ScalarEvolution: Introduce SCEVSDivision and SCEVUDivision

It turns out that not all users of SCEVDivision want the same
signedness.  Let the users determine which operation they'd like by
explicitly choosing SCEVUDivision or SCEVSDivision.

findArrayDimensions and computeAccessFunctions will use SCEVSDivision
while HowFarToZero will use SCEVUDivision.

llvm-svn: 222104
This commit is contained in:
David Majnemer 2014-11-16 20:35:19 +00:00
parent 2f8732e7c6
commit 32b8ccf480
1 changed files with 59 additions and 16 deletions

View File

@ -675,6 +675,34 @@ static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
} }
} }
static const APInt srem(const SCEVConstant *C1, const SCEVConstant *C2) {
APInt A = C1->getValue()->getValue();
APInt B = C2->getValue()->getValue();
uint32_t ABW = A.getBitWidth();
uint32_t BBW = B.getBitWidth();
if (ABW > BBW)
B = B.sext(ABW);
else if (ABW < BBW)
A = A.sext(BBW);
return APIntOps::srem(A, B);
}
static const APInt sdiv(const SCEVConstant *C1, const SCEVConstant *C2) {
APInt A = C1->getValue()->getValue();
APInt B = C2->getValue()->getValue();
uint32_t ABW = A.getBitWidth();
uint32_t BBW = B.getBitWidth();
if (ABW > BBW)
B = B.sext(ABW);
else if (ABW < BBW)
A = A.sext(BBW);
return APIntOps::sdiv(A, B);
}
static const APInt urem(const SCEVConstant *C1, const SCEVConstant *C2) { static const APInt urem(const SCEVConstant *C1, const SCEVConstant *C2) {
APInt A = C1->getValue()->getValue(); APInt A = C1->getValue()->getValue();
APInt B = C2->getValue()->getValue(); APInt B = C2->getValue()->getValue();
@ -729,7 +757,8 @@ static inline int sizeOfSCEV(const SCEV *S) {
namespace { namespace {
struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> { template <typename Derived>
struct SCEVDivision : public SCEVVisitor<Derived, void> {
public: public:
// Computes the Quotient and Remainder of the division of Numerator by // Computes the Quotient and Remainder of the division of Numerator by
// Denominator. // Denominator.
@ -738,7 +767,7 @@ public:
const SCEV **Remainder) { const SCEV **Remainder) {
assert(Numerator && Denominator && "Uninitialized SCEV"); assert(Numerator && Denominator && "Uninitialized SCEV");
SCEVDivision D(SE, Numerator, Denominator); SCEVDivision<Derived> D(SE, Numerator, Denominator);
// Check for the trivial case here to avoid having to check for it in the // Check for the trivial case here to avoid having to check for it in the
// rest of the code. // rest of the code.
@ -801,14 +830,6 @@ public:
void visitUnknown(const SCEVUnknown *Numerator) {} void visitUnknown(const SCEVUnknown *Numerator) {}
void visitCouldNotCompute(const SCEVCouldNotCompute *Numerator) {} void visitCouldNotCompute(const SCEVCouldNotCompute *Numerator) {}
void visitConstant(const SCEVConstant *Numerator) {
if (const SCEVConstant *D = dyn_cast<SCEVConstant>(Denominator)) {
Quotient = SE.getConstant(udiv(Numerator, D));
Remainder = SE.getConstant(urem(Numerator, D));
return;
}
}
void visitAddRecExpr(const SCEVAddRecExpr *Numerator) { void visitAddRecExpr(const SCEVAddRecExpr *Numerator) {
const SCEV *StartQ, *StartR, *StepQ, *StepR; const SCEV *StartQ, *StartR, *StepQ, *StepR;
assert(Numerator->isAffine() && "Numerator should be affine"); assert(Numerator->isAffine() && "Numerator should be affine");
@ -934,11 +955,33 @@ public:
private: private:
ScalarEvolution &SE; ScalarEvolution &SE;
const SCEV *Denominator, *Quotient, *Remainder, *Zero, *One; const SCEV *Denominator, *Quotient, *Remainder, *Zero, *One;
friend struct SCEVSDivision;
friend struct SCEVUDivision;
}; };
struct SCEVSDivision : public SCEVDivision<SCEVSDivision> {
void visitConstant(const SCEVConstant *Numerator) {
if (const SCEVConstant *D = dyn_cast<SCEVConstant>(Denominator)) {
Quotient = SE.getConstant(sdiv(Numerator, D));
Remainder = SE.getConstant(srem(Numerator, D));
return;
}
}
};
struct SCEVUDivision : public SCEVDivision<SCEVUDivision> {
void visitConstant(const SCEVConstant *Numerator) {
if (const SCEVConstant *D = dyn_cast<SCEVConstant>(Denominator)) {
Quotient = SE.getConstant(udiv(Numerator, D));
Remainder = SE.getConstant(urem(Numerator, D));
return;
}
}
};
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Simple SCEV method implementations // Simple SCEV method implementations
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -6086,7 +6129,7 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L, bool ControlsExit) {
// backedge count. // backedge count.
const SCEV *Q, *R; const SCEV *Q, *R;
ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this); ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this);
SCEVDivision::divide(SE, Distance, Step, &Q, &R); SCEVUDivision::divide(SE, Distance, Step, &Q, &R);
if (R->isZero()) { if (R->isZero()) {
const SCEV *Exact = const SCEV *Exact =
getUDivExactExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step); getUDivExactExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
@ -7401,7 +7444,7 @@ static bool findArrayDimensionsRec(ScalarEvolution &SE,
for (const SCEV *&Term : Terms) { for (const SCEV *&Term : Terms) {
// Normalize the terms before the next call to findArrayDimensionsRec. // Normalize the terms before the next call to findArrayDimensionsRec.
const SCEV *Q, *R; const SCEV *Q, *R;
SCEVDivision::divide(SE, Term, Step, &Q, &R); SCEVSDivision::divide(SE, Term, Step, &Q, &R);
// Bail out when GCD does not evenly divide one of the terms. // Bail out when GCD does not evenly divide one of the terms.
if (!R->isZero()) if (!R->isZero())
@ -7538,7 +7581,7 @@ void ScalarEvolution::findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms,
// Divide all terms by the element size. // Divide all terms by the element size.
for (const SCEV *&Term : Terms) { for (const SCEV *&Term : Terms) {
const SCEV *Q, *R; const SCEV *Q, *R;
SCEVDivision::divide(SE, Term, ElementSize, &Q, &R); SCEVSDivision::divide(SE, Term, ElementSize, &Q, &R);
Term = Q; Term = Q;
} }
@ -7585,7 +7628,7 @@ void SCEVAddRecExpr::computeAccessFunctions(
int Last = Sizes.size() - 1; int Last = Sizes.size() - 1;
for (int i = Last; i >= 0; i--) { for (int i = Last; i >= 0; i--) {
const SCEV *Q, *R; const SCEV *Q, *R;
SCEVDivision::divide(SE, Res, Sizes[i], &Q, &R); SCEVSDivision::divide(SE, Res, Sizes[i], &Q, &R);
DEBUG({ DEBUG({
dbgs() << "Res: " << *Res << "\n"; dbgs() << "Res: " << *Res << "\n";