diff --git a/llvm/include/llvm/IR/FPEnv.h b/llvm/include/llvm/IR/FPEnv.h --- a/llvm/include/llvm/IR/FPEnv.h +++ b/llvm/include/llvm/IR/FPEnv.h @@ -21,6 +21,12 @@ namespace llvm { +namespace Intrinsic { +typedef unsigned ID; +} + +class Instruction; + namespace fp { /// Rounding mode used for floating point operations. @@ -66,5 +72,11 @@ /// input in constrained intrinsic exception behavior metadata. Optional ExceptionBehaviorToStr(fp::ExceptionBehavior); +/// Returns constrained intrinsic id to represent the source instruction, if +/// it involves floating point operations. If the instruction is already a +/// constrained intrinsic or does not involve floating point operations, the +/// function returns zero. +Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr); + } #endif diff --git a/llvm/lib/IR/FPEnv.cpp b/llvm/lib/IR/FPEnv.cpp --- a/llvm/lib/IR/FPEnv.cpp +++ b/llvm/lib/IR/FPEnv.cpp @@ -14,6 +14,9 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/FPEnv.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/IntrinsicInst.h" namespace llvm { @@ -75,4 +78,43 @@ return ExceptStr; } +Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) { + Intrinsic::ID IID = Intrinsic::not_intrinsic; + switch (Instr.getOpcode()) { + case Instruction::FCmp: + IID = Intrinsic::experimental_constrained_fcmp; + break; + + // Instructions +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ + case Instruction::NAME: \ + IID = Intrinsic::INTRINSIC; \ + break; +#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) +#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) +#include "llvm/IR/ConstrainedOps.def" + + // Intrinsic calls. + case Instruction::Call: + if (auto *IntrinCall = dyn_cast(&Instr)) { + switch (IntrinCall->getIntrinsicID()) { +#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ + case Intrinsic::NAME: \ + IID = Intrinsic::INTRINSIC; \ + break; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) +#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) +#include "llvm/IR/ConstrainedOps.def" + default: + break; + } + } + break; + default: + break; + } + + return IID; +} + } \ No newline at end of file diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -14,6 +14,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/FPEnv.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" @@ -419,6 +420,49 @@ I->deleteValue(); } +TEST(InstructionTest, ConstrainedTrans) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), + { Type::getFloatTy(Context), Type::getInt32Ty(Context) }, false); + auto *F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); + auto *BB = BasicBlock::Create(Context, "bb", F); + IRBuilder<> Builder(Context); + Builder.SetInsertPoint(BB); + auto *Arg0 = F->arg_begin(); + + { + auto *I = cast(Builder.CreateFAdd(Arg0, Arg0)); + EXPECT_EQ(Intrinsic::experimental_constrained_fadd, + getConstrainedIntrinsicID(*I)); + } + + { + auto *I = cast( + Builder.CreateFPToSI(Arg0, Type::getInt32Ty(Context))); + EXPECT_EQ(Intrinsic::experimental_constrained_fptosi, + getConstrainedIntrinsicID(*I)); + } + + { + auto *I = cast(Builder.CreateIntrinsic(Intrinsic::ceil, + { Type::getFloatTy(Context) }, { Arg0 })); + EXPECT_EQ(Intrinsic::experimental_constrained_ceil, + getConstrainedIntrinsicID(*I)); + } + + { + auto *Arg1 = F->arg_begin() + 1; + auto *I = cast(Builder.CreateAdd(Arg1, Arg1)); + EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I)); + } + + { + auto *I = cast(Builder.CreateConstrainedFPBinOp( + Intrinsic::experimental_constrained_fadd, Arg0, Arg0)); + EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I)); + } +} TEST(InstructionsTest, isEliminableCastPair) { LLVMContext C;