[llvm-commits] [llvm] r52073 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/SpeculativeExec.ll

Evan Cheng evan.cheng at apple.com
Sat Jun 7 01:52:29 PDT 2008


Author: evancheng
Date: Sat Jun  7 03:52:29 2008
New Revision: 52073

URL: http://llvm.org/viewvc/llvm-project?rev=52073&view=rev
Log:
Speculatively execute a block when the the block is the then part of a triangle shape and it contains a single, side effect free, cheap instruction. The branch is eliminated by adding a select instruction. i.e.

Turn                                                                                                                                                                                                       
BB:                                                                                                                                                                                                        
    %t1 = icmp                                                                                                                                                                                             
    br i1 %t1, label %BB1, label %BB2                                                                                                                                                                      
BB1:                                                                                                                                                                                                       
    %t3 = add %t2, c                                                                                                                                                                                       
    br label BB2                                                                                                                                                                                           
BB2:                                                                                                                                                                                                       
=>                                                                                                                                                                                                         
BB:                                                                                                                                                                                                        
    %t1 = icmp                                                                                                                                                                                             
    %t4 = add %t2, c                                                                                                                                                                                       
    %t3 = select i1 %t1, %t2, %t3

Added:
    llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=52073&r1=52072&r2=52073&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Sat Jun  7 03:52:29 2008
@@ -955,6 +955,109 @@
   return true;
 }
 
+/// SpeculativelyExecuteBB - Given a conditional branch that goes to BB1
+/// and an BB2 and the only successor of BB1 is BB2, hoist simple code
+/// (for now, restricted to a single instruction that's side effect free) from
+/// the BB1 into the branch block to speculatively execute it.
+static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) {
+  // Only speculatively execution a single instruction (not counting the
+  // terminator) for now.
+  if (BB1->size() != 2)
+    return false;
+
+  // If BB1 is actually on the false edge of the conditional branch, remember
+  // to swap the select operands later.
+  bool Invert = false;
+  if (BB1 != BI->getSuccessor(0)) {
+    assert(BB1 == BI->getSuccessor(1) && "No edge from 'if' block?");
+    Invert = true;
+  }
+
+  // Turn
+  // BB:
+  //     %t1 = icmp
+  //     br i1 %t1, label %BB1, label %BB2
+  // BB1:
+  //     %t3 = add %t2, c
+  //     br label BB2
+  // BB2:
+  // =>
+  // BB:
+  //     %t1 = icmp
+  //     %t4 = add %t2, c
+  //     %t3 = select i1 %t1, %t2, %t3
+  Instruction *I = BB1->begin();
+  switch (I->getOpcode()) {
+  default: return false;  // Not safe / profitable to hoist.
+  case Instruction::Add:
+  case Instruction::Sub:
+  case Instruction::And:
+  case Instruction::Or:
+  case Instruction::Xor:
+  case Instruction::Shl:
+  case Instruction::LShr:
+  case Instruction::AShr:
+    if (I->getOperand(0)->getType()->isFPOrFPVector())
+      return false;  // FP arithmetic might trap.
+    break;   // These are all cheap and non-trapping instructions.
+  }
+
+  // Can we speculatively execute the instruction? And what is the value 
+  // if the condition is false? Consider the phi uses, if the incoming value
+  // from the "if" block are all the same V, then V is the value of the
+  // select if the condition is false.
+  BasicBlock *BIParent = BI->getParent();
+  SmallVector<PHINode*, 4> PHIUses;
+  Value *FalseV = NULL;
+  for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
+       UI != E; ++UI) {
+    PHINode *PN = dyn_cast<PHINode>(UI);
+    if (!PN)
+      continue;
+    PHIUses.push_back(PN);
+    Value *PHIV = PN->getIncomingValueForBlock(BIParent);
+    if (!FalseV)
+      FalseV = PHIV;
+    else if (FalseV != PHIV)
+      return false;  // Don't know the value when condition is false.
+  }
+  if (!FalseV)  // Can this happen?
+    return false;
+
+  // If we get here, we can hoist the instruction. Try to place it before the
+  // icmp / fcmp instruction preceeding the conditional branch.
+  BasicBlock::iterator InsertPos = BI;
+  if (InsertPos != BIParent->begin())
+    --InsertPos;
+  if (InsertPos->getOpcode() == Instruction::ICmp ||
+      InsertPos->getOpcode() == Instruction::FCmp)
+    BIParent->getInstList().splice(InsertPos, BB1->getInstList(), I);
+  else
+    BIParent->getInstList().splice(BI, BB1->getInstList(), I);
+
+  // Create a select whose true value is the speculatively executed value and
+  // false value is the previously determined FalseV.
+  SelectInst *SI;
+  if (Invert)
+    SI = SelectInst::Create(BI->getCondition(), FalseV, I,
+                            FalseV->getName() + "." + I->getName(), BI);
+  else
+    SI = SelectInst::Create(BI->getCondition(), I, FalseV,
+                            I->getName() + "." + FalseV->getName(), BI);
+
+  // Make the PHI node use the select for all incoming values for "then" and
+  // "if" blocks.
+  for (unsigned i = 0, e = PHIUses.size(); i != e; ++i) {
+    PHINode *PN = PHIUses[i];
+    for (unsigned j = 0, ee = PN->getNumIncomingValues(); j != ee; ++j)
+      if (PN->getIncomingBlock(j) == BB1 ||
+          PN->getIncomingBlock(j) == BIParent)
+        PN->setIncomingValue(j, SI);
+  }
+
+  return true;
+}
+
 /// BlockIsSimpleEnoughToThreadThrough - Return true if we can thread a branch
 /// across this block.
 static bool BlockIsSimpleEnoughToThreadThrough(BasicBlock *BB) {
@@ -1928,6 +2031,24 @@
           // so see if there is any identical code in the "then" and "else"
           // blocks.  If so, we can hoist it up to the branching block.
           Changed |= HoistThenElseCodeToIf(BI);
+        } else {
+          OnlySucc = NULL;
+          for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
+               SI != SE; ++SI) {
+            if (!OnlySucc)
+              OnlySucc = *SI;
+            else if (*SI != OnlySucc) {
+              OnlySucc = 0;     // There are multiple distinct successors!
+              break;
+            }
+          }
+
+          if (OnlySucc == OtherBB) {
+            // If BB's only successor is the other successor of the predecessor,
+            // i.e. a triangle, see if we can hoist any code from this block up
+            // to the "if" block.
+            Changed |= SpeculativelyExecuteBB(BI, BB);
+          }
         }
       }
 

Added: llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll?rev=52073&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll Sat Jun  7 03:52:29 2008
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | opt -simplifycfg  | llvm-dis | grep select
+; RUN: llvm-as < %s | opt -simplifycfg  | llvm-dis | grep br | count 2
+
+define i32 @t2(i32 %a, i32 %b, i32 %c) nounwind  {
+entry:
+        %tmp1 = icmp eq i32 %b, 0
+        br i1 %tmp1, label %bb1, label %bb3
+
+bb1:            ; preds = %entry
+	%tmp2 = icmp sgt i32 %c, 1
+	br i1 %tmp2, label %bb2, label %bb3
+
+bb2:		; preds = bb1
+	%tmp3 = add i32 %a, 1
+	br label %bb3
+
+bb3:		; preds = %bb2, %entry
+	%tmp4 = phi i32 [ %b, %entry ], [ %a, %bb1 ], [ %tmp3, %bb2 ]
+        %tmp5 = sub i32 %tmp4, 1
+	ret i32 %tmp5
+}





More information about the llvm-commits mailing list