Skip to content

Commit ecaa67e

Browse files
committed
[SCEV] Add initial matchers for SCEV expressions. (NFC)
This patch adds initial matchers for SCEV expressions with an arbitrary number of operands and specializes it for binary add expressions. Also adds matchers for SCEVConstant and SCEVUnknown. This patch only converts a few instances to use the new matchers to make sure everything builds as expected for now. Depends on llvm#119389
1 parent 7163603 commit ecaa67e

File tree

2 files changed

+86
-7
lines changed

2 files changed

+86
-7
lines changed

llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15381,14 +15381,12 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
1538115381
// (X >=u C1).
1538215382
auto MatchRangeCheckIdiom = [&SE, Predicate, LHS, RHS, &RewriteMap,
1538315383
&ExprsToRewrite]() {
15384-
auto *AddExpr = dyn_cast<SCEVAddExpr>(LHS);
15385-
if (!AddExpr || AddExpr->getNumOperands() != 2)
15386-
return false;
15387-
15388-
auto *C1 = dyn_cast<SCEVConstant>(AddExpr->getOperand(0));
15389-
auto *LHSUnknown = dyn_cast<SCEVUnknown>(AddExpr->getOperand(1));
15384+
const SCEVConstant *C1;
15385+
const SCEVUnknown *LHSUnknown;
1539015386
auto *C2 = dyn_cast<SCEVConstant>(RHS);
15391-
if (!C1 || !C2 || !LHSUnknown)
15387+
if (!match(LHS,
15388+
m_scev_Add(m_SCEVConstant(C1), m_SCEVUnknown(LHSUnknown))) ||
15389+
!C2)
1539215390
return false;
1539315391

1539415392
auto ExactRegion =

0 commit comments

Comments
 (0)