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 const SCEV *S = U.getPointer();
28 return const_cast<Pattern &>(P).match(S);
29}
30
31template <typename Predicate> struct cst_pred_ty : public Predicate {
32 cst_pred_ty() = default;
33 cst_pred_ty(uint64_t V) : Predicate(V) {}
34 bool match(const SCEV *S) const {
36 "no vector types expected from SCEVs");
37 auto *C = dyn_cast<SCEVConstant>(S);
38 return C && this->isValue(C->getAPInt());
39 }
40};
41
42struct is_zero {
43 bool isValue(const APInt &C) const { return C.isZero(); }
44};
45
46/// Match an integer 0.
48
49struct is_one {
50 bool isValue(const APInt &C) const { return C.isOne(); }
51};
52
53/// Match an integer 1.
55
57 bool isValue(const APInt &C) const { return C.isAllOnes(); }
58};
59
60/// Match an integer with all bits set.
64
65template <typename Class> struct class_match {
66 template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
67};
68
76
77template <typename Class> struct bind_ty {
78 Class *&VR;
79
80 bind_ty(Class *&V) : VR(V) {}
81
82 template <typename ITy> bool match(ITy *V) const {
83 if (auto *CV = dyn_cast<Class>(V)) {
84 VR = CV;
85 return true;
86 }
87 return false;
88 }
89};
90
91template <> struct bind_ty<SCEVUse> {
93
94 bind_ty(SCEVUse &V) : VR(V) {}
95
96 template <typename ITy> bool match(ITy *V) const {
97 VR = V;
98 return true;
99 }
100};
101
102/// Match a SCEV, capturing it if we match.
103inline bind_ty<const SCEV> m_SCEV(const SCEV *&V) { return V; }
104inline bind_ty<SCEVUse> m_SCEV(SCEVUse &V) { return V; }
106 return V;
107}
109 return V;
110}
111
113 return V;
114}
115
117 return V;
118}
119
120/// Match a specified const SCEV *.
122 const SCEV *Expr;
123
125
126 template <typename ITy> bool match(ITy *S) const { return S == Expr; }
127};
128
129/// Match if we have a specific specified SCEV.
130inline specificscev_ty m_scev_Specific(const SCEV *S) { return S; }
131
135 bool isValue(const APInt &C) const { return C == CV; }
136};
137
138/// Match an SCEV constant with a plain unsigned integer.
140
142 int64_t CV;
144 bool isValue(const APInt &C) const { return C.trySExtValue() == CV; }
145};
146
147/// Match an SCEV constant with a plain signed integer (sign-extended value will
148/// be matched)
150 return V;
151}
152
154 const APInt *&CR;
155
156 bind_cst_ty(const APInt *&Op0) : CR(Op0) {}
157
158 bool match(const SCEV *S) const {
160 "no vector types expected from SCEVs");
161 auto *C = dyn_cast<SCEVConstant>(S);
162 if (!C)
163 return false;
164 CR = &C->getAPInt();
165 return true;
166 }
167};
168
169/// Match an SCEV constant and bind it to an APInt.
170inline bind_cst_ty m_scev_APInt(const APInt *&C) { return C; }
171
172/// Match a unary SCEV.
173template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
174 Op0_t Op0;
175
177
178 bool match(const SCEV *S) const {
179 auto *E = dyn_cast<SCEVTy>(S);
180 return E && E->getNumOperands() == 1 &&
181 Op0.match(E->getOperand(0).getPointer());
182 }
183};
184
185template <typename SCEVTy, typename Op0_t>
189
190template <typename Op0_t>
191inline SCEVUnaryExpr_match<SCEVSignExtendExpr, Op0_t>
192m_scev_SExt(const Op0_t &Op0) {
194}
195
196template <typename Op0_t>
197inline SCEVUnaryExpr_match<SCEVZeroExtendExpr, Op0_t>
198m_scev_ZExt(const Op0_t &Op0) {
200}
201
202template <typename Op0_t>
203inline SCEVUnaryExpr_match<SCEVPtrToIntExpr, Op0_t>
204m_scev_PtrToInt(const Op0_t &Op0) {
206}
207
208template <typename Op0_t>
209inline SCEVUnaryExpr_match<SCEVPtrToAddrExpr, Op0_t>
210m_scev_PtrToAddr(const Op0_t &Op0) {
212}
213
214template <typename Op0_t>
215inline SCEVUnaryExpr_match<SCEVTruncateExpr, Op0_t>
216m_scev_Trunc(const Op0_t &Op0) {
218}
219
220/// Match a binary SCEV.
221template <typename SCEVTy, typename Op0_t, typename Op1_t,
223 bool Commutable = false>
225 Op0_t Op0;
227
229
230 bool match(const SCEV *S) const {
231 if (auto WrappingS = dyn_cast<SCEVNAryExpr>(S))
232 if (WrappingS->getNoWrapFlags(WrapFlags) != WrapFlags)
233 return false;
234
235 auto *E = dyn_cast<SCEVTy>(S);
236 return E && E->getNumOperands() == 2 &&
237 ((Op0.match(E->getOperand(0).getPointer()) &&
238 Op1.match(E->getOperand(1).getPointer())) ||
239 (Commutable && Op0.match(E->getOperand(1).getPointer()) &&
240 Op1.match(E->getOperand(0).getPointer())));
241 }
242};
243
244template <typename SCEVTy, typename Op0_t, typename Op1_t,
246 bool Commutable = false>
247inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>
248m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
250 Op1);
251}
252
253template <typename Op0_t, typename Op1_t>
254inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t>
255m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
256 return m_scev_Binary<SCEVAddExpr>(Op0, Op1);
257}
258
259template <typename Op0_t, typename Op1_t>
260inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t>
261m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
262 return m_scev_Binary<SCEVMulExpr>(Op0, Op1);
263}
264
265template <typename Op0_t, typename Op1_t>
266inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true>
267m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
269 Op1);
270}
271
272template <typename Op0_t, typename Op1_t>
273inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>
274m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1) {
276 Op1);
277}
278
279template <typename Op0_t, typename Op1_t>
280inline SCEVBinaryExpr_match<SCEVUDivExpr, Op0_t, Op1_t>
281m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1) {
282 return m_scev_Binary<SCEVUDivExpr>(Op0, Op1);
283}
284
285template <typename Op0_t, typename Op1_t>
286inline SCEVBinaryExpr_match<SCEVSMaxExpr, Op0_t, Op1_t>
287m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1) {
288 return m_scev_Binary<SCEVSMaxExpr>(Op0, Op1);
289}
290
291template <typename Op0_t, typename Op1_t>
292inline SCEVBinaryExpr_match<SCEVMinMaxExpr, Op0_t, Op1_t>
293m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1) {
294 return m_scev_Binary<SCEVMinMaxExpr>(Op0, Op1);
295}
296
297/// Match unsigned remainder pattern.
298/// Matches patterns generated by getURemExpr.
299template <typename Op0_t, typename Op1_t> struct SCEVURem_match {
300 Op0_t Op0;
303
306
307 bool match(const SCEV *Expr) const {
308 if (Expr->getType()->isPointerTy())
309 return false;
310
311 // Try to match 'zext (trunc A to iB) to iY', which is used
312 // for URem with constant power-of-2 second operands. Make sure the size of
313 // the operand A matches the size of the whole expressions.
314 const SCEV *LHS;
316 Type *TruncTy = cast<SCEVZeroExtendExpr>(Expr)->getOperand()->getType();
317 // Bail out if the type of the LHS is larger than the type of the
318 // expression for now.
319 if (SE.getTypeSizeInBits(LHS->getType()) >
320 SE.getTypeSizeInBits(Expr->getType()))
321 return false;
322 if (LHS->getType() != Expr->getType())
323 LHS = SE.getZeroExtendExpr(LHS, Expr->getType());
324 const SCEV *RHS =
325 SE.getConstant(APInt(SE.getTypeSizeInBits(Expr->getType()), 1)
326 << SE.getTypeSizeInBits(TruncTy));
327 return Op0.match(LHS) && Op1.match(RHS);
328 }
329
330 const SCEV *A;
331 const SCEVMulExpr *Mul;
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
368
369/// Match an affine SCEVAddRecExpr.
370template <typename Op0_t, typename Op1_t, typename Loop_t>
373 Loop_t Loop;
374
375 SCEVAffineAddRec_match(Op0_t Op0, Op1_t Op1, Loop_t Loop)
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 bind_ty<const Loop> m_Loop(const Loop *&L) { return L; }
395
396template <typename Op0_t, typename Op1_t>
397inline SCEVAffineAddRec_match<Op0_t, Op1_t, class_match<const Loop>>
398m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1) {
400 Op0, Op1, 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!")
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.
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)