[llvm-commits] CVS: llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Apr 9 17:51:01 PDT 2004


Changes in directory llvm/lib/Transforms/Utils:

SimplifyCFG.cpp updated: 1.34 -> 1.35

---
Log message:

Fold code like:
  if (C)
    V1 |= V2;

into:
  Vx = V1 | V2;
  V1 = select C, V1, Vx

when the expression can be evaluated unconditionally and is *cheap* to 
execute.  This limited form of if conversion is quite handy in lots of cases.
For example, it turns this testcase into straight-line code:

int in0 ; int in1 ; int in2 ; int in3 ;
int in4 ; int in5 ; int in6 ; int in7 ;
int in8 ; int in9 ; int in10; int in11;
int in12; int in13; int in14; int in15;
long output;

void mux(void) {
  output =
      (in0   ?  0x00000001 : 0) | (in1   ?  0x00000002 : 0) |
      (in2   ?  0x00000004 : 0) | (in3   ?  0x00000008 : 0) |
      (in4   ?  0x00000010 : 0) | (in5   ?  0x00000020 : 0) |
      (in6   ?  0x00000040 : 0) | (in7   ?  0x00000080 : 0) |
      (in8   ?  0x00000100 : 0) | (in9   ?  0x00000200 : 0) |
      (in10  ?  0x00000400 : 0) | (in11  ?  0x00000800 : 0) |
      (in12  ?  0x00001000 : 0) | (in13  ?  0x00002000 : 0) |
      (in14  ?  0x00004000 : 0) | (in15  ?  0x00008000 : 0) ;
}




---
Diffs of the changes:  (+72 -18)

Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff -u llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.34 llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.35
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.34	Fri Apr  2 12:15:10 2004
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp	Fri Apr  9 17:50:22 2004
@@ -182,23 +182,59 @@
 // if the specified value dominates the block.  We don't handle the true
 // generality of domination here, just a special case which works well enough
 // for us.
-static bool DominatesMergePoint(Value *V, BasicBlock *BB) {
-  if (Instruction *I = dyn_cast<Instruction>(V)) {
-    BasicBlock *PBB = I->getParent();
-    // If this instruction is defined in a block that contains an unconditional
-    // branch to BB, then it must be in the 'conditional' part of the "if
-    // statement".
-    if (isa<BranchInst>(PBB->getTerminator()) && 
-        cast<BranchInst>(PBB->getTerminator())->isUnconditional() && 
-        cast<BranchInst>(PBB->getTerminator())->getSuccessor(0) == BB)
-      return false;
-
-    // We also don't want to allow wierd loops that might have the "if
-    // condition" in the bottom of this block.
-    if (PBB == BB) return false;
-  }
+static bool DominatesMergePoint(Value *V, BasicBlock *BB, bool AllowAggressive){
+  Instruction *I = dyn_cast<Instruction>(V);
+  if (!I) return true;    // Non-instructions all dominate instructions.
+  BasicBlock *PBB = I->getParent();
+
+  // We don't want to allow wierd loops that might have the "if condition" in
+  // the bottom of this block.
+  if (PBB == BB) return false;
+
+  // If this instruction is defined in a block that contains an unconditional
+  // branch to BB, then it must be in the 'conditional' part of the "if
+  // statement".
+  if (BranchInst *BI = dyn_cast<BranchInst>(PBB->getTerminator()))
+    if (BI->isUnconditional() && BI->getSuccessor(0) == BB) {
+      if (!AllowAggressive) return false;
+      // Okay, it looks like the instruction IS in the "condition".  Check to
+      // see if its a cheap instruction to unconditionally compute, and if it
+      // only uses stuff defined outside of the condition.  If so, hoist it out.
+      switch (I->getOpcode()) {
+      default: return false;  // Cannot hoist this out safely.
+      case Instruction::Load:
+        // We can hoist loads that are non-volatile and obviously cannot trap.
+        if (cast<LoadInst>(I)->isVolatile())
+          return false;
+        if (!isa<AllocaInst>(I->getOperand(0)) &&
+            !isa<Constant>(I->getOperand(0)) &&
+            !isa<GlobalValue>(I->getOperand(0)))
+          return false;
+
+        // Finally, we have to check to make sure there are no instructions
+        // before the load in its basic block, as we are going to hoist the loop
+        // out to its predecessor.
+        if (PBB->begin() != BasicBlock::iterator(I))
+          return false;
+        break;
+      case Instruction::Add:
+      case Instruction::Sub:
+      case Instruction::And:
+      case Instruction::Or:
+      case Instruction::Xor:
+      case Instruction::Shl:
+      case Instruction::Shr:
+        break;   // These are all cheap and non-trapping instructions.
+      }
+      
+      // Okay, we can only really hoist these out if their operands are not
+      // defined in the conditional region.
+      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+        if (!DominatesMergePoint(I->getOperand(i), BB, false))
+          return false;
+      // Okay, it's safe to do this!
+    }
 
-  // Non-instructions all dominate instructions.
   return true;
 }
 
@@ -904,12 +940,30 @@
           // incoming values are defined in the conditional parts of the branch,
           // so check for this.
           //
-          if (DominatesMergePoint(PN->getIncomingValue(0), BB) &&
-              DominatesMergePoint(PN->getIncomingValue(1), BB)) {
+          if (DominatesMergePoint(PN->getIncomingValue(0), BB, true) &&
+              DominatesMergePoint(PN->getIncomingValue(1), BB, true)) {
             Value *TrueVal =
               PN->getIncomingValue(PN->getIncomingBlock(0) == IfFalse);
             Value *FalseVal =
               PN->getIncomingValue(PN->getIncomingBlock(0) == IfTrue);
+
+            // If one of the incoming values is defined in the conditional
+            // region, move it into it's predecessor block, which we know is
+            // safe.
+            if (!DominatesMergePoint(TrueVal, BB, false)) {
+              Instruction *TrueI = cast<Instruction>(TrueVal);
+              BasicBlock *OldBB = TrueI->getParent();
+              OldBB->getInstList().remove(TrueI);
+              BasicBlock *NewBB = *pred_begin(OldBB);
+              NewBB->getInstList().insert(NewBB->getTerminator(), TrueI);
+            }
+            if (!DominatesMergePoint(FalseVal, BB, false)) {
+              Instruction *FalseI = cast<Instruction>(FalseVal);
+              BasicBlock *OldBB = FalseI->getParent();
+              OldBB->getInstList().remove(FalseI);
+              BasicBlock *NewBB = *pred_begin(OldBB);
+              NewBB->getInstList().insert(NewBB->getTerminator(), FalseI);
+            }
 
             // Change the PHI node into a select instruction.
             BasicBlock::iterator InsertPos = PN;





More information about the llvm-commits mailing list