Skip to content

Commit ac5edf5

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 a363bee commit ac5edf5

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
@@ -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

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15393,14 +15393,12 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
1539315393
// (X >=u C1).
1539415394
auto MatchRangeCheckIdiom = [&SE, Predicate, LHS, RHS, &RewriteMap,
1539515395
&ExprsToRewrite]() {
15396-
auto *AddExpr = dyn_cast<SCEVAddExpr>(LHS);
15397-
if (!AddExpr || AddExpr->getNumOperands() != 2)
15398-
return false;
15399-
15400-
auto *C1 = dyn_cast<SCEVConstant>(AddExpr->getOperand(0));
15401-
auto *LHSUnknown = dyn_cast<SCEVUnknown>(AddExpr->getOperand(1));
15396+
const SCEVConstant *C1;
15397+
const SCEVUnknown *LHSUnknown;
1540215398
auto *C2 = dyn_cast<SCEVConstant>(RHS);
15403-
if (!C1 || !C2 || !LHSUnknown)
15399+
if (!match(LHS,
15400+
m_scev_Add(m_SCEVConstant(C1), m_SCEVUnknown(LHSUnknown))) ||
15401+
!C2)
1540415402
return false;
1540515403

1540615404
auto ExactRegion =

0 commit comments

Comments
 (0)