aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Analysis/LoopInfo.cpp9
-rw-r--r--lib/Transforms/Scalar/LICM.cpp9
-rw-r--r--lib/Transforms/Scalar/TailDuplication.cpp3
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp23
-rw-r--r--lib/VMCore/Instruction.cpp62
5 files changed, 60 insertions, 46 deletions
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index d350fa6..bef6bef 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -79,14 +79,9 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
// Test if the value is already loop-invariant.
if (isLoopInvariant(I))
return true;
- // Don't hoist instructions with side-effects.
- if (I->isTrapping())
+ if (!I->isSafeToSpeculativelyExecute())
return false;
- // Don't hoist PHI nodes.
- if (isa<PHINode>(I))
- return false;
- // Don't hoist allocation instructions.
- if (isa<AllocationInst>(I))
+ if (I->mayReadFromMemory())
return false;
// Determine the insertion point, unless one was given.
if (!InsertPt) {
diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp
index 52dd06a..bdf7dee 100644
--- a/lib/Transforms/Scalar/LICM.cpp
+++ b/lib/Transforms/Scalar/LICM.cpp
@@ -623,7 +623,8 @@ void LICM::hoist(Instruction &I) {
///
bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) {
// If it is not a trapping instruction, it is always safe to hoist.
- if (!Inst.isTrapping()) return true;
+ if (Inst.isSafeToSpeculativelyExecute())
+ return true;
// Otherwise we have to check to make sure that the instruction dominates all
// of the exit blocks. If it doesn't, then there is a path out of the loop
@@ -635,12 +636,6 @@ bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) {
if (Inst.getParent() == CurLoop->getHeader())
return true;
- // It's always safe to load from a global or alloca.
- if (isa<LoadInst>(Inst))
- if (isa<AllocationInst>(Inst.getOperand(0)) ||
- isa<GlobalVariable>(Inst.getOperand(0)))
- return true;
-
// Get the exit blocks for the current loop.
SmallVector<BasicBlock*, 8> ExitBlocks;
CurLoop->getExitBlocks(ExitBlocks);
diff --git a/lib/Transforms/Scalar/TailDuplication.cpp b/lib/Transforms/Scalar/TailDuplication.cpp
index 684b0963..6d05fdf 100644
--- a/lib/Transforms/Scalar/TailDuplication.cpp
+++ b/lib/Transforms/Scalar/TailDuplication.cpp
@@ -258,7 +258,8 @@ void TailDup::eliminateUnconditionalBranch(BranchInst *Branch) {
while (!isa<TerminatorInst>(BBI)) {
Instruction *I = BBI++;
- bool CanHoist = !I->isTrapping() && !I->mayHaveSideEffects();
+ bool CanHoist = I->isSafeToSpeculativelyExecute() &&
+ !I->mayReadFromMemory();
if (CanHoist) {
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(op)))
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 55e1bf2..3b6b77f 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -384,26 +384,15 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
// 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.
+ if (!I->isSafeToSpeculativelyExecute())
+ return false;
+
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;
- // FIXME: A computation of a constant can trap!
- if (!isa<AllocaInst>(I->getOperand(0)) &&
- !isa<Constant>(I->getOperand(0)))
- return false;
- // External weak globals may have address 0, so we can't load them.
- Value *V2 = I->getOperand(0)->getUnderlyingObject();
- if (V2) {
- GlobalVariable* GV = dyn_cast<GlobalVariable>(V2);
- if (GV && GV->hasExternalWeakLinkage())
- 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.
+ // 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.
BasicBlock::iterator IP = PBB->begin();
while (isa<DbgInfoIntrinsic>(IP))
IP++;
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index 99fd8d0..e19ad1c 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -14,6 +14,8 @@
#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
+#include "llvm/Constants.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/LeakDetector.h"
using namespace llvm;
@@ -365,24 +367,56 @@ bool Instruction::isCommutative(unsigned op) {
}
}
-/// isTrapping - Return true if the instruction may trap.
-///
-bool Instruction::isTrapping(unsigned op) {
- switch(op) {
+bool Instruction::isSafeToSpeculativelyExecute() const {
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+ if (Constant *C = dyn_cast<Constant>(getOperand(i)))
+ if (C->canTrap())
+ return false;
+
+ switch (getOpcode()) {
+ default:
+ return true;
case UDiv:
+ case URem: {
+ // x / y is undefined if y == 0, but calcuations like x / 3 are safe.
+ ConstantInt *Op = dyn_cast<ConstantInt>(getOperand(1));
+ return Op && !Op->isNullValue();
+ }
case SDiv:
- case FDiv:
- case URem:
- case SRem:
- case FRem:
- case Load:
- case Store:
+ case SRem: {
+ // x / y is undefined if y == 0, and might be undefined if y == -1,
+ // but calcuations like x / 3 are safe.
+ ConstantInt *Op = dyn_cast<ConstantInt>(getOperand(1));
+ return Op && !Op->isNullValue() && !Op->isAllOnesValue();
+ }
+ case Load: {
+ if (cast<LoadInst>(this)->isVolatile())
+ return false;
+ if (isa<AllocationInst>(getOperand(0)))
+ return true;
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(getOperand(0)))
+ return !GV->hasExternalWeakLinkage();
+ // FIXME: Handle cases involving GEPs. We have to be careful because
+ // a load of a out-of-bounds GEP has undefined behavior.
+ return false;
+ }
case Call:
- case Invoke:
+ return false; // The called function could have undefined behavior or
+ // side-effects.
+ // FIXME: We should special-case some intrinsics (bswap,
+ // overflow-checking arithmetic, etc.)
case VAArg:
+ case Alloca:
+ case Malloc:
+ case Invoke:
+ case PHI:
+ case Store:
case Free:
- return true;
- default:
- return false;
+ case Ret:
+ case Br:
+ case Switch:
+ case Unwind:
+ case Unreachable:
+ return false; // Misc instructions which have effects
}
}