summaryrefslogtreecommitdiff
path: root/lib/Analysis/ScalarEvolutionExpander.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-03-03 04:36:42 +0000
committerDan Gohman <gohman@apple.com>2010-03-03 04:36:42 +0000
commited78dbafd05ccc9dd4eb6e9e4d750d8aaacbe43a (patch)
treebd0c3d208708caccd8c1105231b2548584bc3209 /lib/Analysis/ScalarEvolutionExpander.cpp
parent6ba9554988f2efe13c6556c6149aea4846cf415d (diff)
downloadllvm-ed78dbafd05ccc9dd4eb6e9e4d750d8aaacbe43a.tar.gz
llvm-ed78dbafd05ccc9dd4eb6e9e4d750d8aaacbe43a.tar.bz2
llvm-ed78dbafd05ccc9dd4eb6e9e4d750d8aaacbe43a.tar.xz
Revert r97580; that's not the right way to fix this.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97639 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ScalarEvolutionExpander.cpp')
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp152
1 files changed, 31 insertions, 121 deletions
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index e26e9dd8b5..b6c7ce6448 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -528,138 +528,48 @@ static bool isNonConstantNegative(const SCEV *F) {
return SC->getValue()->getValue().isNegative();
}
-/// PickMostRelevantLoop - Given two loops pick the one that's most relevant for
-/// SCEV expansion. If they are nested, this is the most nested. If they are
-/// neighboring, pick the later.
-static const Loop *PickMostRelevantLoop(const Loop *A, const Loop *B,
- DominatorTree &DT) {
- if (!A) return B;
- if (!B) return A;
- if (A->contains(B)) return B;
- if (B->contains(A)) return A;
- if (DT.dominates(A->getHeader(), B->getHeader())) return B;
- if (DT.dominates(B->getHeader(), A->getHeader())) return A;
- return A; // Arbitrarily break the tie.
-}
+Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
+ int NumOperands = S->getNumOperands();
+ const Type *Ty = SE.getEffectiveSCEVType(S->getType());
-/// GetRelevantLoop - Get the most relevant loop associated with the given
-/// expression, according to PickMostRelevantLoop.
-static const Loop *GetRelevantLoop(const SCEV *S, LoopInfo &LI,
- DominatorTree &DT) {
- if (isa<SCEVConstant>(S))
- return 0;
- if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
- if (const Instruction *I = dyn_cast<Instruction>(U->getValue()))
- return LI.getLoopFor(I->getParent());
- return 0;
- }
- if (const SCEVNAryExpr *N = dyn_cast<SCEVNAryExpr>(S)) {
- const Loop *L = 0;
- if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S))
- L = AR->getLoop();
- for (SCEVNAryExpr::op_iterator I = N->op_begin(), E = N->op_end();
- I != E; ++I)
- L = PickMostRelevantLoop(L, GetRelevantLoop(*I, LI, DT), DT);
- return L;
- }
- if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S))
- return GetRelevantLoop(C->getOperand(), LI, DT);
- if (const SCEVUDivExpr *D = dyn_cast<SCEVUDivExpr>(S))
- return PickMostRelevantLoop(GetRelevantLoop(D->getLHS(), LI, DT),
- GetRelevantLoop(D->getRHS(), LI, DT),
- DT);
- llvm_unreachable("Unexpected SCEV type!");
-}
+ // Find the index of an operand to start with. Choose the operand with
+ // pointer type, if there is one, or the last operand otherwise.
+ int PIdx = 0;
+ for (; PIdx != NumOperands - 1; ++PIdx)
+ if (S->getOperand(PIdx)->getType()->isPointerTy()) break;
-namespace {
-
-/// LoopCompare - Compare loops by PickMostRelevantLoop.
-class LoopCompare {
- DominatorTree &DT;
-public:
- explicit LoopCompare(DominatorTree &dt) : DT(dt) {}
-
- bool operator()(std::pair<const Loop *, const SCEV *> LHS,
- std::pair<const Loop *, const SCEV *> RHS) const {
- // Compare loops with PickMostRelevantLoop.
- if (LHS.first != RHS.first)
- return PickMostRelevantLoop(LHS.first, RHS.first, DT) == LHS.first;
-
- // If one operand is a non-constant negative and the other is not,
- // put the non-constant negative on the right so that a sub can
- // be used instead of a negate and add.
- if (isNonConstantNegative(LHS.second)) {
- if (!isNonConstantNegative(RHS.second))
- return false;
- } else if (isNonConstantNegative(RHS.second))
- return true;
+ // Expand code for the operand that we chose.
+ Value *V = expand(S->getOperand(PIdx));
- // Otherwise they are equivalent according to this comparison.
- return false;
+ // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the
+ // comments on expandAddToGEP for details.
+ if (const PointerType *PTy = dyn_cast<PointerType>(V->getType())) {
+ // Take the operand at PIdx out of the list.
+ const SmallVectorImpl<const SCEV *> &Ops = S->getOperands();
+ SmallVector<const SCEV *, 8> NewOps;
+ NewOps.insert(NewOps.end(), Ops.begin(), Ops.begin() + PIdx);
+ NewOps.insert(NewOps.end(), Ops.begin() + PIdx + 1, Ops.end());
+ // Make a GEP.
+ return expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, V);
}
-};
-}
+ // Otherwise, we'll expand the rest of the SCEVAddExpr as plain integer
+ // arithmetic.
+ V = InsertNoopCastOfTo(V, Ty);
-Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
- const Type *Ty = SE.getEffectiveSCEVType(S->getType());
-
- // Collect all the add operands in a loop, along with their associated loops.
- // Iterate in reverse so that constants are emitted last, all else equal, and
- // so that pointer operands are inserted first, which the code below relies on
- // to form more involved GEPs.
- SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops;
- for (std::reverse_iterator<SCEVAddExpr::op_iterator> I(S->op_end()),
- E(S->op_begin()); I != E; ++I)
- OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT),
- *I));
-
- // Sort by loop. Use a stable sort so that constants follow non-constants and
- // pointer operands precede non-pointer operands.
- std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT));
-
- // Emit instructions to add all the operands. Hoist as much as possible
- // out of loops, and form meaningful getelementptrs where possible.
- Value *Sum = 0;
- for (SmallVectorImpl<std::pair<const Loop *, const SCEV *> >::iterator
- I = OpsAndLoops.begin(), E = OpsAndLoops.end(); I != E; ) {
- const Loop *CurLoop = I->first;
- const SCEV *Op = I->second;
- if (!Sum) {
- // This is the first operand. Just expand it.
- Sum = expand(Op);
- ++I;
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Sum->getType())) {
- // The running sum expression is a pointer. Try to form a getelementptr
- // at this level with that as the base.
- SmallVector<const SCEV *, 4> NewOps;
- for (; I != E && I->first == CurLoop; ++I)
- NewOps.push_back(I->second);
- Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, Sum);
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Op->getType())) {
- // The running sum is an integer, and there's a pointer at this level.
- // Try to form a getelementptr.
- SmallVector<const SCEV *, 4> NewOps;
- NewOps.push_back(SE.getUnknown(Sum));
- for (++I; I != E && I->first == CurLoop; ++I)
- NewOps.push_back(I->second);
- Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, expand(Op));
- } else if (isNonConstantNegative(Op)) {
- // Instead of doing a negate and add, just do a subtract.
+ // Emit a bunch of add instructions
+ for (int i = NumOperands-1; i >= 0; --i) {
+ if (i == PIdx) continue;
+ const SCEV *Op = S->getOperand(i);
+ if (isNonConstantNegative(Op)) {
Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty);
- Sum = InsertNoopCastOfTo(Sum, Ty);
- Sum = InsertBinop(Instruction::Sub, Sum, W);
- ++I;
+ V = InsertBinop(Instruction::Sub, V, W);
} else {
- // A simple add.
Value *W = expandCodeFor(Op, Ty);
- Sum = InsertNoopCastOfTo(Sum, Ty);
- Sum = InsertBinop(Instruction::Add, Sum, W);
- ++I;
+ V = InsertBinop(Instruction::Add, V, W);
}
}
-
- return Sum;
+ return V;
}
Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) {