summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/ConstantProp.cpp38
1 files changed, 30 insertions, 8 deletions
diff --git a/lib/Transforms/Scalar/ConstantProp.cpp b/lib/Transforms/Scalar/ConstantProp.cpp
index 2df4f01..51800f5 100644
--- a/lib/Transforms/Scalar/ConstantProp.cpp
+++ b/lib/Transforms/Scalar/ConstantProp.cpp
@@ -120,28 +120,50 @@ ConstantFoldBinaryInst(Method *M, Method::inst_iterator &DI,
return true;
}
-inline static bool ConstantFoldTerminator(TerminatorInst *T) {
+// ConstantFoldTerminator - If a terminator instruction is predicated on a
+// constant value, convert it into an unconditional branch to the constant
+// destination.
+//
+bool ConstantFoldTerminator(TerminatorInst *T) {
// Branch - See if we are conditional jumping on constant
if (T->getInstType() == Instruction::Br) {
BranchInst *BI = (BranchInst*)T;
- if (!BI->isUnconditional() && // Are we branching on constant?
- BI->getOperand(2)->isConstant()) {
+ if (BI->isUnconditional()) return false; // Can't optimize uncond branch
+ BasicBlock *Dest1 = BI->getOperand(0)->castBasicBlockAsserting();
+ BasicBlock *Dest2 = BI->getOperand(1)->castBasicBlockAsserting();
+
+ if (BI->getOperand(2)->isConstant()) { // Are we branching on constant?
// YES. Change to unconditional branch...
ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
- Value *Destination = BI->getOperand(Cond->getValue() ? 0 : 1);
- Value *OldDest = BI->getOperand(Cond->getValue() ? 1 : 0);
+ BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2;
+ BasicBlock *OldDest = Cond->getValue() ? Dest2 : Dest1;
- //cerr << "Method: " << T->getParent()->getParent() << "\nRemoving branch from " << T->getParent() << "\n\nTo: " << OldDest << endl;
+ //cerr << "Method: " << T->getParent()->getParent()
+ // << "\nRemoving branch from " << T->getParent()
+ // << "\n\nTo: " << OldDest << endl;
// Let the basic block know that we are letting go of it. Based on this,
// it will adjust it's PHI nodes.
- assert(T->getParent() && "Terminator not inserted in block!");
- OldDest->castBasicBlockAsserting()->removePredecessor(T->getParent());
+ assert(BI->getParent() && "Terminator not inserted in block!");
+ OldDest->removePredecessor(BI->getParent());
BI->setOperand(0, Destination); // Set the unconditional destination
BI->setOperand(1, 0); // Clear the conditional destination
BI->setOperand(2, 0); // Clear the condition...
return true;
+ } else if (Dest2 == Dest1) { // Conditional branch to same location?
+ // This branch matches something like this:
+ // br bool %cond, label %Dest, label %Dest
+ // and changes it into: br label %Dest
+
+ // Let the basic block know that we are letting go of one copy of it.
+ assert(BI->getParent() && "Terminator not inserted in block!");
+ Dest1->removePredecessor(BI->getParent());
+
+ // Nuke the second destination, and the use of the condition variable
+ BI->setOperand(1, 0); // Clear the conditional destination
+ BI->setOperand(2, 0); // Clear the condition...
+ return true;
}
}
return false;