From 502a4f5162498ec420e3cb22f667808d726dd7da Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 12 Jun 2008 21:15:59 +0000 Subject: [PATCH] Do not speculatively execute an instruction by hoisting it to its predecessor BB if any of its operands are defined but not used in BB. The transformation will prevent the operand from being sunk into the use block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52244 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Value.h | 2 ++ lib/Transforms/Utils/SimplifyCFG.cpp | 18 ++++++++++++++++-- lib/VMCore/Value.cpp | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) 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