[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Jeff Cohen
jeffc at jolt-lang.org
Sun Feb 27 11:37:18 PST 2005
Changes in directory llvm/lib/Transforms/Scalar:
LoopStrengthReduce.cpp updated: 1.1 -> 1.2
---
Log message:
First pass at improved Loop Strength Reduction. Still not yet ready for prime time.
---
Diffs of the changes: (+39 -35)
LoopStrengthReduce.cpp | 74 +++++++++++++++++++++++++------------------------
1 files changed, 39 insertions(+), 35 deletions(-)
Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.1 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.2
--- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.1 Mon Oct 18 16:08:22 2004
+++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Sun Feb 27 13:37:07 2005
@@ -50,6 +50,7 @@
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
+ AU.addRequiredID(LoopSimplifyID);
AU.addRequired<LoopInfo>();
AU.addRequired<DominatorSet>();
}
@@ -99,50 +100,38 @@
//
// We currently only handle GEP instructions that consist of zero or more
// constants and one instance of the canonical induction variable.
- bool foundIndvar = false;
- bool indvarLast = false;
+ unsigned indvar = 0;
std::vector<Value *> pre_op_vector;
std::vector<Value *> inc_op_vector;
Value *CanonicalIndVar = L->getCanonicalInductionVariable();
+ BasicBlock *Header = L->getHeader();
+
for (unsigned op = 1, e = GEPI->getNumOperands(); op != e; ++op) {
Value *operand = GEPI->getOperand(op);
if (operand == CanonicalIndVar) {
- // FIXME: We currently only support strength reducing GEP instructions
- // with one instance of the canonical induction variable. This means that
- // we can't deal with statements of the form A[i][i].
- if (foundIndvar == true)
- return;
-
// FIXME: use getCanonicalInductionVariableIncrement to choose between
// one and neg one maybe? We need to support int *foo = GEP base, -1
const Type *Ty = CanonicalIndVar->getType();
pre_op_vector.push_back(Constant::getNullValue(Ty));
inc_op_vector.push_back(ConstantInt::get(Ty, 1));
- foundIndvar = true;
- indvarLast = true;
+ indvar = op;
+ break;
} else if (isa<Constant>(operand)) {
pre_op_vector.push_back(operand);
- if (indvarLast == true) indvarLast = false;
+ } else if (Instruction *inst = dyn_cast<Instruction>(operand)) {
+ if (!DS->dominates(inst, Header->begin()))
+ return;
+ pre_op_vector.push_back(operand);
} else
return;
}
- // FIXME: handle GEPs where the indvar is not the last element of the index
- // array.
- if (indvarLast == false)
- return;
- assert(true == foundIndvar && "Indvar used by GEP not found in operand list");
+ assert(indvar > 0 && "Indvar used by GEP not found in operand list");
- // FIXME: Being able to hoist the definition of the initial pointer value
- // would allow us to strength reduce more loops. For example, %tmp.32 in the
- // following loop:
- // entry:
- // br label %no_exit.0
- // no_exit.0: ; preds = %entry, %no_exit.0
- // %init.1.0 = phi uint [ 0, %entry ], [ %indvar.next, %no_exit.0 ]
- // %tmp.32 = load uint** %CROSSING
- // %tmp.35 = getelementptr uint* %tmp.32, uint %init.1.0
- // br label %no_exit.0
- BasicBlock *Header = L->getHeader();
+ // Ensure the pointer base is loop invariant. While strength reduction
+ // makes sense even if the pointer changed on every iteration, there is no
+ // realistic way of handling it unless GEPs were completely decomposed into
+ // their constituent operations so we have explicit multiplications to work
+ // with.
if (Instruction *GepPtrOp = dyn_cast<Instruction>(GEPI->getOperand(0)))
if (!DS->dominates(GepPtrOp, Header->begin()))
return;
@@ -153,8 +142,6 @@
// If there is only one operand after the initial non-constant one, we know
// that it was the induction variable, and has been replaced by a constant
// null value. In this case, replace the GEP with a use of pointer directly.
- //
- //
BasicBlock *Preheader = L->getLoopPreheader();
Value *PreGEP;
if (isa<Constant>(GEPI->getOperand(0))) {
@@ -164,7 +151,7 @@
PreGEP = GEPI->getOperand(0);
} else {
PreGEP = new GetElementPtrInst(GEPI->getOperand(0),
- pre_op_vector, GEPI->getName(),
+ pre_op_vector, GEPI->getName()+".pre",
Preheader->getTerminator());
}
@@ -175,9 +162,10 @@
GEPI->getName()+".str", InsertBefore);
NewPHI->addIncoming(PreGEP, Preheader);
- // Now, create the GEP instruction to increment the value selected by the PHI
- // instruction we just created above by one, and add it as the second incoming
- // Value and BasicBlock pair to the PHINode.
+ // Now, create the GEP instruction to increment by one the value selected by
+ // the PHI instruction we just created above, and add it as the second
+ // incoming Value/BasicBlock pair to the PHINode. It is inserted before the
+ // increment of the canonical induction variable.
Instruction *IncrInst =
const_cast<Instruction*>(L->getCanonicalInductionVariableIncrement());
GetElementPtrInst *StrGEP = new GetElementPtrInst(NewPHI, inc_op_vector,
@@ -185,8 +173,24 @@
IncrInst);
NewPHI->addIncoming(StrGEP, IncrInst->getParent());
- // Replace all uses of the old GEP instructions with the new PHI
- GEPI->replaceAllUsesWith(NewPHI);
+ if (GEPI->getNumOperands() - 1 == indvar) {
+ // If there were no operands following the induction variable, replace all
+ // uses of the old GEP instruction with the new PHI.
+ GEPI->replaceAllUsesWith(NewPHI);
+ } else {
+ // Create a new GEP instruction using the new PHI as the base. The
+ // operands of the original GEP past the induction variable become
+ // operands of this new GEP.
+ std::vector<Value *> op_vector;
+ const Type *Ty = CanonicalIndVar->getType();
+ op_vector.push_back(Constant::getNullValue(Ty));
+ for (unsigned op = indvar + 1; op < GEPI->getNumOperands(); op++)
+ op_vector.push_back(GEPI->getOperand(op));
+ GetElementPtrInst *newGEP = new GetElementPtrInst(NewPHI, op_vector,
+ GEPI->getName() + ".lsr",
+ GEPI);
+ GEPI->replaceAllUsesWith(newGEP);
+}
// The old GEP is now dead.
DeadInsts.insert(GEPI);
More information about the llvm-commits
mailing list