LLVM 23.0.0git
ScalarEvolutionPatternMatch.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7//
8// This file provides a simple and efficient mechanism for performing general
9// tree-based pattern matches on SCEVs, based on LLVM's IR pattern matchers.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONPATTERNMATCH_H
14#define LLVM_ANALYSIS_SCALAREVOLUTIONPATTERNMATCH_H
15
17
18namespace llvm {
20
21template <typename Pattern> bool match(const SCEV *S, const Pattern &P) {
22 return P.match(S);
23}
24
25template <typename Predicate> struct cst_pred_ty : public Predicate {
26 cst_pred_ty() = default;
27 cst_pred_ty(uint64_t V) : Predicate(V) {}
28 bool match(const SCEV *S) const {
30 "no vector types expected from SCEVs");
31 auto *C = dyn_cast<SCEVConstant>(S);
32 return C && this->isValue(C->getAPInt());
33 }
34};
35
36struct is_zero {
37 bool isValue(const APInt &C) const { return C.isZero(); }
38};
39
40/// Match an integer 0.
42
43struct is_one {
44 bool isValue(const APInt &C) const { return C.isOne(); }
45};
46
47/// Match an integer 1.
49
51 bool isValue(const APInt &C) const { return C.isAllOnes(); }
52};
53
54/// Match an integer with all bits set.
58
59template <typename Class> struct class_match {
60 template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
61};
62
70
71template <typename Class> struct bind_ty {
72 Class *&VR;
73
74 bind_ty(Class *&V) : VR(V) {}
75
76 template <typename ITy> bool match(ITy *V) const {
77 if (auto *CV = dyn_cast<Class>(V)) {
78 VR = CV;
79 return true;
80 }
81 return false;
82 }
83};
84
85/// Match a SCEV, capturing it if we match.
86inline bind_ty<const SCEV> m_SCEV(const SCEV *&V) { return V; }
88 return V;
89}
91 return V;
92}
93
95 return V;
96}
97
99 return V;
100}
101
102/// Match a specified const SCEV *.
104 const SCEV *Expr;
105
107
108 template <typename ITy> bool match(ITy *S) const { return S == Expr; }
109};
110
111/// Match if we have a specific specified SCEV.
112inline specificscev_ty m_scev_Specific(const SCEV *S) { return S; }
113
117 bool isValue(const APInt &C) const { return C == CV; }
118};
119
120/// Match an SCEV constant with a plain unsigned integer.
122
124 int64_t CV;
126 bool isValue(const APInt &C) const { return C.trySExtValue() == CV; }
127};
128
129/// Match an SCEV constant with a plain signed integer (sign-extended value will
130/// be matched)
132 return V;
133}
134
136 const APInt *&CR;
137
138 bind_cst_ty(const APInt *&Op0) : CR(Op0) {}
139
140 bool match(const SCEV *S) const {
142 "no vector types expected from SCEVs");
143 auto *C = dyn_cast<SCEVConstant>(S);
144 if (!C)
145 return false;
146 CR = &C->getAPInt();
147 return true;
148 }
149};
150
151/// Match an SCEV constant and bind it to an APInt.
152inline bind_cst_ty m_scev_APInt(const APInt *&C) { return C; }
153
154/// Match a unary SCEV.
155template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
156 Op0_t Op0;
157
159
160 bool match(const SCEV *S) const {
161 auto *E = dyn_cast<SCEVTy>(S);
162 return E && E->getNumOperands() == 1 && Op0.match(E->getOperand(0));
163 }
164};
165
166template <typename SCEVTy, typename Op0_t>
170
171template <typename Op0_t>
172inline SCEVUnaryExpr_match<SCEVSignExtendExpr, Op0_t>
173m_scev_SExt(const Op0_t &Op0) {
175}
176
177template <typename Op0_t>
178inline SCEVUnaryExpr_match<SCEVZeroExtendExpr, Op0_t>
179m_scev_ZExt(const Op0_t &Op0) {
181}
182
183template <typename Op0_t>
184inline SCEVUnaryExpr_match<SCEVPtrToIntExpr, Op0_t>
185m_scev_PtrToInt(const Op0_t &Op0) {
187}
188
189template <typename Op0_t>
190inline SCEVUnaryExpr_match<SCEVPtrToAddrExpr, Op0_t>
191m_scev_PtrToAddr(const Op0_t &Op0) {
193}
194
195template <typename Op0_t>
196inline SCEVUnaryExpr_match<SCEVTruncateExpr, Op0_t>
197m_scev_Trunc(const Op0_t &Op0) {
199}
200
201/// Match a binary SCEV.
202template <typename SCEVTy, typename Op0_t, typename Op1_t,
204 bool Commutable = false>
206 Op0_t Op0;
208
210
211 bool match(const SCEV *S) const {
212 if (auto WrappingS = dyn_cast<SCEVNAryExpr>(S))
213 if (WrappingS->getNoWrapFlags(WrapFlags) != WrapFlags)
214 return false;
215
216 auto *E = dyn_cast<SCEVTy>(S);
217 return E && E->getNumOperands() == 2 &&
218 ((Op0.match(E->getOperand(0)) && Op1.match(E->getOperand(1))) ||
219 (Commutable && Op0.match(E->getOperand(1)) &&
220 Op1.match(E->getOperand(0))));
221 }
222};
223
224template <typename SCEVTy, typename Op0_t, typename Op1_t,
226 bool Commutable = false>
227inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>
228m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
230 Op1);
231}
232
233template <typename Op0_t, typename Op1_t>
234inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t>
235m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
236 return m_scev_Binary<SCEVAddExpr>(Op0, Op1);
237}
238
239template <typename Op0_t, typename Op1_t>
240inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t>
241m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
242 return m_scev_Binary<SCEVMulExpr>(Op0, Op1);
243}
244
245template <typename Op0_t, typename Op1_t>
246inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true>
247m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
249 Op1);
250}
251
252template <typename Op0_t, typename Op1_t>
253inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>
254m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1) {
256 Op1);
257}
258
259template <typename Op0_t, typename Op1_t>
260inline SCEVBinaryExpr_match<SCEVUDivExpr, Op0_t, Op1_t>
261m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1) {
262 return m_scev_Binary<SCEVUDivExpr>(Op0, Op1);
263}
264
265template <typename Op0_t, typename Op1_t>
266inline SCEVBinaryExpr_match<SCEVSMaxExpr, Op0_t, Op1_t>
267m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1) {
268 return m_scev_Binary<SCEVSMaxExpr>(Op0, Op1);
269}
270
271template <typename Op0_t, typename Op1_t>
272inline SCEVBinaryExpr_match<SCEVMinMaxExpr, Op0_t, Op1_t>
273m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1) {
274 return m_scev_Binary<SCEVMinMaxExpr>(Op0, Op1);
275}
276
277/// Match unsigned remainder pattern.
278/// Matches patterns generated by getURemExpr.
279template <typename Op0_t, typename Op1_t> struct SCEVURem_match {
280 Op0_t Op0;
283
286
287 bool match(const SCEV *Expr) const {
288 if (Expr->getType()->isPointerTy())
289 return false;
290
291 // Try to match 'zext (trunc A to iB) to iY', which is used
292 // for URem with constant power-of-2 second operands. Make sure the size of
293 // the operand A matches the size of the whole expressions.
294 const SCEV *LHS;
296 Type *TruncTy = cast<SCEVZeroExtendExpr>(Expr)->getOperand()->getType();
297 // Bail out if the type of the LHS is larger than the type of the
298 // expression for now.
299 if (SE.getTypeSizeInBits(LHS->getType()) >
300 SE.getTypeSizeInBits(Expr->getType()))
301 return false;
302 if (LHS->getType() != Expr->getType())
303 LHS = SE.getZeroExtendExpr(LHS, Expr->getType());
304 const SCEV *RHS =
305 SE.getConstant(APInt(SE.getTypeSizeInBits(Expr->getType()), 1)
306 << SE.getTypeSizeInBits(TruncTy));
307 return Op0.match(LHS) && Op1.match(RHS);
308 }
309
310 const SCEV *A;
311 const SCEVMulExpr *Mul;
313 return false;
314
315 const auto MatchURemWithDivisor = [&](const SCEV *B) {
316 // (SomeExpr + (-(SomeExpr / B) * B)).
317 if (Expr == SE.getURemExpr(A, B))
318 return Op0.match(A) && Op1.match(B);
319 return false;
320 };
321
322 // (SomeExpr + (-1 * (SomeExpr / B) * B)).
323 if (Mul->getNumOperands() == 3 && isa<SCEVConstant>(Mul->getOperand(0)))
324 return MatchURemWithDivisor(Mul->getOperand(1)) ||
325 MatchURemWithDivisor(Mul->getOperand(2));
326
327 // (SomeExpr + ((-SomeExpr / B) * B)) or (SomeExpr + ((SomeExpr / B) * -B)).
328 if (Mul->getNumOperands() == 2)
329 return MatchURemWithDivisor(Mul->getOperand(1)) ||
330 MatchURemWithDivisor(Mul->getOperand(0)) ||
331 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(1))) ||
332 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(0)));
333 return false;
334 }
335};
336
337/// Match the mathematical pattern A - (A / B) * B, where A and B can be
338/// arbitrary expressions. Also match zext (trunc A to iB) to iY, which is used
339/// for URem with constant power-of-2 second operands. It's not always easy, as
340/// A and B can be folded (imagine A is X / 2, and B is 4, A / B becomes X / 8).
341template <typename Op0_t, typename Op1_t>
346
348
349/// Match an affine SCEVAddRecExpr.
350template <typename Op0_t, typename Op1_t, typename Loop_t>
353 Loop_t Loop;
354
355 SCEVAffineAddRec_match(Op0_t Op0, Op1_t Op1, Loop_t Loop)
356 : Ops(Op0, Op1), Loop(Loop) {}
357
358 bool match(const SCEV *S) const {
359 return Ops.match(S) && Loop.match(cast<SCEVAddRecExpr>(S)->getLoop());
360 }
361};
362
363/// Match a specified const Loop*.
365 const Loop *L;
366
367 specificloop_ty(const Loop *L) : L(L) {}
368
369 bool match(const Loop *L) const { return L == this->L; }
370};
371
372inline specificloop_ty m_SpecificLoop(const Loop *L) { return L; }
373
374inline bind_ty<const Loop> m_Loop(const Loop *&L) { return L; }
375
376template <typename Op0_t, typename Op1_t>
377inline SCEVAffineAddRec_match<Op0_t, Op1_t, class_match<const Loop>>
378m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1) {
380 Op0, Op1, m_Loop());
381}
382
383template <typename Op0_t, typename Op1_t, typename Loop_t>
384inline SCEVAffineAddRec_match<Op0_t, Op1_t, Loop_t>
385m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1, const Loop_t &L) {
387}
388
390 bool match(const SCEV *S) const {
391 const SCEVUnknown *Unknown;
393 isa<UndefValue>(Unknown->getValue());
394 }
395};
396
397/// Match an SCEVUnknown wrapping undef or poison.
401
402} // namespace SCEVPatternMatch
403} // namespace llvm
404
405#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define P(N)
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
This node represents an addition of some number of SCEVs.
This class represents a constant integer value.
This node represents multiplication of some number of SCEVs.
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
NoWrapFlags
NoWrapFlags are bitfield indices into SubclassData.
The main scalar evolution driver.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:273
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:267
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
cstval_pred_ty< Predicate, ConstantInt, AllowPoison > cst_pred_ty
specialization of cstval_pred_ty for ConstantInt
class_match< const SCEVVScale > m_SCEVVScale()
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
cst_pred_ty< is_all_ones > m_scev_AllOnes()
Match an integer with all bits set.
SCEVUnaryExpr_match< SCEVZeroExtendExpr, Op0_t > m_scev_ZExt(const Op0_t &Op0)
is_undef_or_poison m_scev_UndefOrPoison()
Match an SCEVUnknown wrapping undef or poison.
SCEVBinaryExpr_match< SCEVMinMaxExpr, Op0_t, Op1_t > m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1)
class_match< const SCEVConstant > m_SCEVConstant()
cst_pred_ty< is_one > m_scev_One()
Match an integer 1.
specificloop_ty m_SpecificLoop(const Loop *L)
cst_pred_ty< is_specific_signed_cst > m_scev_SpecificSInt(int64_t V)
Match an SCEV constant with a plain signed integer (sign-extended value will be matched)
SCEVBinaryExpr_match< SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable > m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1)
SCEVAffineAddRec_match< Op0_t, Op1_t, class_match< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
bind_ty< const SCEVMulExpr > m_scev_Mul(const SCEVMulExpr *&V)
SCEVUnaryExpr_match< SCEVTy, Op0_t > m_scev_Unary(const Op0_t &Op0)
SCEVUnaryExpr_match< SCEVSignExtendExpr, Op0_t > m_scev_SExt(const Op0_t &Op0)
SCEVUnaryExpr_match< SCEVPtrToAddrExpr, Op0_t > m_scev_PtrToAddr(const Op0_t &Op0)
cst_pred_ty< is_zero > m_scev_Zero()
Match an integer 0.
SCEVUnaryExpr_match< SCEVTruncateExpr, Op0_t > m_scev_Trunc(const Op0_t &Op0)
bool match(const SCEV *S, const Pattern &P)
SCEVBinaryExpr_match< SCEVUDivExpr, Op0_t, Op1_t > m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1)
specificscev_ty m_scev_Specific(const SCEV *S)
Match if we have a specific specified SCEV.
SCEVBinaryExpr_match< SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true > m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1)
class_match< const Loop > m_Loop()
bind_ty< const SCEVAddExpr > m_scev_Add(const SCEVAddExpr *&V)
SCEVUnaryExpr_match< SCEVPtrToIntExpr, Op0_t > m_scev_PtrToInt(const Op0_t &Op0)
bind_ty< const SCEVUnknown > m_SCEVUnknown(const SCEVUnknown *&V)
cst_pred_ty< is_specific_cst > m_scev_SpecificInt(uint64_t V)
Match an SCEV constant with a plain unsigned integer.
SCEVBinaryExpr_match< SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true > m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1)
SCEVBinaryExpr_match< SCEVSMaxExpr, Op0_t, Op1_t > m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1)
SCEVURem_match< Op0_t, Op1_t > m_scev_URem(Op0_t LHS, Op1_t RHS, ScalarEvolution &SE)
Match the mathematical pattern A - (A / B) * B, where A and B can be arbitrary expressions.
class_match< const SCEV > m_SCEV()
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Mul
Product of integers.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
SCEVBinaryExpr_match< SCEVAddRecExpr, Op0_t, Op1_t > Ops
SCEVURem_match(Op0_t Op0, Op1_t Op1, ScalarEvolution &SE)