diff options
author | Chris Lattner <sabre@nondot.org> | 2001-06-29 23:56:58 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2001-06-29 23:56:58 +0000 |
commit | 2b05880476693393ebebba777c70ca3cbb043fc3 (patch) | |
tree | 22ae9d8b9978ff46fbc17d110f31d6fa7d1ec763 /lib/Transforms/Scalar/ConstantProp.cpp | |
parent | cb056de508c4938304b3a5a75e77eee19f6f98d1 (diff) |
Export ConstantFoldTerminator, allow it to fold conditional branches to
the same label.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/ConstantProp.cpp')
-rw-r--r-- | lib/Transforms/Scalar/ConstantProp.cpp | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/lib/Transforms/Scalar/ConstantProp.cpp b/lib/Transforms/Scalar/ConstantProp.cpp index 2df4f01a7e..51800f5a6b 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; |