diff --git a/include/llvm/Value.h b/include/llvm/Value.h index 8731aa6cb84..26d2d1df4c6 100644 --- a/include/llvm/Value.h +++ b/include/llvm/Value.h @@ -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. diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 605855d1769..a993784cd25 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -23,12 +23,15 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" #include #include #include #include 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(*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(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; } diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp index 919f4b00e87..e581fe83807 100644 --- a/lib/VMCore/Value.cpp +++ b/lib/VMCore/Value.cpp @@ -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(*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