summaryrefslogtreecommitdiffstats
path: root/llvm/lib/VMCore/Instruction.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-07-17 04:28:42 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-07-17 04:28:42 +0000
commitb8f6a4fc8e554d44d9dd4759f503ee74f5cc58df (patch)
treeb9ca4e65ad9c2e10f23f15fda8f426c8d283f294 /llvm/lib/VMCore/Instruction.cpp
parent1fa07e1aeaac2347e549056093bbc60dac4f7941 (diff)
downloadbcm5719-llvm-b8f6a4fc8e554d44d9dd4759f503ee74f5cc58df.tar.gz
bcm5719-llvm-b8f6a4fc8e554d44d9dd4759f503ee74f5cc58df.zip
Replace isTrapping with a new, similar method called
isSafeToSpeculativelyExecute. The new method is a bit closer to what the callers actually care about in that it rejects more things callers don't want. It also adds more precise handling for integer division, and unifies code for analyzing the legality of a speculative load. llvm-svn: 76150
Diffstat (limited to 'llvm/lib/VMCore/Instruction.cpp')
-rw-r--r--llvm/lib/VMCore/Instruction.cpp62
1 files changed, 48 insertions, 14 deletions
diff --git a/llvm/lib/VMCore/Instruction.cpp b/llvm/lib/VMCore/Instruction.cpp
index 99fd8d09e5b..e19ad1c16f9 100644
--- a/llvm/lib/VMCore/Instruction.cpp
+++ b/llvm/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
}
}
OpenPOWER on IntegriCloud