[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Aug 7 22:28:33 PDT 2005
Changes in directory llvm/lib/Transforms/Scalar:
LoopStrengthReduce.cpp updated: 1.37 -> 1.38
---
Log message:
Implement a simple optimization for the termination condition of the loop.
The termination condition actually wants to use the post-incremented value
of the loop, not a new indvar with an unusual base.
On PPC, for example, this allows us to compile
LoopStrengthReduce/exit_compare_live_range.ll to:
_foo:
li r2, 0
.LBB_foo_1: ; no_exit
li r5, 0
stw r5, 0(r3)
addi r2, r2, 1
cmpw cr0, r2, r4
bne .LBB_foo_1 ; no_exit
blr
instead of:
_foo:
li r2, 1 ;; IV starts at 1, not 0
.LBB_foo_1: ; no_exit
li r5, 0
stw r5, 0(r3)
addi r5, r2, 1
cmpw cr0, r2, r4
or r2, r5, r5 ;; Reg-reg copy, extra live range
bne .LBB_foo_1 ; no_exit
blr
This implements LoopStrengthReduce/exit_compare_live_range.ll
---
Diffs of the changes: (+107 -6)
LoopStrengthReduce.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 107 insertions(+), 6 deletions(-)
Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.37 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.38
--- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.37 Thu Aug 4 20:30:11 2005
+++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Aug 8 00:28:22 2005
@@ -46,9 +46,16 @@
SCEVHandle Offset;
Instruction *User;
Value *OperandValToReplace;
+
+ // isUseOfPostIncrementedValue - True if this should use the
+ // post-incremented version of this IV, not the preincremented version.
+ // This can only be set in special cases, such as the terminating setcc
+ // instruction for a loop.
+ bool isUseOfPostIncrementedValue;
IVStrideUse(const SCEVHandle &Offs, Instruction *U, Value *O)
- : Offset(Offs), User(U), OperandValToReplace(O) {}
+ : Offset(Offs), User(U), OperandValToReplace(O),
+ isUseOfPostIncrementedValue(false) {}
};
/// IVUsersOfOneStride - This structure keeps track of all instructions that
@@ -127,6 +134,7 @@
std::set<Instruction*> &Processed);
SCEVHandle GetExpressionSCEV(Instruction *E, Loop *L);
+ void OptimizeIndvars(Loop *L);
void StrengthReduceStridedIVUsers(Value *Stride, IVUsersOfOneStride &Uses,
Loop *L, bool isOnlyStride);
@@ -353,8 +361,15 @@
/// operation. This is null if we should just use zero so far.
Value *EmittedBase;
- BasedUser(Instruction *I, Value *Op, const SCEVHandle &IMM)
- : Inst(I), OperandValToReplace(Op), Imm(IMM), EmittedBase(0) {}
+ // isUseOfPostIncrementedValue - True if this should use the
+ // post-incremented version of this IV, not the preincremented version.
+ // This can only be set in special cases, such as the terminating setcc
+ // instruction for a loop.
+ bool isUseOfPostIncrementedValue;
+
+ BasedUser(Instruction *I, Value *Op, const SCEVHandle &IMM, bool iUOPIV)
+ : Inst(I), OperandValToReplace(Op), Imm(IMM), EmittedBase(0),
+ isUseOfPostIncrementedValue(iUOPIV) {}
// Once we rewrite the code to insert the new IVs we want, update the
// operands of Inst to use the new expression 'NewBase', with 'Imm' added
@@ -505,7 +520,8 @@
UsersToProcess.push_back(std::make_pair(Uses.Users[i].Offset,
BasedUser(Uses.Users[i].User,
Uses.Users[i].OperandValToReplace,
- ZeroBase)));
+ ZeroBase,
+ Uses.Users[i].isUseOfPostIncrementedValue)));
// First pass, figure out what we can represent in the immediate fields of
// instructions. If we can represent anything there, move it to the imm
@@ -586,7 +602,15 @@
// Now that we know what we need to do, insert code before User for the
// immediate and any loop-variant expressions.
- User.RewriteInstructionToUseNewBase(NewPHI, Rewriter);
+ Value *NewBase = NewPHI;
+
+ // If this instruction wants to use the post-incremented value, move it
+ // after the post-inc and use its value instead of the PHI.
+ if (User.isUseOfPostIncrementedValue) {
+ NewBase = IncV;
+ User.Inst->moveBefore(LatchBlock->getTerminator());
+ }
+ User.RewriteInstructionToUseNewBase(NewBase, Rewriter);
// Mark old value we replaced as possibly dead, so that it is elminated
// if we just replaced the last use of that value.
@@ -602,6 +626,76 @@
// different starting values, into different PHIs.
}
+// OptimizeIndvars - Now that IVUsesByStride is set up with all of the indvar
+// uses in the loop, look to see if we can eliminate some, in favor of using
+// common indvars for the different uses.
+void LoopStrengthReduce::OptimizeIndvars(Loop *L) {
+ // TODO: implement optzns here.
+
+
+
+
+ // Finally, get the terminating condition for the loop if possible. If we
+ // can, we want to change it to use a post-incremented version of its
+ // induction variable, to allow coallescing the live ranges for the IV into
+ // one register value.
+ PHINode *SomePHI = cast<PHINode>(L->getHeader()->begin());
+ BasicBlock *Preheader = L->getLoopPreheader();
+ BasicBlock *LatchBlock =
+ SomePHI->getIncomingBlock(SomePHI->getIncomingBlock(0) == Preheader);
+ BranchInst *TermBr = dyn_cast<BranchInst>(LatchBlock->getTerminator());
+ if (!TermBr || TermBr->isUnconditional() ||
+ !isa<SetCondInst>(TermBr->getCondition()))
+ return;
+ SetCondInst *Cond = cast<SetCondInst>(TermBr->getCondition());
+
+ // Search IVUsesByStride to find Cond's IVUse if there is one.
+ IVStrideUse *CondUse = 0;
+ Value *CondStride = 0;
+
+ for (std::map<Value*, IVUsersOfOneStride>::iterator I =IVUsesByStride.begin(),
+ E = IVUsesByStride.end(); I != E && !CondUse; ++I)
+ for (std::vector<IVStrideUse>::iterator UI = I->second.Users.begin(),
+ E = I->second.Users.end(); UI != E; ++UI)
+ if (UI->User == Cond) {
+ CondUse = &*UI;
+ CondStride = I->first;
+ // NOTE: we could handle setcc instructions with multiple uses here, but
+ // InstCombine does it as well for simple uses, it's not clear that it
+ // occurs enough in real life to handle.
+ break;
+ }
+ if (!CondUse) return; // setcc doesn't use the IV.
+
+ // setcc stride is complex, don't mess with users.
+ if (!isa<ConstantInt>(CondStride)) return;
+
+ // It's possible for the setcc instruction to be anywhere in the loop, and
+ // possible for it to have multiple users. If it is not immediately before
+ // the latch block branch, move it.
+ if (&*++BasicBlock::iterator(Cond) != (Instruction*)TermBr) {
+ if (Cond->hasOneUse()) { // Condition has a single use, just move it.
+ Cond->moveBefore(TermBr);
+ } else {
+ // Otherwise, clone the terminating condition and insert into the loopend.
+ Cond = cast<SetCondInst>(Cond->clone());
+ Cond->setName(L->getHeader()->getName() + ".termcond");
+ LatchBlock->getInstList().insert(TermBr, Cond);
+
+ // Clone the IVUse, as the old use still exists!
+ IVUsesByStride[CondStride].addUser(CondUse->Offset, Cond,
+ CondUse->OperandValToReplace);
+ CondUse = &IVUsesByStride[CondStride].Users.back();
+ }
+ }
+
+ // If we get to here, we know that we can transform the setcc instruction to
+ // use the post-incremented version of the IV, allowing us to coallesce the
+ // live ranges for the IV correctly.
+ CondUse->Offset = SCEV::getMinusSCEV(CondUse->Offset,
+ SCEVUnknown::get(CondStride));
+ CondUse->isUseOfPostIncrementedValue = true;
+}
void LoopStrengthReduce::runOnLoop(Loop *L) {
// First step, transform all loops nesting inside of this loop.
@@ -616,7 +710,14 @@
AddUsersIfInteresting(I, L, Processed);
// If we have nothing to do, return.
- //if (IVUsesByStride.empty()) return;
+ if (IVUsesByStride.empty()) return;
+
+ // Optimize induction variables. Some indvar uses can be transformed to use
+ // strides that will be needed for other purposes. A common example of this
+ // is the exit test for the loop, which can often be rewritten to use the
+ // computation of some other indvar to decide when to terminate the loop.
+ OptimizeIndvars(L);
+
// FIXME: We can widen subreg IV's here for RISC targets. e.g. instead of
// doing computation in byte values, promote to 32-bit values if safe.
More information about the llvm-commits
mailing list