@@ -52,6 +52,87 @@ inline cst_pred_ty<is_all_ones> m_scev_AllOnes() {
5252 return cst_pred_ty<is_all_ones>();
5353}
5454
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+
55136} // namespace SCEVPatternMatch
56137} // namespace llvm
57138
0 commit comments