diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -255,6 +255,21 @@ return DefaultConstrainedRounding; } + void setConstrainedFPFunctionAttr() { + assert(BB && "Must have a basic block to set any function attributes!"); + + Function *F = BB->getParent(); + if (!F->hasFnAttribute(Attribute::StrictFP)) { + F->addFnAttr(Attribute::StrictFP); + } + } + + void setConstrainedFPCallAttr(CallInst *I) { + if (!I->hasFnAttr(Attribute::StrictFP)) + I->addAttribute(AttributeList::FunctionIndex, Attribute::StrictFP); + setConstrainedFPFunctionAttr(); + } + //===--------------------------------------------------------------------===// // RAII helpers. //===--------------------------------------------------------------------===// @@ -1479,6 +1494,8 @@ CallInst *C = CreateIntrinsic(ID, {L->getType()}, {L, R, RoundingV, ExceptV}, nullptr, Name); + setConstrainedFPCallAttr(C); + return cast(setFPAttrs(C, FPMathTag, UseFMF)); } @@ -2083,6 +2100,8 @@ Name); break; } + setConstrainedFPCallAttr(C); + if (isa(C)) C = cast(setFPAttrs(C, FPMathTag, UseFMF)); return C; @@ -2239,6 +2258,8 @@ ArrayRef Args = None, const Twine &Name = "", MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles); + if (IsFPConstrained) + setConstrainedFPCallAttr(CI); if (isa(CI)) CI = cast(setFPAttrs(CI, FPMathTag, FMF)); return Insert(CI, Name); @@ -2248,6 +2269,8 @@ ArrayRef OpBundles, const Twine &Name = "", MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles); + if (IsFPConstrained) + setConstrainedFPCallAttr(CI); if (isa(CI)) CI = cast(setFPAttrs(CI, FPMathTag, FMF)); return Insert(CI, Name); diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -229,6 +229,15 @@ II = cast(VDouble); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fpext); + // Verify attributes on the call are created automatically. + AttributeSet CallAttrs = II->getAttributes().getFnAttributes(); + EXPECT_EQ(CallAttrs.hasAttribute(Attribute::StrictFP), true); + + // Verify attributes on the containing function are created automatically. + AttributeList Attrs = BB->getParent()->getAttributes(); + AttributeSet FnAttrs = Attrs.getFnAttributes(); + EXPECT_EQ(FnAttrs.hasAttribute(Attribute::StrictFP), true); + // Verify the codepaths for setting and overriding the default metadata. V = Builder.CreateFAdd(V, V); ASSERT_TRUE(isa(V));