[llvm-commits] CVS: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Fri Sep 23 11:47:31 PDT 2005
Changes in directory llvm/lib/Transforms/Utils:
SimplifyCFG.cpp updated: 1.89 -> 1.90
---
Log message:
Fold two consequtive branches that share a common destination between them.
This implements SimplifyCFG/branch-fold.ll, and is useful on ?:/min/max heavy
code
---
Diffs of the changes: (+119 -33)
SimplifyCFG.cpp | 152 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 119 insertions(+), 33 deletions(-)
Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff -u llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.89 llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.90
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.89 Fri Sep 23 02:23:18 2005
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp Fri Sep 23 13:47:20 2005
@@ -1207,6 +1207,8 @@
if (!UncondBranchPreds.empty()) {
while (!UncondBranchPreds.empty()) {
BasicBlock *Pred = UncondBranchPreds.back();
+ DEBUG(std::cerr << "FOLDING: " << *BB
+ << "INTO UNCOND BRANCH PRED: " << *Pred);
UncondBranchPreds.pop_back();
Instruction *UncondBranch = Pred->getTerminator();
// Clone the return and add it to the end of the predecessor.
@@ -1386,7 +1388,6 @@
if (PN->getParent() == BI->getParent())
if (FoldCondBranchOnPHI(BI))
return SimplifyCFG(BB) | true;
-
// If this basic block is ONLY a setcc and a branch, and if a predecessor
// branches to us and one of our successors, fold the setcc into the
@@ -1442,43 +1443,128 @@
}
}
- // If this block ends with a branch instruction, and if there is a
- // predecessor that ends on a branch of the same condition, make this
- // conditional branch redundant.
+ // Scan predessor blocks for conditional branchs.
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
if (BranchInst *PBI = dyn_cast<BranchInst>((*PI)->getTerminator()))
- if (PBI != BI && PBI->isConditional() &&
- PBI->getCondition() == BI->getCondition() &&
- PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
- // Okay, the outcome of this conditional branch is statically
- // knowable. If this block had a single pred, handle specially.
- if (BB->getSinglePredecessor()) {
- // Turn this into a branch on constant.
- bool CondIsTrue = PBI->getSuccessor(0) == BB;
- BI->setCondition(ConstantBool::get(CondIsTrue));
- return SimplifyCFG(BB); // Nuke the branch on constant.
+ if (PBI != BI && PBI->isConditional()) {
+
+ // If this block ends with a branch instruction, and if there is a
+ // predecessor that ends on a branch of the same condition, make this
+ // conditional branch redundant.
+ if (PBI->getCondition() == BI->getCondition() &&
+ PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
+ // Okay, the outcome of this conditional branch is statically
+ // knowable. If this block had a single pred, handle specially.
+ if (BB->getSinglePredecessor()) {
+ // Turn this into a branch on constant.
+ bool CondIsTrue = PBI->getSuccessor(0) == BB;
+ BI->setCondition(ConstantBool::get(CondIsTrue));
+ return SimplifyCFG(BB); // Nuke the branch on constant.
+ }
+
+ // Otherwise, if there are multiple predecessors, insert a PHI that
+ // merges in the constant and simplify the block result.
+ if (BlockIsSimpleEnoughToThreadThrough(BB)) {
+ PHINode *NewPN = new PHINode(Type::BoolTy,
+ BI->getCondition()->getName()+".pr",
+ BB->begin());
+ for (PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+ if ((PBI = dyn_cast<BranchInst>((*PI)->getTerminator())) &&
+ PBI != BI && PBI->isConditional() &&
+ PBI->getCondition() == BI->getCondition() &&
+ PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
+ bool CondIsTrue = PBI->getSuccessor(0) == BB;
+ NewPN->addIncoming(ConstantBool::get(CondIsTrue), *PI);
+ } else {
+ NewPN->addIncoming(BI->getCondition(), *PI);
+ }
+
+ BI->setCondition(NewPN);
+ // This will thread the branch.
+ return SimplifyCFG(BB) | true;
+ }
}
- // Otherwise, if there are multiple predecessors, insert a PHI that
- // merges in the constant and simplify the block result.
- if (BlockIsSimpleEnoughToThreadThrough(BB)) {
- PHINode *NewPN = new PHINode(Type::BoolTy,
- BI->getCondition()->getName()+".pr",
- BB->begin());
- for (PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
- if ((PBI = dyn_cast<BranchInst>((*PI)->getTerminator())) &&
- PBI != BI && PBI->isConditional() &&
- PBI->getCondition() == BI->getCondition() &&
- PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
- bool CondIsTrue = PBI->getSuccessor(0) == BB;
- NewPN->addIncoming(ConstantBool::get(CondIsTrue), *PI);
- } else {
- NewPN->addIncoming(BI->getCondition(), *PI);
- }
+ // If this is a conditional branch in an empty block, and if any
+ // predecessors is a conditional branch to one of our destinations,
+ // fold the conditions into logical ops and one cond br.
+ if (&BB->front() == BI) {
+ int PBIOp, BIOp;
+ if (PBI->getSuccessor(0) == BI->getSuccessor(0)) {
+ PBIOp = BIOp = 0;
+ } else if (PBI->getSuccessor(0) == BI->getSuccessor(1)) {
+ PBIOp = 0; BIOp = 1;
+ } else if (PBI->getSuccessor(1) == BI->getSuccessor(0)) {
+ PBIOp = 1; BIOp = 0;
+ } else if (PBI->getSuccessor(1) == BI->getSuccessor(1)) {
+ PBIOp = BIOp = 1;
+ } else {
+ PBIOp = BIOp = -1;
+ }
- BI->setCondition(NewPN);
- // This will thread the branch.
- return SimplifyCFG(BB) | true;
+ // Finally, if everything is ok, fold the branches to logical ops.
+ if (PBIOp != -1) {
+ BasicBlock *CommonDest = PBI->getSuccessor(PBIOp);
+ BasicBlock *OtherDest = BI->getSuccessor(BIOp ^ 1);
+
+ DEBUG(std::cerr << "FOLDING BRs:" << *PBI->getParent()
+ << "AND: " << *BI->getParent());
+
+ // BI may have other predecessors. Because of this, we leave
+ // it alone, but modify PBI.
+
+ // Make sure we get to CommonDest on True&True directions.
+ Value *PBICond = PBI->getCondition();
+ if (PBIOp)
+ PBICond = BinaryOperator::createNot(PBICond,
+ PBICond->getName()+".not",
+ PBI);
+ Value *BICond = BI->getCondition();
+ if (BIOp)
+ BICond = BinaryOperator::createNot(BICond,
+ BICond->getName()+".not",
+ PBI);
+ // Merge the conditions.
+ Value *Cond =
+ BinaryOperator::createOr(PBICond, BICond, "brmerge", PBI);
+
+ // Modify PBI to branch on the new condition to the new dests.
+ PBI->setCondition(Cond);
+ PBI->setSuccessor(0, CommonDest);
+ PBI->setSuccessor(1, OtherDest);
+
+ // OtherDest may have phi nodes. If so, add an entry from PBI's
+ // block that are identical to the entries for BI's block.
+ PHINode *PN;
+ for (BasicBlock::iterator II = OtherDest->begin();
+ (PN = dyn_cast<PHINode>(II)); ++II) {
+ Value *V = PN->getIncomingValueForBlock(BB);
+ PN->addIncoming(V, PBI->getParent());
+ }
+
+ // We know that the CommonDest already had an edge from PBI to
+ // it. If it has PHIs though, the PHIs may have different
+ // entries for BB and PBI's BB. If so, insert a select to make
+ // them agree.
+ for (BasicBlock::iterator II = CommonDest->begin();
+ (PN = dyn_cast<PHINode>(II)); ++II) {
+ Value * BIV = PN->getIncomingValueForBlock(BB);
+ unsigned PBBIdx = PN->getBasicBlockIndex(PBI->getParent());
+ Value *PBIV = PN->getIncomingValue(PBBIdx);
+ if (BIV != PBIV) {
+ // Insert a select in PBI to pick the right value.
+ Value *NV = new SelectInst(PBICond, PBIV, BIV,
+ PBIV->getName()+".mux", PBI);
+ PN->setIncomingValue(PBBIdx, NV);
+ }
+ }
+
+ DEBUG(std::cerr << "INTO: " << *PBI->getParent());
+
+ // This basic block is probably dead. We know it has at least
+ // one fewer predecessor.
+ return SimplifyCFG(BB) | true;
+ }
}
}
}
More information about the llvm-commits
mailing list