@@ -53,6 +53,87 @@ inline specific_intval<0> m_scev_MinusOne() {
5353 return specific_intval<0 >(APInt (64 , -1 ));
5454}
5555
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+
56137} // namespace SCEVPatternMatch
57138} // namespace llvm
58139
0 commit comments