Implement SimplifyCFG/branch-cond-merge.ll
authorChris Lattner <sabre@nondot.org>
Sat, 1 May 2004 23:35:43 +0000 (23:35 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 1 May 2004 23:35:43 +0000 (23:35 +0000)
Turning "if (A < B && B < C)" into "if (A < B & B < C)"

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13311 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyCFG.cpp

index 7f2060fbfc8293e8d2553f995e489bb9865ac01a..dedaa6a657c21132b0dc9ce0ec43c33737d2db5b 100644 (file)
@@ -790,17 +790,71 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
       if (FoldValueComparisonIntoPredecessors(SI))
         return SimplifyCFG(BB) || 1;
   } else if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
-    if (Value *CompVal = isValueEqualityComparison(BB->getTerminator())) {
-      // This block must be empty, except for the setcond inst, if it exists.
-      BasicBlock::iterator I = BB->begin();
-      if (&*I == BI ||
-          (&*I == cast<Instruction>(BI->getCondition()) &&
-           &*++I == BI))
-        if (FoldValueComparisonIntoPredecessors(BI))
-          return SimplifyCFG(BB) | true;
-    }
-
     if (BI->isConditional()) {
+      if (Value *CompVal = isValueEqualityComparison(BI)) {
+        // This block must be empty, except for the setcond inst, if it exists.
+        BasicBlock::iterator I = BB->begin();
+        if (&*I == BI ||
+            (&*I == cast<Instruction>(BI->getCondition()) &&
+             &*++I == BI))
+          if (FoldValueComparisonIntoPredecessors(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
+      // predecessor and use logical operations to pick the right destination.
+      if (Instruction *Cond = dyn_cast<Instruction>(BI->getCondition()))
+        if (Cond->getParent() == BB && &BB->front() == Cond &&
+            Cond->getNext() == BI && Cond->hasOneUse()) {
+          BasicBlock *TrueDest  = BI->getSuccessor(0);
+          BasicBlock *FalseDest = BI->getSuccessor(1);
+
+          for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI!=E; ++PI)
+            if (BranchInst *PBI = dyn_cast<BranchInst>((*PI)->getTerminator()))
+              if (PBI->isConditional()) {
+                if (PBI->getSuccessor(0) == FalseDest ||
+                    PBI->getSuccessor(1) == TrueDest) {
+                  // Invert the predecessors condition test (xor it with true),
+                  // which allows us to write this code once.
+                  Value *NewCond =
+                    BinaryOperator::createNot(PBI->getCondition(),
+                                    PBI->getCondition()->getName()+".not", PBI);
+                  PBI->setCondition(NewCond);
+                  BasicBlock *OldTrue = PBI->getSuccessor(0);
+                  BasicBlock *OldFalse = PBI->getSuccessor(1);
+                  PBI->setSuccessor(0, OldFalse);
+                  PBI->setSuccessor(1, OldTrue);
+                }
+
+                if (PBI->getSuccessor(0) == TrueDest ||
+                    PBI->getSuccessor(1) == FalseDest) {
+                  // Clone Cond into the predecessor basic block, and and the
+                  // two conditions together.
+                  Instruction *New = Cond->clone();
+                  New->setName(Cond->getName());
+                  Cond->setName(Cond->getName()+".old");
+                  (*PI)->getInstList().insert(PBI, New);
+                  Instruction::BinaryOps Opcode =
+                    PBI->getSuccessor(0) == TrueDest ?
+                    Instruction::Or : Instruction::And;
+                  Value *NewCond = 
+                    BinaryOperator::create(Opcode, PBI->getCondition(),
+                                           New, "bothcond", PBI);
+                  PBI->setCondition(NewCond);
+                  if (PBI->getSuccessor(0) == BB) {
+                    AddPredecessorToBlock(TrueDest, *PI, BB);
+                    PBI->setSuccessor(0, TrueDest);
+                  }
+                  if (PBI->getSuccessor(1) == BB) {
+                    AddPredecessorToBlock(FalseDest, *PI, BB);
+                    PBI->setSuccessor(1, FalseDest);
+                  }
+                  return SimplifyCFG(BB) | 1;
+                }
+              }
+        }
+
       // If this block ends with a branch instruction, and if there is one
       // predecessor, see if the previous block ended with a branch on the same
       // condition, which makes this conditional branch redundant.