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
18
19namespace llvm {
21
22template <typename Pattern> bool match(const SCEV *S, const Pattern &P) {
23 return P.match(S);
24}
25
26template <typename Pattern> bool match(const SCEVUse U, const Pattern &P) {
27 return P.match(U.getPointer());
28}
29
30template <typename Predicate> struct cst_pred_ty : public Predicate {
31 cst_pred_ty() = default;
32 cst_pred_ty(uint64_t V) : Predicate(V) {}
33 bool match(const SCEV *S) const {
35 "no vector types expected from SCEVs");
36 auto *C = dyn_cast<SCEVConstant>(S);
37 return C && this->isValue(C->getAPInt());
38 }
39};
40
41struct is_zero {
42 bool isValue(const APInt &C) const { return C.isZero(); }
43};
44
45/// Match an integer 0.
47
48struct is_one {
49 bool isValue(const APInt &C) const { return C.isOne(); }
50};
51
52/// Match an integer 1.
54
56 bool isValue(const APInt &C) const { return C.isAllOnes(); }
57};
58
59/// Match an integer with all bits set.
63
64template <typename Class> struct class_match {
65 template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
66};
67
75
76template <typename Class> struct bind_ty {
77 Class *&VR;
78
79 bind_ty(Class *&V) : VR(V) {}
80
81 template <typename ITy> bool match(ITy *V) const {
82 if (auto *CV = dyn_cast<Class>(V)) {
83 VR = CV;
84 return true;
85 }
86 return false;
87 }
88};
89
90template <> struct bind_ty<SCEVUse> {
92
93 bind_ty(SCEVUse &V) : VR(V) {}
94
95 template <typename ITy> bool match(ITy *V) const {
96 VR = V;
97 return true;
98 }
99};
100
101/// Match a SCEV, capturing it if we match.
102inline bind_ty<const SCEV> m_SCEV(const SCEV *&V) { return V; }
103inline bind_ty<SCEVUse> m_SCEV(SCEVUse &V) { return V; }
105 return V;
106}
108 return V;
109}
110
112 return V;
113}
114
116 return V;
117}
118
119/// Match a specified const SCEV *.
121 const SCEV *Expr;
122
124
125 template <typename ITy> bool match(ITy *S) const { return S == Expr; }
126};
127
128/// Match if we have a specific specified SCEV.
129inline specificscev_ty m_scev_Specific(const SCEV *S) { return S; }
130
134 bool isValue(const APInt &C) const { return C == CV; }
135};
136
137/// Match an SCEV constant with a plain unsigned integer.
139
141 int64_t CV;
143 bool isValue(const APInt &C) const { return C.trySExtValue() == CV; }
144};
145
146/// Match an SCEV constant with a plain signed integer (sign-extended value will
147/// be matched)
149 return V;
150}
151
153 const APInt *&CR;
154
155 bind_cst_ty(const APInt *&Op0) : CR(Op0) {}
156
157 bool match(const SCEV *S) const {
159 "no vector types expected from SCEVs");
160 auto *C = dyn_cast<SCEVConstant>(S);
161 if (!C)
162 return false;
163 CR = &C->getAPInt();
164 return true;
165 }
166};
167
168/// Match an SCEV constant and bind it to an APInt.
169inline bind_cst_ty m_scev_APInt(const APInt *&C) { return C; }
170
171/// Match a unary SCEV.
172template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
173 Op0_t Op0;
174
176
177 bool match(const SCEV *S) const {
178 auto *E = dyn_cast<SCEVTy>(S);
179 return E && E->getNumOperands() == 1 &&
180 Op0.match(E->getOperand(0).getPointer());
181 }
182};
183
184template <typename SCEVTy, typename Op0_t>
188
189template <typename Op0_t>
190inline SCEVUnaryExpr_match<SCEVSignExtendExpr, Op0_t>
191m_scev_SExt(const Op0_t &Op0) {
193}
194
195template <typename Op0_t>
196inline SCEVUnaryExpr_match<SCEVZeroExtendExpr, Op0_t>
197m_scev_ZExt(const Op0_t &Op0) {
199}
200
201template <typename Op0_t>
202inline SCEVUnaryExpr_match<SCEVPtrToIntExpr, Op0_t>
203m_scev_PtrToInt(const Op0_t &Op0) {
205}
206
207template <typename Op0_t>
208inline SCEVUnaryExpr_match<SCEVPtrToAddrExpr, Op0_t>
209m_scev_PtrToAddr(const Op0_t &Op0) {
211}
212
213template <typename Op0_t>
214inline SCEVUnaryExpr_match<SCEVTruncateExpr, Op0_t>
215m_scev_Trunc(const Op0_t &Op0) {
217}
218
219/// Match a binary SCEV.
220template <typename SCEVTy, typename Op0_t, typename Op1_t,
222 bool Commutable = false>
224 Op0_t Op0;
226
228
229 bool match(const SCEV *S) const {
230 if (auto WrappingS = dyn_cast<SCEVNAryExpr>(S))
231 if (WrappingS->getNoWrapFlags(WrapFlags) != WrapFlags)
232 return false;
233
234 auto *E = dyn_cast<SCEVTy>(S);
235 return E && E->getNumOperands() == 2 &&
236 ((Op0.match(E->getOperand(0).getPointer()) &&
237 Op1.match(E->getOperand(1).getPointer())) ||
238 (Commutable && Op0.match(E->getOperand(1).getPointer()) &&
239 Op1.match(E->getOperand(0).getPointer())));
240 }
241};
242
243template <typename SCEVTy, typename Op0_t, typename Op1_t,
245 bool Commutable = false>
246inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>
247m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
249 Op1);
250}
251
252template <typename Op0_t, typename Op1_t>
253inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t>
254m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
255 return m_scev_Binary<SCEVAddExpr>(Op0, Op1);
256}
257
258template <typename Op0_t, typename Op1_t>
259inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t>
260m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
261 return m_scev_Binary<SCEVMulExpr>(Op0, Op1);
262}
263
264template <typename Op0_t, typename Op1_t>
265inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true>
266m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
268 Op1);
269}
270
271template <typename Op0_t, typename Op1_t>
272inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>
273m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1) {
275 Op1);
276}
277
278template <typename Op0_t, typename Op1_t>
279inline SCEVBinaryExpr_match<SCEVUDivExpr, Op0_t, Op1_t>
280m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1) {
281 return m_scev_Binary<SCEVUDivExpr>(Op0, Op1);
282}
283
284template <typename Op0_t, typename Op1_t>
285inline SCEVBinaryExpr_match<SCEVSMaxExpr, Op0_t, Op1_t>
286m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1) {
287 return m_scev_Binary<SCEVSMaxExpr>(Op0, Op1);
288}
289
290template <typename Op0_t, typename Op1_t>
291inline SCEVBinaryExpr_match<SCEVMinMaxExpr, Op0_t, Op1_t>
292m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1) {
293 return m_scev_Binary<SCEVMinMaxExpr>(Op0, Op1);
294}
295
296/// Match unsigned remainder pattern.
297/// Matches patterns generated by getURemExpr.
298template <typename Op0_t, typename Op1_t> struct SCEVURem_match {
299 Op0_t Op0;
302
305
306 bool match(const SCEV *Expr) const {
307 if (Expr->getType()->isPointerTy())
308 return false;
309
310 // Try to match 'zext (trunc A to iB) to iY', which is used
311 // for URem with constant power-of-2 second operands. Make sure the size of
312 // the operand A matches the size of the whole expressions.
313 const SCEV *LHS;
315 Type *TruncTy = cast<SCEVZeroExtendExpr>(Expr)->getOperand()->getType();
316 // Bail out if the type of the LHS is larger than the type of the
317 // expression for now.
318 if (SE.getTypeSizeInBits(LHS->getType()) >
319 SE.getTypeSizeInBits(Expr->getType()))
320 return false;
321 if (LHS->getType() != Expr->getType())
322 LHS = SE.getZeroExtendExpr(LHS, Expr->getType());
323 const SCEV *RHS =
324 SE.getConstant(APInt(SE.getTypeSizeInBits(Expr->getType()), 1)
325 << SE.getTypeSizeInBits(TruncTy));
326 return Op0.match(LHS) && Op1.match(RHS);
327 }
328
329 const SCEV *A;
330 const SCEVMulExpr *Mul;
332 return false;
333
334 const auto MatchURemWithDivisor = [&](const SCEV *B) {
335 // (SomeExpr + (-(SomeExpr / B) * B)).
336 if (Expr == SE.getURemExpr(A, B))
337 return Op0.match(A) && Op1.match(B);
338 return false;
339 };
340
341 // (SomeExpr + (-1 * (SomeExpr / B) * B)).
342 if (Mul->getNumOperands() == 3 && isa<SCEVConstant>(Mul->getOperand(0)))
343 return MatchURemWithDivisor(Mul->getOperand(1)) ||
344 MatchURemWithDivisor(Mul->getOperand(2));
345
346 // (SomeExpr + ((-SomeExpr / B) * B)) or (SomeExpr + ((SomeExpr / B) * -B)).
347 if (Mul->getNumOperands() == 2)
348 return MatchURemWithDivisor(Mul->getOperand(1)) ||
349 MatchURemWithDivisor(Mul->getOperand(0)) ||
350 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(1))) ||
351 MatchURemWithDivisor(SE.getNegativeSCEV(Mul->getOperand(0)));
352 return false;
353 }
354};
355
356/// Match the mathematical pattern A - (A / B) * B, where A and B can be
357/// arbitrary expressions. Also match zext (trunc A to iB) to iY, which is used
358/// for URem with constant power-of-2 second operands. It's not always easy, as
359/// A and B can be folded (imagine A is X / 2, and B is 4, A / B becomes X / 8).
360template <typename Op0_t, typename Op1_t>
365
367
368/// Match an affine SCEVAddRecExpr.
369template <typename Op0_t, typename Op1_t, typename Loop_t>
372 Loop_t Loop;
373
374 SCEVAffineAddRec_match(Op0_t Op0, Op1_t Op1, Loop_t Loop)
375 : Ops(Op0, Op1), Loop(Loop) {}
376
377 bool match(const SCEV *S) const {
378 return Ops.match(S) && Loop.match(cast<SCEVAddRecExpr>(S)->getLoop());
379 }
380};
381
382/// Match a specified const Loop*.
384 const Loop *L;
385
386 specificloop_ty(const Loop *L) : L(L) {}
387
388 bool match(const Loop *L) const { return L == this->L; }
389};
390
391inline specificloop_ty m_SpecificLoop(const Loop *L) { return L; }
392
393inline bind_ty<const Loop> m_Loop(const Loop *&L) { return L; }
394
395template <typename Op0_t, typename Op1_t>
396inline SCEVAffineAddRec_match<Op0_t, Op1_t, class_match<const Loop>>
397m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1) {
399 Op0, Op1, m_Loop());
400}
401
402template <typename Op0_t, typename Op1_t, typename Loop_t>
403inline SCEVAffineAddRec_match<Op0_t, Op1_t, Loop_t>
404m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1, const Loop_t &L) {
406}
407
409 bool match(const SCEV *S) const {
410 const SCEVUnknown *Unknown;
412 isa<UndefValue>(Unknown->getValue());
413 }
414};
415
416/// Match an SCEVUnknown wrapping undef or poison.
420
421} // namespace SCEVPatternMatch
422} // namespace llvm
423
424#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:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:290
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:284
@ 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.
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)