Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -970,6 +970,30 @@ return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; } + Value *getConstrainedRounding(MDNode *RoundingMD) { + MDString *Rounding = nullptr; + + if (RoundingMD) + Rounding = cast(RoundingMD->getOperand(0)); + + if (!Rounding) + Rounding = MDString::get(Context, "round.dynamic"); + + return MetadataAsValue::get(Context, Rounding); + } + + Value *getConstrainedExcept(MDNode *ExceptMD) { + MDString *Except = nullptr; + + if (ExceptMD) + Except = cast(ExceptMD->getOperand(0)); + + if (!Except) + Except = MDString::get(Context, "fpexcept.strict"); + + return MetadataAsValue::get(Context, Except); + } + public: Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { @@ -1187,6 +1211,19 @@ return Insert(I, Name); } + CallInst *CreateConstrainedFAdd(Value *L, Value *R, const Twine &Name = "", + MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) { + + Value *Rounding = getConstrainedRounding(RoundingMD); + Value *Except = getConstrainedExcept(ExceptMD); + + Value *F = Intrinsic::getDeclaration( + BB->getModule(), Intrinsic::experimental_constrained_fadd, + {L->getType()}); + + return CreateCall(F, { L, R, Rounding, Except }, Name); + } + Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; @@ -1204,6 +1241,19 @@ return Insert(I, Name); } + CallInst *CreateConstrainedFSub(Value *L, Value *R, const Twine &Name = "", + MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) { + + Value *Rounding = getConstrainedRounding(RoundingMD); + Value *Except = getConstrainedExcept(ExceptMD); + + Value *F = Intrinsic::getDeclaration( + BB->getModule(), Intrinsic::experimental_constrained_fsub, + {L->getType()}); + + return CreateCall(F, { L, R, Rounding, Except }); + } + Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; @@ -1221,6 +1271,19 @@ return Insert(I, Name); } + CallInst *CreateConstrainedFMul(Value *L, Value *R, const Twine &Name = "", + MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) { + + Value *Rounding = getConstrainedRounding(RoundingMD); + Value *Except = getConstrainedExcept(ExceptMD); + + Value *F = Intrinsic::getDeclaration( + BB->getModule(), Intrinsic::experimental_constrained_fmul, + {L->getType()}); + + return CreateCall(F, { L, R, Rounding, Except }); + } + Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; @@ -1238,6 +1301,19 @@ return Insert(I, Name); } + CallInst *CreateConstrainedFDiv(Value *L, Value *R, const Twine &Name = "", + MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) { + + Value *Rounding = getConstrainedRounding(RoundingMD); + Value *Except = getConstrainedExcept(ExceptMD); + + Value *F = Intrinsic::getDeclaration( + BB->getModule(), Intrinsic::experimental_constrained_fdiv, + {L->getType()}); + + return CreateCall(F, { L, R, Rounding, Except }); + } + Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; @@ -1255,6 +1331,19 @@ return Insert(I, Name); } + CallInst *CreateConstrainedFRem(Value *L, Value *R, const Twine &Name = "", + MDNode *RoundingMD = nullptr, MDNode *ExceptMD = nullptr) { + + Value *Rounding = getConstrainedRounding(RoundingMD); + Value *Except = getConstrainedExcept(ExceptMD); + + Value *F = Intrinsic::getDeclaration( + BB->getModule(), Intrinsic::experimental_constrained_frem, + {L->getType()}); + + return CreateCall(F, { L, R, Rounding, Except }); + } + Value *CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { Index: unittests/IR/IRBuilderTest.cpp =================================================================== --- unittests/IR/IRBuilderTest.cpp +++ unittests/IR/IRBuilderTest.cpp @@ -121,6 +121,26 @@ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma); EXPECT_TRUE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); + + Call = Builder.CreateConstrainedFAdd(V, V); + II = cast(Call); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fadd); + + Call = Builder.CreateConstrainedFSub(V, V); + II = cast(Call); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fsub); + + Call = Builder.CreateConstrainedFMul(V, V); + II = cast(Call); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fmul); + + Call = Builder.CreateConstrainedFDiv(V, V); + II = cast(Call); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fdiv); + + Call = Builder.CreateConstrainedFRem(V, V); + II = cast(Call); + EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem); } TEST_F(IRBuilderTest, Lifetime) {