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