LLVM 24.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
19
20namespace llvm {
22template <typename SCEVPtrT> struct match_bind<SCEVUseT<SCEVPtrT>> {
24
26
27 template <typename ITy> bool match(ITy *V) const {
28 VR = V;
29 return true;
30 }
31};
32} // namespace PatternMatchHelpers
33
35
36using namespace llvm::PatternMatchHelpers;
37
38template <typename Pattern> bool match(const SCEV *S, const Pattern &P) {
39 return P.match(S);
40}
41
42template <typename SCEVPtrT, typename Pattern>
43bool match(const SCEVUseT<SCEVPtrT> U, const Pattern &P) {
44 return P.match(U.getPointer());
45}
46
47template <typename Predicate> struct cst_pred_ty : public Predicate {
48 cst_pred_ty() = default;
49 cst_pred_ty(uint64_t V) : Predicate(V) {}
50 bool match(const SCEV *S) const {
52 "no vector types expected from SCEVs");
53 auto *C = dyn_cast<SCEVConstant>(S);
54 return C && this->isValue(C->getAPInt());
55 }
56};
57
58struct is_zero {
59 bool isValue(const APInt &C) const { return C.isZero(); }
60};
61
62/// Match an integer 0.
64
65struct is_one {
66 bool isValue(const APInt &C) const { return C.isOne(); }
67};
68
69/// Match an integer 1.
71
73 bool isValue(const APInt &C) const { return C.isAllOnes(); }
74};
75
76/// Match an integer with all bits set.
80
81inline auto m_SCEV() { return m_Isa<const SCEV>(); }
82inline auto m_SCEVConstant() { return m_Isa<const SCEVConstant>(); }
83inline auto m_SCEVVScale() { return m_Isa<const SCEVVScale>(); }
84
85/// Match a SCEV, capturing it if we match.
86inline match_bind<const SCEV> m_SCEV(const SCEV *&V) { return V; }
87
88template <typename SCEVPtrT>
93 return V;
94}
96 return V;
97}
98
100 return V;
101}
102
104 return V;
105}
106
107/// Match a specified const SCEV *.
109 const SCEV *Expr;
110
112
113 template <typename ITy> bool match(ITy *S) const { return S == Expr; }
114};
115
116/// Match if we have a specific specified SCEV.
117inline specificscev_ty m_scev_Specific(const SCEV *S) { return S; }
118
122 bool isValue(const APInt &C) const { return C == CV; }
123};
124
125/// Match an SCEV constant with a plain unsigned integer.
127
129 int64_t CV;
131 bool isValue(const APInt &C) const { return C.trySExtValue() == CV; }
132};
133
134/// Match an SCEV constant with a plain signed integer (sign-extended value will
135/// be matched)
137 return V;
138}
139
141 const APInt *&CR;
142
143 bind_cst_ty(const APInt *&Op0) : CR(Op0) {}
144
145 bool match(const SCEV *S) const {
147 "no vector types expected from SCEVs");
148 auto *C = dyn_cast<SCEVConstant>(S);
149 if (!C)
150 return false;
151 CR = &C->getAPInt();
152 return true;
153 }
154};
155
156/// Match an SCEV constant and bind it to an APInt.
157inline bind_cst_ty m_scev_APInt(const APInt *&C) { return C; }
158
159/// Match a unary SCEV.
160template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
162
164
165 bool match(const SCEV *S) const {
166 auto *E = dyn_cast<SCEVTy>(S);
167 return E && E->getNumOperands() == 1 &&
168 Op0.match(E->getOperand(0).getPointer());
169 }
170};
171
172template <typename SCEVTy, typename Op0_t>
176
177template <typename Op0_t>
178inline SCEVUnaryExpr_match<SCEVSignExtendExpr, Op0_t>
179m_scev_SExt(const Op0_t &Op0) {
181}
182
183template <typename Op0_t>
184inline SCEVUnaryExpr_match<SCEVZeroExtendExpr, Op0_t>
185m_scev_ZExt(const Op0_t &Op0) {
187}
188
189template <typename Op0_t>
190inline SCEVUnaryExpr_match<SCEVPtrToAddrExpr, Op0_t>
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,
203 SCEVFlags WrapFlags = SCEV::FlagNone, bool Commutable = false>
207
209
210 bool match(const SCEV *S) const {
211 if (auto WrappingS = dyn_cast<SCEVNAryExpr>(S))
212 if (WrappingS->getNoWrapFlags(WrapFlags) != WrapFlags)
213 return false;
214
215 auto *E = dyn_cast<SCEVTy>(S);
216 return E && E->getNumOperands() == 2 &&
217 ((Op0.match(E->getOperand(0).getPointer()) &&
218 Op1.match(E->getOperand(1).getPointer())) ||
219 (Commutable && Op0.match(E->getOperand(1).getPointer()) &&
220 Op1.match(E->getOperand(0).getPointer())));
221 }
222};
223
224template <typename SCEVTy, typename Op0_t, typename Op1_t,
225 SCEVFlags WrapFlags = SCEV::FlagNone, bool Commutable = false>
226inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>
231
232template <typename Op0_t, typename Op1_t>
233inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t>
234m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
235 return m_scev_Binary<SCEVAddExpr>(Op0, Op1);
236}
237
238template <typename Op0_t, typename Op1_t>
239inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t, SCEV::FlagNSW>
240m_scev_NSWAdd(const Op0_t &Op0, const Op1_t &Op1) {
242}
243
244template <typename Op0_t, typename Op1_t>
245inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t>
246m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
247 return m_scev_Binary<SCEVMulExpr>(Op0, Op1);
248}
249
250template <typename Op0_t, typename Op1_t>
251inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNone, true>
252m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
254 Op1);
255}
256
257template <typename Op0_t, typename Op1_t>
258inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>
259m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1) {
261 Op1);
262}
263
264template <typename Op0_t, typename Op1_t>
265inline SCEVBinaryExpr_match<SCEVUDivExpr, Op0_t, Op1_t>
266m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1) {
267 return m_scev_Binary<SCEVUDivExpr>(Op0, Op1);
268}
269
270template <typename Op0_t, typename Op1_t>
271inline SCEVBinaryExpr_match<SCEVSMaxExpr, Op0_t, Op1_t, SCEV::FlagNone, true>
272m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1) {
274 Op1);
275}
276
277template <typename Op0_t, typename Op1_t>
278inline SCEVBinaryExpr_match<SCEVUMaxExpr, Op0_t, Op1_t, SCEV::FlagNone, true>
279m_scev_UMax(const Op0_t &Op0, const Op1_t &Op1) {
281 Op1);
282}
283
284template <typename Op0_t, typename Op1_t>
285inline SCEVBinaryExpr_match<SCEVMinMaxExpr, Op0_t, Op1_t>
286m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1) {
287 return m_scev_Binary<SCEVMinMaxExpr>(Op0, Op1);
288}
289
290/// Match unsigned remainder pattern.
291/// Matches patterns generated by getURemExpr.
292template <typename Op0_t, typename Op1_t> struct SCEVURem_match {
296
299
300 bool match(const SCEV *Expr) const {
301 if (Expr->getType()->isPointerTy())
302 return false;
303
304 // Try to match 'zext (trunc A to iB) to iY', which is used
305 // for URem with constant power-of-2 second operands. Make sure the size of
306 // the operand A matches the size of the whole expressions.
307 const SCEV *LHS;
309 Type *TruncTy = cast<SCEVZeroExtendExpr>(Expr)->getOperand()->getType();
310 // Bail out if the type of the LHS is larger than the type of the
311 // expression for now.
312 if (SE.getTypeSizeInBits(LHS->getType()) >
313 SE.getTypeSizeInBits(Expr->getType()))
314 return false;
315 if (LHS->getType() != Expr->getType())
316 LHS = SE.getZeroExtendExpr(LHS, Expr->getType());
317 const SCEV *RHS =
318 SE.getConstant(APInt(SE.getTypeSizeInBits(Expr->getType()), 1)
319 << SE.getTypeSizeInBits(TruncTy));
320 return Op0.match(LHS) && Op1.match(RHS);
321 }
322
323 const SCEV *A;
324 const SCEVMulExpr *Mul;
326 return false;
327
328 // URem is represented as `A - ((A udiv B) * B)`. Only construct the complex
329 // SCEV expression, if the multiply of the expression to check has a UDiv
330 // operand.
331 if (none_of(Mul->operands(),
332 [](const SCEV *Op) { return isa<SCEVUDivExpr>(Op); }))
333 return false;
334
335 const auto MatchURemWithDivisor = [&](const SCEV *B) {
336 // (SomeExpr + (-(SomeExpr / B) * B)).
337 if (Expr == SE.getURemExpr(A, B))
338 return Op0.match(A) && Op1.match(B);
339 return false;
340 };
341
342 // (SomeExpr + (-1 * (SomeExpr / B) * B)).
343 if (Mul->getNumOperands() == 3 && isa<SCEVConstant>(Mul->getOperand(0)))
344 return MatchURemWithDivisor(Mul->getOperand(1)) ||
345 MatchURemWithDivisor(Mul->getOperand(2));
346
347 // (SomeExpr + ((-SomeExpr / B) * B)) or (SomeExpr + ((SomeExpr / B) * -B)).
348 if (Mul->getNumOperands() == 2)
349 return MatchURemWithDivisor(Mul->getOperand(1)) ||
350 MatchURemWithDivisor(Mul->getOperand(0)) ||
351 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(1))) ||
352 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(0)));
353 return false;
354 }
355};
356
357/// Match the mathematical pattern A - (A / B) * B, where A and B can be
358/// arbitrary expressions. Also match zext (trunc A to iB) to iY, which is used
359/// for URem with constant power-of-2 second operands. It's not always easy, as
360/// A and B can be folded (imagine A is X / 2, and B is 4, A / B becomes X / 8).
361template <typename Op0_t, typename Op1_t>
366
367inline auto m_Loop() { return m_Isa<const Loop>(); }
368
369/// Match an affine SCEVAddRecExpr.
370template <typename Op0_t, typename Op1_t, typename Loop_t>
373 Loop_t Loop;
374
376 : Ops(Op0, Op1), Loop(Loop) {}
377
378 bool match(const SCEV *S) const {
379 return Ops.match(S) && Loop.match(cast<SCEVAddRecExpr>(S)->getLoop());
380 }
381};
382
383/// Match a specified const Loop*.
385 const Loop *L;
386
387 specificloop_ty(const Loop *L) : L(L) {}
388
389 bool match(const Loop *L) const { return L == this->L; }
390};
391
392inline specificloop_ty m_SpecificLoop(const Loop *L) { return L; }
393
394inline match_bind<const Loop> m_Loop(const Loop *&L) { return L; }
395
396template <typename Op0_t, typename Op1_t>
397inline SCEVAffineAddRec_match<Op0_t, Op1_t, match_isa<const Loop>>
398m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1) {
400 m_Loop());
401}
402
403template <typename Op0_t, typename Op1_t, typename Loop_t>
404inline SCEVAffineAddRec_match<Op0_t, Op1_t, Loop_t>
405m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1, const Loop_t &L) {
407}
408
410 bool match(const SCEV *S) const {
411 const SCEVUnknown *Unknown;
413 isa<UndefValue>(Unknown->getValue());
414 }
415};
416
417/// Match an SCEVUnknown wrapping undef or poison.
421
422} // namespace SCEVPatternMatch
423} // namespace llvm
424
425#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
Type * getType() const
Return the LLVM type of this SCEV expression.
static constexpr auto FlagNone
The main scalar evolution driver.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
cstval_pred_ty< Predicate, ConstantInt, AllowPoison > cst_pred_ty
specialization of cstval_pred_ty for ConstantInt
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)
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)
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)
match_bind< const SCEVMulExpr > m_scev_Mul(const SCEVMulExpr *&V)
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)
SCEVBinaryExpr_match< SCEVAddExpr, Op0_t, Op1_t, SCEV::FlagNSW > m_scev_NSWAdd(const Op0_t &Op0, const Op1_t &Op1)
specificscev_ty m_scev_Specific(const SCEV *S)
Match if we have a specific specified SCEV.
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
match_bind< const SCEVUnknown > m_SCEVUnknown(const SCEVUnknown *&V)
SCEVBinaryExpr_match< SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true > m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1)
SCEVBinaryExpr_match< SCEVUMaxExpr, Op0_t, Op1_t, SCEV::FlagNone, true > m_scev_UMax(const Op0_t &Op0, const Op1_t &Op1)
SCEVBinaryExpr_match< SCEVSMaxExpr, Op0_t, Op1_t, SCEV::FlagNone, true > m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1)
SCEVBinaryExpr_match< SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNone, true > m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1)
match_bind< const SCEVAddExpr > m_scev_Add(const SCEVAddExpr *&V)
cst_pred_ty< is_specific_cst > m_scev_SpecificInt(uint64_t V)
Match an SCEV constant with a plain unsigned integer.
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.
This is an optimization pass for GlobalISel generic memory operations.
@ Unknown
Not known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
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.
DWARFExpression::Operation Op
SCEVFlags
SCEVFlags are bitfield indices into SCEV's SubclassData.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Matcher to bind the captured value.
SCEVBinaryExpr_match< SCEVAddRecExpr, Op0_t, Op1_t > Ops
SCEVURem_match(Op0_t Op0, Op1_t Op1, ScalarEvolution &SE)