LLVM 22.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 {
19namespace SCEVPatternMatch {
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;
28 bool match(const SCEV *S) const {
29 assert((isa<SCEVCouldNotCompute>(S) || !S->getType()->isVectorTy()) &&
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.
57}
58
59template <typename Class> struct class_match {
60 template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
61};
62
66}
69}
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
98/// Match a specified const SCEV *.
100 const SCEV *Expr;
101
103
104 template <typename ITy> bool match(ITy *S) const { return S == Expr; }
105};
106
107/// Match if we have a specific specified SCEV.
108inline specificscev_ty m_scev_Specific(const SCEV *S) { return S; }
109
113 bool isValue(const APInt &C) const { return C == CV; }
114};
115
116/// Match an SCEV constant with a plain unsigned integer.
118
120 int64_t CV;
122 bool isValue(const APInt &C) const { return C.trySExtValue() == CV; }
123};
124
125/// Match an SCEV constant with a plain signed integer (sign-extended value will
126/// be matched)
128 return V;
129}
130
132 const APInt *&CR;
133
134 bind_cst_ty(const APInt *&Op0) : CR(Op0) {}
135
136 bool match(const SCEV *S) const {
137 assert((isa<SCEVCouldNotCompute>(S) || !S->getType()->isVectorTy()) &&
138 "no vector types expected from SCEVs");
139 auto *C = dyn_cast<SCEVConstant>(S);
140 if (!C)
141 return false;
142 CR = &C->getAPInt();
143 return true;
144 }
145};
146
147/// Match an SCEV constant and bind it to an APInt.
148inline bind_cst_ty m_scev_APInt(const APInt *&C) { return C; }
149
150/// Match a unary SCEV.
151template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
153
155
156 bool match(const SCEV *S) const {
157 auto *E = dyn_cast<SCEVTy>(S);
158 return E && E->getNumOperands() == 1 && Op0.match(E->getOperand(0));
159 }
160};
161
162template <typename SCEVTy, typename Op0_t>
165}
166
167template <typename Op0_t>
168inline SCEVUnaryExpr_match<SCEVSignExtendExpr, Op0_t>
169m_scev_SExt(const Op0_t &Op0) {
170 return m_scev_Unary<SCEVSignExtendExpr>(Op0);
171}
172
173template <typename Op0_t>
174inline SCEVUnaryExpr_match<SCEVZeroExtendExpr, Op0_t>
175m_scev_ZExt(const Op0_t &Op0) {
176 return m_scev_Unary<SCEVZeroExtendExpr>(Op0);
177}
178
179template <typename Op0_t>
180inline SCEVUnaryExpr_match<SCEVPtrToIntExpr, Op0_t>
183}
184
185/// Match a binary SCEV.
186template <typename SCEVTy, typename Op0_t, typename Op1_t>
190
192
193 bool match(const SCEV *S) const {
194 auto *E = dyn_cast<SCEVTy>(S);
195 return E && E->getNumOperands() == 2 && Op0.match(E->getOperand(0)) &&
196 Op1.match(E->getOperand(1));
197 }
198};
199
200template <typename SCEVTy, typename Op0_t, typename Op1_t>
201inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t>
202m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
204}
205
206template <typename Op0_t, typename Op1_t>
207inline SCEVBinaryExpr_match<SCEVAddExpr, Op0_t, Op1_t>
208m_scev_Add(const Op0_t &Op0, const Op1_t &Op1) {
209 return m_scev_Binary<SCEVAddExpr>(Op0, Op1);
210}
211
212template <typename Op0_t, typename Op1_t>
213inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t>
214m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
215 return m_scev_Binary<SCEVMulExpr>(Op0, Op1);
216}
217
218template <typename Op0_t, typename Op1_t>
219inline SCEVBinaryExpr_match<SCEVUDivExpr, Op0_t, Op1_t>
220m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1) {
221 return m_scev_Binary<SCEVUDivExpr>(Op0, Op1);
222}
223
225
226/// Match an affine SCEVAddRecExpr.
227template <typename Op0_t, typename Op1_t, typename Loop_t>
230 Loop_t Loop;
231
233 : Ops(Op0, Op1), Loop(Loop) {}
234
235 bool match(const SCEV *S) const {
236 return Ops.match(S) && Loop.match(cast<SCEVAddRecExpr>(S)->getLoop());
237 }
238};
239
240/// Match a specified const Loop*.
242 const Loop *L;
243
244 specificloop_ty(const Loop *L) : L(L) {}
245
246 bool match(const Loop *L) const { return L == this->L; }
247};
248
249inline specificloop_ty m_SpecificLoop(const Loop *L) { return L; }
250
251inline bind_ty<const Loop> m_Loop(const Loop *&L) { return L; }
252
253template <typename Op0_t, typename Op1_t>
254inline SCEVAffineAddRec_match<Op0_t, Op1_t, class_match<const Loop>>
255m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1) {
257 Op0, Op1, m_Loop());
258}
259
260template <typename Op0_t, typename Op1_t, typename Loop_t>
261inline SCEVAffineAddRec_match<Op0_t, Op1_t, Loop_t>
262m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1, const Loop_t &L) {
264}
265
266} // namespace SCEVPatternMatch
267} // namespace llvm
268
269#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define P(N)
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 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.
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:273
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
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)
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)
SCEVAffineAddRec_match< Op0_t, Op1_t, class_match< const Loop > > m_scev_AffineAddRec(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)
cst_pred_ty< is_zero > m_scev_Zero()
Match an integer 0.
SCEVBinaryExpr_match< SCEVMulExpr, Op0_t, Op1_t > m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1)
SCEVBinaryExpr_match< SCEVTy, Op0_t, Op1_t > m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1)
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.
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.
class_match< const SCEV > m_SCEV()
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
SCEVBinaryExpr_match< SCEVAddRecExpr, Op0_t, Op1_t > Ops
SCEVAffineAddRec_match(Op0_t Op0, Op1_t Op1, Loop_t Loop)