diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2017-01-26 23:27:59 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2017-01-26 23:27:59 +0000 |
commit | a0a1164ce41b5fbb68d86759e96b51e8a2529ece (patch) | |
tree | eb8ceef583dfad25a2c6675d920fa2a7254fbafc /llvm/lib/IR | |
parent | 79b733bc6b8cdc856c6e5e394b77766dcf07d2f9 (diff) | |
download | bcm5719-llvm-a0a1164ce41b5fbb68d86759e96b51e8a2529ece.tar.gz bcm5719-llvm-a0a1164ce41b5fbb68d86759e96b51e8a2529ece.zip |
Add intrinsics for constrained floating point operations
This commit introduces a set of experimental intrinsics intended to prevent
optimizations that make assumptions about the rounding mode and floating point
exception behavior. These intrinsics will later be extended to specify
flush-to-zero behavior. More work is also required to model instruction
dependencies in machine code and to generate these instructions from clang
(when required by pragmas and/or command line options that are not currently
supported).
Differential Revision: https://reviews.llvm.org/D27028
llvm-svn: 293226
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/IntrinsicInst.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 18 |
2 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index 240250662ae..c9814a96bea 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -21,6 +21,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringSwitch.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Constants.h" #include "llvm/IR/GlobalVariable.h" @@ -93,3 +94,34 @@ Value *InstrProfIncrementInst::getStep() const { LLVMContext &Context = M->getContext(); return ConstantInt::get(Type::getInt64Ty(Context), 1); } + +ConstrainedFPIntrinsic::RoundingMode +ConstrainedFPIntrinsic::getRoundingMode() const { + Metadata *MD = dyn_cast<MetadataAsValue>(getOperand(2))->getMetadata(); + if (!MD || !isa<MDString>(MD)) + return rmInvalid; + StringRef RoundingArg = cast<MDString>(MD)->getString(); + + // For dynamic rounding mode, we use round to nearest but we will set the + // 'exact' SDNodeFlag so that the value will not be rounded. + return StringSwitch<RoundingMode>(RoundingArg) + .Case("round.dynamic", rmDynamic) + .Case("round.tonearest", rmToNearest) + .Case("round.downward", rmDownward) + .Case("round.upward", rmUpward) + .Case("round.towardzero", rmTowardZero) + .Default(rmInvalid); +} + +ConstrainedFPIntrinsic::ExceptionBehavior +ConstrainedFPIntrinsic::getExceptionBehavior() const { + Metadata *MD = dyn_cast<MetadataAsValue>(getOperand(3))->getMetadata(); + if (!MD || !isa<MDString>(MD)) + return ebInvalid; + StringRef ExceptionArg = cast<MDString>(MD)->getString(); + return StringSwitch<ExceptionBehavior>(ExceptionArg) + .Case("fpexcept.ignore", ebIgnore) + .Case("fpexcept.maytrap", ebMayTrap) + .Case("fpexcept.strict", ebStrict) + .Default(ebInvalid); +} diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 5855059a189..41593af000c 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -457,6 +457,7 @@ private: void visitUserOp1(Instruction &I); void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS); + void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); template <class DbgIntrinsicTy> void visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII); void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); @@ -3929,6 +3930,14 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { "constant int", CS); break; + case Intrinsic::experimental_constrained_fadd: + case Intrinsic::experimental_constrained_fsub: + case Intrinsic::experimental_constrained_fmul: + case Intrinsic::experimental_constrained_fdiv: + case Intrinsic::experimental_constrained_frem: + visitConstrainedFPIntrinsic( + cast<ConstrainedFPIntrinsic>(*CS.getInstruction())); + break; case Intrinsic::dbg_declare: // llvm.dbg.declare Assert(isa<MetadataAsValue>(CS.getArgOperand(0)), "invalid llvm.dbg.declare intrinsic call 1", CS); @@ -4294,6 +4303,15 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) { return nullptr; } +void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { + Assert(isa<MetadataAsValue>(FPI.getOperand(2)), + "invalid rounding mode argument", &FPI); + Assert(FPI.getRoundingMode() != ConstrainedFPIntrinsic::rmInvalid, + "invalid rounding mode argument", &FPI); + Assert(FPI.getExceptionBehavior() != ConstrainedFPIntrinsic::ebInvalid, + "invalid exception behavior argument", &FPI); +} + template <class DbgIntrinsicTy> void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata(); |