Do not speculatively execute an instruction by hoisting it to its predecessor BB...
authorEvan Cheng <evan.cheng@apple.com>
Thu, 12 Jun 2008 21:15:59 +0000 (21:15 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 12 Jun 2008 21:15:59 +0000 (21:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52244 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Value.h
lib/Transforms/Utils/SimplifyCFG.cpp
lib/VMCore/Value.cpp

index 8731aa6cb8403d6871230de841dfa9b463ae97c3..26d2d1df4c65f66fd389285596694c3bb6b9143c 100644 (file)
@@ -161,6 +161,8 @@ public:
   ///
   bool hasNUsesOrMore(unsigned N) const;
 
+  bool isUsedInBasicBlock(BasicBlock *BB) const;
+
   /// getNumUses - This method computes the number of uses of this Value.  This
   /// is a linear time operation.  Use hasOneUse, hasNUses, or hasMoreThanNUses
   /// to check for specific values.
index 605855d1769899cfbaf73822c56865d8f41c42a0..a993784cd25125f590e77531a200316016bc550f 100644 (file)
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Statistic.h"
 #include <algorithm>
 #include <functional>
 #include <set>
 #include <map>
 using namespace llvm;
 
+STATISTIC(NumSpeculations, "Number of speculative executed instructions");
+
 /// SafeToMergeTerminators - Return true if it is safe to merge these two
 /// terminator instructions together.
 ///
@@ -1030,12 +1033,22 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) {
   if (!FalseV)  // Can this happen?
     return false;
 
+  // Do not hoist the instruction if any of its operands are defined but not
+  // used in this BB. The transformation will prevent the operand from
+  // being sunk into the use block.
+  for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) {
+    Instruction *OpI = dyn_cast<Instruction>(*i);
+    if (OpI && OpI->getParent() == BIParent &&
+        !OpI->isUsedInBasicBlock(BIParent))
+      return false;
+  }
+
   // If we get here, we can hoist the instruction. Try to place it before the
-  // icmp / fcmp instruction preceeding the conditional branch.
+  // icmp instruction preceeding the conditional branch.
   BasicBlock::iterator InsertPos = BI;
   if (InsertPos != BIParent->begin())
     --InsertPos;
-  if (InsertPos == BrCond)
+  if (InsertPos == BrCond && !isa<PHINode>(BrCond))
     BIParent->getInstList().splice(InsertPos, BB1->getInstList(), I);
   else
     BIParent->getInstList().splice(BI, BB1->getInstList(), I);
@@ -1060,6 +1073,7 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) {
         PN->setIncomingValue(j, SI);
   }
 
+  ++NumSpeculations;
   return true;
 }
 
index 919f4b00e87319c3df48821e66792b8d14a13de5..e581fe83807331d7569e4c55e09c167a998f5741 100644 (file)
@@ -93,6 +93,17 @@ bool Value::hasNUsesOrMore(unsigned N) const {
   return true;
 }
 
+/// isUsedInBasicBlock - Return true if this value is used in the specified
+/// basic block.
+bool Value::isUsedInBasicBlock(BasicBlock *BB) const {
+  for (use_const_iterator I = use_begin(), E = use_end(); I != E; ++I) {
+    const Instruction *User = dyn_cast<Instruction>(*I);
+    if (User && User->getParent() == BB)
+      return true;
+  }
+  return false;
+}
+
 
 /// getNumUses - This method computes the number of uses of this Value.  This
 /// is a linear time operation.  Use hasOneUse or hasNUses to check for specific