void visitAddExpr(const SCEVAddExpr *Numerator) {
SmallVector<const SCEV *, 2> Qs, Rs;
+ Type *Ty = Denominator->getType();
+
for (const SCEV *Op : Numerator->operands()) {
const SCEV *Q, *R;
divide(SE, Op, Denominator, &Q, &R);
+
+ // Bail out if types do not match.
+ if (Ty != Q->getType() || Ty != R->getType()) {
+ Quotient = Zero;
+ Remainder = Numerator;
+ return;
+ }
+
Qs.push_back(Q);
Rs.push_back(R);
}
void visitMulExpr(const SCEVMulExpr *Numerator) {
SmallVector<const SCEV *, 2> Qs;
+ Type *Ty = Denominator->getType();
bool FoundDenominatorTerm = false;
for (const SCEV *Op : Numerator->operands()) {
+ // Bail out if types do not match.
+ if (Ty != Op->getType()) {
+ Quotient = Zero;
+ Remainder = Numerator;
+ return;
+ }
+
if (FoundDenominatorTerm) {
Qs.push_back(Op);
continue;
Qs.push_back(Op);
continue;
}
+
+ // Bail out if types do not match.
+ if (Ty != Q->getType()) {
+ Quotient = Zero;
+ Remainder = Numerator;
+ return;
+ }
+
FoundDenominatorTerm = true;
Qs.push_back(Q);
}
cast<SCEVConstant>(Zero)->getValue();
Remainder = SCEVParameterRewriter::rewrite(Numerator, SE, RewriteMap, true);
+ if (Remainder->isZero()) {
+ // The Quotient is obtained by replacing Denominator by 1 in Numerator.
+ RewriteMap[cast<SCEVUnknown>(Denominator)->getValue()] =
+ cast<SCEVConstant>(One)->getValue();
+ Quotient =
+ SCEVParameterRewriter::rewrite(Numerator, SE, RewriteMap, true);
+ return;
+ }
+
// Quotient is (Numerator - Remainder) divided by Denominator.
const SCEV *Q, *R;
const SCEV *Diff = SE.getMinusSCEV(Numerator, Remainder);
};
}
-// Find the Greatest Common Divisor of A and B.
-static const SCEV *
-findGCD(ScalarEvolution &SE, const SCEV *A, const SCEV *B) {
-
- if (const SCEVConstant *CA = dyn_cast<SCEVConstant>(A))
- if (const SCEVConstant *CB = dyn_cast<SCEVConstant>(B))
- return SE.getConstant(gcd(CA, CB));
-
- const SCEV *One = SE.getConstant(A->getType(), 1);
- if (isa<SCEVConstant>(A) && isa<SCEVUnknown>(B))
- return One;
- if (isa<SCEVUnknown>(A) && isa<SCEVConstant>(B))
- return One;
-
- const SCEV *Q, *R;
- if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(A)) {
- SmallVector<const SCEV *, 2> Qs;
- for (const SCEV *Op : M->operands())
- Qs.push_back(findGCD(SE, Op, B));
- return SE.getMulExpr(Qs);
- }
- if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(B)) {
- SmallVector<const SCEV *, 2> Qs;
- for (const SCEV *Op : M->operands())
- Qs.push_back(findGCD(SE, A, Op));
- return SE.getMulExpr(Qs);
- }
-
- SCEVDivision::divide(SE, A, B, &Q, &R);
- if (R->isZero())
- return B;
-
- SCEVDivision::divide(SE, B, A, &Q, &R);
- if (R->isZero())
- return A;
-
- return One;
-}
-
-// Find the Greatest Common Divisor of all the SCEVs in Terms.
-static const SCEV *
-findGCD(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &Terms) {
- assert(Terms.size() > 0 && "Terms vector is empty");
-
- const SCEV *GCD = Terms[0];
- for (const SCEV *T : Terms)
- GCD = findGCD(SE, GCD, T);
-
- return GCD;
-}
-
static bool findArrayDimensionsRec(ScalarEvolution &SE,
SmallVectorImpl<const SCEV *> &Terms,
SmallVectorImpl<const SCEV *> &Sizes) {
- // The GCD of all Terms is the dimension of the innermost dimension.
- const SCEV *GCD = findGCD(SE, Terms);
+ int Last = Terms.size() - 1;
+ const SCEV *Step = Terms[Last];
// End of recursion.
- if (Terms.size() == 1) {
- if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(GCD)) {
+ if (Last == 0) {
+ if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
SmallVector<const SCEV *, 2> Qs;
for (const SCEV *Op : M->operands())
if (!isa<SCEVConstant>(Op))
Qs.push_back(Op);
- GCD = SE.getMulExpr(Qs);
+ Step = SE.getMulExpr(Qs);
}
- Sizes.push_back(GCD);
+ Sizes.push_back(Step);
return true;
}
for (const SCEV *&Term : Terms) {
// Normalize the terms before the next call to findArrayDimensionsRec.
const SCEV *Q, *R;
- SCEVDivision::divide(SE, Term, GCD, &Q, &R);
+ SCEVDivision::divide(SE, Term, Step, &Q, &R);
// Bail out when GCD does not evenly divide one of the terms.
if (!R->isZero())
if (!findArrayDimensionsRec(SE, Terms, Sizes))
return false;
- Sizes.push_back(GCD);
+ Sizes.push_back(Step);
return true;
}
if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
Ty = Store->getValueOperand()->getType();
else if (LoadInst *Load = dyn_cast<LoadInst>(Inst))
- Ty = Load->getPointerOperand()->getType();
+ Ty = Load->getType();
else
return nullptr;
SmallVectorImpl<const SCEV *> &Sizes,
const SCEV *ElementSize) const {
- if (Terms.size() < 1)
+ if (Terms.size() < 1 || !ElementSize)
return;
// Early return when Terms do not contain parameters: we do not delinearize