diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/LoopInfo.cpp | 9 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LICM.cpp | 9 | ||||
-rw-r--r-- | lib/Transforms/Scalar/TailDuplication.cpp | 3 | ||||
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 23 | ||||
-rw-r--r-- | lib/VMCore/Instruction.cpp | 62 |
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 } } |