[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Feb 15 14:52:17 PST 2006
Changes in directory llvm/lib/Transforms/Scalar:
LoopUnswitch.cpp updated: 1.22 -> 1.23
---
Log message:
Implement trivial unswitching for switch stmts. This allows us to trivial
unswitch this loop on 2 before sweating to unswitch on 1/3.
void test4(int N, int i, int C, int*P, int*Q) {
int j;
for (j = 0; j < N; ++j) {
switch (C) { // general unswitching.
default: P[i+j] = 0; break;
case 1: Q[i+j] = 0; break;
case 3: P[i+j] = Q[i+j]; break;
case 2: break; // TRIVIAL UNSWITCH on C==2
}
}
}
---
Diffs of the changes: (+51 -27)
LoopUnswitch.cpp | 78 +++++++++++++++++++++++++++++++++++--------------------
1 files changed, 51 insertions(+), 27 deletions(-)
Index: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
diff -u llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.22 llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.23
--- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.22 Wed Feb 15 16:03:36 2006
+++ llvm/lib/Transforms/Scalar/LoopUnswitch.cpp Wed Feb 15 16:52:05 2006
@@ -79,7 +79,7 @@
void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,Constant *Val,
bool isEqual);
void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
- BasicBlock *ExitBlock);
+ bool EntersWhenTrue, BasicBlock *ExitBlock);
};
RegisterOpt<LoopUnswitch> X("loop-unswitch", "Unswitch loops");
}
@@ -152,7 +152,7 @@
// Okay, everything after this looks good, check to make sure that this block
// doesn't include any side effects.
- for (BasicBlock::iterator I = Header->begin(), E = Header->end(); I != E; ++I)
+ for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
if (I->mayWriteToMemory())
return false;
@@ -180,31 +180,48 @@
/// condition is false. Otherwise, return null to indicate a complex condition.
static bool IsTrivialUnswitchCondition(Loop *L, Value *Cond,
Constant **Val = 0,
+ bool *EntersWhenTrue = 0,
BasicBlock **LoopExit = 0) {
BasicBlock *Header = L->getHeader();
- BranchInst *HeaderTerm = dyn_cast<BranchInst>(Header->getTerminator());
-
- // If the header block doesn't end with a conditional branch on Cond, we can't
- // handle it.
- if (!HeaderTerm || !HeaderTerm->isConditional() ||
- HeaderTerm->getCondition() != Cond)
- return false;
+ TerminatorInst *HeaderTerm = Header->getTerminator();
+
+ BasicBlock *LoopExitBB = 0;
+ if (BranchInst *BI = dyn_cast<BranchInst>(HeaderTerm)) {
+ // If the header block doesn't end with a conditional branch on Cond, we
+ // can't handle it.
+ if (!BI->isConditional() || BI->getCondition() != Cond)
+ return false;
- // Check to see if a successor of the branch is guaranteed to go to the latch
- // block or exit through a one exit block without having any side-effects. If
- // so, determine the value of Cond that causes it to do this.
- BasicBlock *LoopExitBlock = 0;
- if ((LoopExitBlock = isTrivialLoopExitBlock(L, HeaderTerm->getSuccessor(0)))){
- if (Val) *Val = ConstantBool::True;
- } else if ((LoopExitBlock =
- isTrivialLoopExitBlock(L, HeaderTerm->getSuccessor(1)))) {
- if (Val) *Val = ConstantBool::False;
+ // Check to see if a successor of the branch is guaranteed to go to the
+ // latch block or exit through a one exit block without having any
+ // side-effects. If so, determine the value of Cond that causes it to do
+ // this.
+ if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(0)))) {
+ if (Val) *Val = ConstantBool::True;
+ } else if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(1)))) {
+ if (Val) *Val = ConstantBool::False;
+ }
+ } else if (SwitchInst *SI = dyn_cast<SwitchInst>(HeaderTerm)) {
+ // If this isn't a switch on Cond, we can't handle it.
+ if (SI->getCondition() != Cond) return false;
+
+ // Check to see if a successor of the switch is guaranteed to go to the
+ // latch block or exit through a one exit block without having any
+ // side-effects. If so, determine the value of Cond that causes it to do
+ // this. Note that we can't trivially unswitch on the default case.
+ for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i)
+ if ((LoopExitBB = isTrivialLoopExitBlock(L, SI->getSuccessor(i)))) {
+ // Okay, we found a trivial case, remember the value that is trivial.
+ if (Val) *Val = SI->getCaseValue(i);
+ if (EntersWhenTrue) *EntersWhenTrue = false;
+ break;
+ }
}
- if (!LoopExitBlock)
+ if (!LoopExitBB)
return false; // Can't handle this.
- if (LoopExit) *LoopExit = LoopExitBlock;
+ if (LoopExit) *LoopExit = LoopExitBB;
// We already know that nothing uses any scalar values defined inside of this
// loop. As such, we just have to check to see if this loop will execute any
@@ -356,9 +373,11 @@
// If this is a trivial condition to unswitch (which results in no code
// duplication), do it now.
Constant *CondVal;
+ bool EntersWhenTrue = true;
BasicBlock *ExitBlock;
- if (IsTrivialUnswitchCondition(L, LoopCond, &CondVal, &ExitBlock)){
- UnswitchTrivialCondition(L, LoopCond, CondVal, ExitBlock);
+ if (IsTrivialUnswitchCondition(L, LoopCond, &CondVal,
+ &EntersWhenTrue, &ExitBlock)) {
+ UnswitchTrivialCondition(L, LoopCond, CondVal, EntersWhenTrue, ExitBlock);
NewLoop1 = L;
} else {
VersionLoop(LoopCond, Val, L, NewLoop1, NewLoop2);
@@ -490,12 +509,13 @@
/// side-effects), unswitch it. This doesn't involve any code duplication, just
/// moving the conditional branch outside of the loop and updating loop info.
void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
- Constant *Val,
+ Constant *Val, bool EntersWhenTrue,
BasicBlock *ExitBlock) {
DEBUG(std::cerr << "loop-unswitch: Trivial-Unswitch loop %"
<< L->getHeader()->getName() << " [" << L->getBlocks().size()
<< " blocks] in Function " << L->getHeader()->getParent()->getName()
- << " on cond:" << *Cond << "\n");
+ << " on cond: " << *Val << (EntersWhenTrue ? " == " : " != ") <<
+ *Cond << "\n");
// First step, split the preheader, so that we know that there is a safe place
// to insert the conditional branch. We will change 'OrigPH' to have a
@@ -516,14 +536,18 @@
// Okay, now we have a position to branch from and a position to branch to,
// insert the new conditional branch.
- EmitPreheaderBranchOnCondition(Cond, Val, NewPH, NewExit,
- OrigPH->getTerminator());
+ {
+ BasicBlock *TrueDest = NewPH, *FalseDest = NewExit;
+ if (!EntersWhenTrue) std::swap(TrueDest, FalseDest);
+ EmitPreheaderBranchOnCondition(Cond, Val, TrueDest, FalseDest,
+ OrigPH->getTerminator());
+ }
OrigPH->getTerminator()->eraseFromParent();
// Now that we know that the loop is never entered when this condition is a
// particular value, rewrite the loop with this info. We know that this will
// at least eliminate the old branch.
- RewriteLoopBodyWithConditionConstant(L, Cond, Val, true);
+ RewriteLoopBodyWithConditionConstant(L, Cond, Val, EntersWhenTrue);
++NumTrivial;
}
More information about the llvm-commits
mailing list