diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index a74364dffb2e..88630f560386 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -1931,10 +1931,17 @@ public: Value *CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPCast( + Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr, + Name); return CreateCast(Instruction::FPTrunc, V, DestTy, Name); } Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fpext, + V, DestTy, nullptr, Name); return CreateCast(Instruction::FPExt, V, DestTy, Name); } @@ -2046,6 +2053,29 @@ public: return Insert(CastInst::CreateFPCast(V, DestTy), Name); } + CallInst *CreateConstrainedFPCast( + Intrinsic::ID ID, Value *V, Type *DestTy, + Instruction *FMFSource = nullptr, const Twine &Name = "", + MDNode *FPMathTag = nullptr, + Optional Rounding = None, + Optional Except = None) { + Value *RoundingV = getConstrainedFPRounding(Rounding); + Value *ExceptV = getConstrainedFPExcept(Except); + + FastMathFlags UseFMF = FMF; + if (FMFSource) + UseFMF = FMFSource->getFastMathFlags(); + + CallInst *C; + if (ID == Intrinsic::experimental_constrained_fpext) + C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr, + Name); + else + C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV}, + nullptr, Name); + return cast(setFPAttrs(C, FPMathTag, UseFMF)); + } + // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 667b9ef0319a..f73cf140e19f 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -125,10 +125,14 @@ TEST_F(IRBuilderTest, Intrinsics) { TEST_F(IRBuilderTest, ConstrainedFP) { IRBuilder<> Builder(BB); Value *V; + Value *VDouble; CallInst *Call; IntrinsicInst *II; + GlobalVariable *GVDouble = new GlobalVariable(*M, Type::getDoubleTy(Ctx), + true, GlobalValue::ExternalLinkage, nullptr); V = Builder.CreateLoad(GV->getValueType(), GV); + VDouble = Builder.CreateLoad(GVDouble->getValueType(), GVDouble); // See if we get constrained intrinsics instead of non-constrained // instructions. @@ -159,6 +163,16 @@ TEST_F(IRBuilderTest, ConstrainedFP) { II = cast(V); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem); + V = Builder.CreateFPTrunc(VDouble, Type::getFloatTy(Ctx)); + ASSERT_TRUE(isa(V)); + II = cast(V); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fptrunc); + + VDouble = Builder.CreateFPExt(V, Type::getDoubleTy(Ctx)); + ASSERT_TRUE(isa(VDouble)); + II = cast(VDouble); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fpext); + // Verify the codepaths for setting and overriding the default metadata. V = Builder.CreateFAdd(V, V); ASSERT_TRUE(isa(V));