@@ -53,6 +53,87 @@ inline specific_intval<0> m_scev_MinusOne() {
53
53
return specific_intval<0 >(APInt (64 , -1 ));
54
54
}
55
55
56
+ template <typename Class> struct class_match {
57
+ template <typename ITy> bool match (ITy *V) const { return isa<Class>(V); }
58
+ };
59
+
60
+ template <typename Class> struct bind_ty {
61
+ Class *&VR;
62
+
63
+ bind_ty (Class *&V) : VR(V) {}
64
+
65
+ template <typename ITy> bool match (ITy *V) const {
66
+ if (auto *CV = dyn_cast<Class>(V)) {
67
+ VR = CV;
68
+ return true ;
69
+ }
70
+ return false ;
71
+ }
72
+ };
73
+
74
+ // / Match a SCEV, capturing it if we match.
75
+ inline bind_ty<const SCEV> m_SCEV (const SCEV *&V) { return V; }
76
+ inline bind_ty<const SCEVConstant> m_SCEVConstant (const SCEVConstant *&V) {
77
+ return V;
78
+ }
79
+ inline bind_ty<const SCEVUnknown> m_SCEVUnknown (const SCEVUnknown *&V) {
80
+ return V;
81
+ }
82
+
83
+ namespace detail {
84
+
85
+ template <typename TupleTy, typename Fn, std::size_t ... Is>
86
+ bool CheckTupleElements (const TupleTy &Ops, Fn P, std::index_sequence<Is...>) {
87
+ return (P (std::get<Is>(Ops), Is) && ...);
88
+ }
89
+
90
+ // / Helper to check if predicate \p P holds on all tuple elements in \p Ops
91
+ template <typename TupleTy, typename Fn>
92
+ bool all_of_tuple_elements (const TupleTy &Ops, Fn P) {
93
+ return CheckTupleElements (
94
+ Ops, P, std::make_index_sequence<std::tuple_size<TupleTy>::value>{});
95
+ }
96
+
97
+ } // namespace detail
98
+
99
+ template <typename Ops_t, typename SCEVTy> struct SCEV_match {
100
+ Ops_t Ops;
101
+
102
+ SCEV_match () : Ops() {
103
+ static_assert (std::tuple_size<Ops_t>::value == 0 &&
104
+ " constructor can only be used with zero operands" );
105
+ }
106
+ SCEV_match (Ops_t Ops) : Ops(Ops) {}
107
+ template <typename A_t, typename B_t> SCEV_match (A_t A, B_t B) : Ops({A, B}) {
108
+ static_assert (std::tuple_size<Ops_t>::value == 2 &&
109
+ " constructor can only be used for binary matcher" );
110
+ }
111
+
112
+ bool match (const SCEV *S) const {
113
+ auto *Cast = dyn_cast<SCEVTy>(S);
114
+ if (!Cast || Cast->getNumOperands () != std::tuple_size<Ops_t>::value)
115
+ return false ;
116
+ return detail::all_of_tuple_elements (Ops, [Cast](auto Op, unsigned Idx) {
117
+ return Op.match (Cast->getOperand (Idx));
118
+ });
119
+ }
120
+ };
121
+
122
+ template <typename Op0_t, typename Op1_t, typename SCEVTy>
123
+ using BinarySCEV_match = SCEV_match<std::tuple<Op0_t, Op1_t>, SCEVTy>;
124
+
125
+ template <typename Op0_t, typename Op1_t, typename SCEVTy>
126
+ inline BinarySCEV_match<Op0_t, Op1_t, SCEVTy> m_scev_Binary (const Op0_t &Op0,
127
+ const Op1_t &Op1) {
128
+ return BinarySCEV_match<Op0_t, Op1_t, SCEVTy>(Op0, Op1);
129
+ }
130
+
131
+ template <typename Op0_t, typename Op1_t>
132
+ inline BinarySCEV_match<Op0_t, Op1_t, SCEVAddExpr>
133
+ m_scev_Add (const Op0_t &Op0, const Op1_t &Op1) {
134
+ return BinarySCEV_match<Op0_t, Op1_t, SCEVAddExpr>(Op0, Op1);
135
+ }
136
+
56
137
} // namespace SCEVPatternMatch
57
138
} // namespace llvm
58
139
0 commit comments