First pass at improved Loop Strength Reduction. Still not yet ready for prime time.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20358 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jeff Cohen 2005-02-27 19:37:07 +00:00
parent 2a3cdf7e34
commit f465db6c6a

View File

@ -50,6 +50,7 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage &AU) const { virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG(); AU.setPreservesCFG();
AU.addRequiredID(LoopSimplifyID);
AU.addRequired<LoopInfo>(); AU.addRequired<LoopInfo>();
AU.addRequired<DominatorSet>(); AU.addRequired<DominatorSet>();
} }
@ -99,50 +100,38 @@ void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
// //
// We currently only handle GEP instructions that consist of zero or more // We currently only handle GEP instructions that consist of zero or more
// constants and one instance of the canonical induction variable. // constants and one instance of the canonical induction variable.
bool foundIndvar = false; unsigned indvar = 0;
bool indvarLast = false;
std::vector<Value *> pre_op_vector; std::vector<Value *> pre_op_vector;
std::vector<Value *> inc_op_vector; std::vector<Value *> inc_op_vector;
Value *CanonicalIndVar = L->getCanonicalInductionVariable(); Value *CanonicalIndVar = L->getCanonicalInductionVariable();
BasicBlock *Header = L->getHeader();
for (unsigned op = 1, e = GEPI->getNumOperands(); op != e; ++op) { for (unsigned op = 1, e = GEPI->getNumOperands(); op != e; ++op) {
Value *operand = GEPI->getOperand(op); Value *operand = GEPI->getOperand(op);
if (operand == CanonicalIndVar) { 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 // FIXME: use getCanonicalInductionVariableIncrement to choose between
// one and neg one maybe? We need to support int *foo = GEP base, -1 // one and neg one maybe? We need to support int *foo = GEP base, -1
const Type *Ty = CanonicalIndVar->getType(); const Type *Ty = CanonicalIndVar->getType();
pre_op_vector.push_back(Constant::getNullValue(Ty)); pre_op_vector.push_back(Constant::getNullValue(Ty));
inc_op_vector.push_back(ConstantInt::get(Ty, 1)); inc_op_vector.push_back(ConstantInt::get(Ty, 1));
foundIndvar = true; indvar = op;
indvarLast = true; break;
} else if (isa<Constant>(operand)) { } else if (isa<Constant>(operand)) {
pre_op_vector.push_back(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 } else
return; return;
} }
// FIXME: handle GEPs where the indvar is not the last element of the index assert(indvar > 0 && "Indvar used by GEP not found in operand list");
// array.
if (indvarLast == false)
return;
assert(true == foundIndvar && "Indvar used by GEP not found in operand list");
// FIXME: Being able to hoist the definition of the initial pointer value // Ensure the pointer base is loop invariant. While strength reduction
// would allow us to strength reduce more loops. For example, %tmp.32 in the // makes sense even if the pointer changed on every iteration, there is no
// following loop: // realistic way of handling it unless GEPs were completely decomposed into
// entry: // their constituent operations so we have explicit multiplications to work
// br label %no_exit.0 // with.
// 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();
if (Instruction *GepPtrOp = dyn_cast<Instruction>(GEPI->getOperand(0))) if (Instruction *GepPtrOp = dyn_cast<Instruction>(GEPI->getOperand(0)))
if (!DS->dominates(GepPtrOp, Header->begin())) if (!DS->dominates(GepPtrOp, Header->begin()))
return; return;
@ -153,8 +142,6 @@ void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
// If there is only one operand after the initial non-constant one, we know // 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 // 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. // null value. In this case, replace the GEP with a use of pointer directly.
//
//
BasicBlock *Preheader = L->getLoopPreheader(); BasicBlock *Preheader = L->getLoopPreheader();
Value *PreGEP; Value *PreGEP;
if (isa<Constant>(GEPI->getOperand(0))) { if (isa<Constant>(GEPI->getOperand(0))) {
@ -164,7 +151,7 @@ void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
PreGEP = GEPI->getOperand(0); PreGEP = GEPI->getOperand(0);
} else { } else {
PreGEP = new GetElementPtrInst(GEPI->getOperand(0), PreGEP = new GetElementPtrInst(GEPI->getOperand(0),
pre_op_vector, GEPI->getName(), pre_op_vector, GEPI->getName()+".pre",
Preheader->getTerminator()); Preheader->getTerminator());
} }
@ -175,9 +162,10 @@ void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
GEPI->getName()+".str", InsertBefore); GEPI->getName()+".str", InsertBefore);
NewPHI->addIncoming(PreGEP, Preheader); NewPHI->addIncoming(PreGEP, Preheader);
// Now, create the GEP instruction to increment the value selected by the PHI // Now, create the GEP instruction to increment by one the value selected by
// instruction we just created above by one, and add it as the second incoming // the PHI instruction we just created above, and add it as the second
// Value and BasicBlock pair to the PHINode. // incoming Value/BasicBlock pair to the PHINode. It is inserted before the
// increment of the canonical induction variable.
Instruction *IncrInst = Instruction *IncrInst =
const_cast<Instruction*>(L->getCanonicalInductionVariableIncrement()); const_cast<Instruction*>(L->getCanonicalInductionVariableIncrement());
GetElementPtrInst *StrGEP = new GetElementPtrInst(NewPHI, inc_op_vector, GetElementPtrInst *StrGEP = new GetElementPtrInst(NewPHI, inc_op_vector,
@ -185,8 +173,24 @@ void LoopStrengthReduce::strengthReduceGEP(GetElementPtrInst *GEPI, Loop *L,
IncrInst); IncrInst);
NewPHI->addIncoming(StrGEP, IncrInst->getParent()); NewPHI->addIncoming(StrGEP, IncrInst->getParent());
// Replace all uses of the old GEP instructions with the new PHI if (GEPI->getNumOperands() - 1 == indvar) {
GEPI->replaceAllUsesWith(NewPHI); // 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. // The old GEP is now dead.
DeadInsts.insert(GEPI); DeadInsts.insert(GEPI);