Index: llvm/trunk/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/trunk/include/llvm/IR/IRBuilder.h +++ llvm/trunk/include/llvm/IR/IRBuilder.h @@ -1931,10 +1931,17 @@ 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 @@ 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. Index: llvm/trunk/unittests/IR/IRBuilderTest.cpp =================================================================== --- llvm/trunk/unittests/IR/IRBuilderTest.cpp +++ llvm/trunk/unittests/IR/IRBuilderTest.cpp @@ -125,10 +125,14 @@ 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 @@ 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));