24#define DEBUG_TYPE "scev-division"
34static inline int sizeOfSCEV(
const SCEV *S) {
38 FindSCEVSize() =
default;
40 bool follow(
const SCEV *S) {
46 bool isDone()
const {
return false; }
50 SCEVTraversal<FindSCEVSize>
ST(
F);
60 const SCEV *Denominator,
const SCEV **Quotient,
61 const SCEV **Remainder) {
62 assert(Numerator && Denominator &&
"Uninitialized SCEV");
64 SCEVDivision
D(SE, Numerator, Denominator);
68 if (Numerator == Denominator) {
81 if (Denominator->isOne()) {
82 *Quotient = Numerator;
90 *Quotient = Numerator;
91 for (
const SCEV *
Op :
T->operands()) {
99 *Remainder = Numerator;
108 *Quotient =
D.Quotient;
109 *Remainder =
D.Remainder;
115 APInt DenominatorVal =
D->getAPInt();
119 if (NumeratorBW > DenominatorBW)
120 DenominatorVal = DenominatorVal.
sext(NumeratorBW);
121 else if (NumeratorBW < DenominatorBW)
122 NumeratorVal = NumeratorVal.
sext(DenominatorBW);
126 APInt::sdivrem(NumeratorVal, DenominatorVal, QuotientVal, RemainderVal);
127 Quotient = SE.getConstant(QuotientVal);
128 Remainder = SE.getConstant(RemainderVal);
134 return cannotDivide(Numerator);
138 const SCEV *StartQ, *StartR, *StepQ, *StepR;
140 return cannotDivide(Numerator);
144 Type *Ty = Denominator->getType();
147 return cannotDivide(Numerator);
148 Quotient = SE.getAddRecExpr(StartQ, StepQ, Numerator->
getLoop(),
150 Remainder = SE.getAddRecExpr(StartR, StepR, Numerator->
getLoop(),
156 Type *Ty = Denominator->getType();
160 divide(SE,
Op, Denominator, &Q, &R);
163 if (Ty != Q->
getType() || Ty != R->getType())
164 return cannotDivide(Numerator);
170 if (Qs.
size() == 1) {
176 Quotient = SE.getAddExpr(Qs);
177 Remainder = SE.getAddExpr(Rs);
182 Type *Ty = Denominator->getType();
184 bool FoundDenominatorTerm =
false;
187 if (Ty !=
Op->getType())
188 return cannotDivide(Numerator);
190 if (FoundDenominatorTerm) {
197 divide(SE,
Op, Denominator, &Q, &R);
205 return cannotDivide(Numerator);
207 FoundDenominatorTerm =
true;
211 if (FoundDenominatorTerm) {
216 Quotient = SE.getMulExpr(Qs);
221 return cannotDivide(Numerator);
228 if (Remainder->isZero()) {
237 const SCEV *Diff = SE.getMinusSCEV(Numerator, Remainder);
239 if (sizeOfSCEV(Diff) > sizeOfSCEV(Numerator))
240 return cannotDivide(Numerator);
241 divide(SE, Diff, Denominator, &Q, &R);
243 return cannotDivide(Numerator);
248 const SCEV *Denominator)
249 : SE(S), Denominator(Denominator) {
255 cannotDivide(Numerator);
260void SCEVDivision::cannotDivide(
const SCEV *Numerator) {
262 Remainder = Numerator;
266 OS <<
"Printing analysis 'Scalar Evolution Division' for function '"
267 <<
F.getName() <<
"':\n";
270 if (!Div || Div->
getOpcode() != Instruction::SDiv)
275 const SCEV *Quotient, *Remainder;
278 OS <<
"Instruction: " << *Div <<
"\n";
279 OS.indent(2) <<
"Numerator: " << *Numerator <<
"\n";
280 OS.indent(2) <<
"Denominator: " << *Denominator <<
"\n";
281 OS.indent(2) <<
"Quotient: " << *Quotient <<
"\n";
282 OS.indent(2) <<
"Remainder: " << *Remainder <<
"\n";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
This file defines the SmallVector class.
Class for arbitrary precision integers.
static LLVM_ABI void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
unsigned getBitWidth() const
Return the number of bits in the APInt.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
BinaryOps getOpcode() const
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This node represents an addition of some number of SCEVs.
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStart() const
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
This class represents a constant integer value.
const APInt & getAPInt() const
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This node represents multiplication of some number of SCEVs.
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
ArrayRef< const SCEV * > operands() const
static const SCEV * rewrite(const SCEV *Scev, ScalarEvolution &SE, ValueToSCEVMapTy &Map)
This class represents the value of vscale, as used when defining the length of a scalable vector or r...
This class represents an analyzed expression in the program.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Value * getOperand(unsigned i) const
This is an optimization pass for GlobalISel generic memory operations.
DenseMap< const Value *, const SCEV * > ValueToSCEVMapTy
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static void divide(ScalarEvolution &SE, const SCEV *Numerator, const SCEV *Denominator, const SCEV **Quotient, const SCEV **Remainder)
Computes the Quotient and Remainder of the division of Numerator by Denominator.
void visitVScale(const SCEVVScale *Numerator)
void visitAddRecExpr(const SCEVAddRecExpr *Numerator)
void visitConstant(const SCEVConstant *Numerator)
void visitAddExpr(const SCEVAddExpr *Numerator)
void visitMulExpr(const SCEVMulExpr *Numerator)