From de79836312e02b3b4a6d322ced971afee6d4ba4d Mon Sep 17 00:00:00 2001 From: "Kevin P. Neal" Date: Tue, 22 Oct 2019 13:07:15 -0400 Subject: [PATCH] [FPEnv] Teach the IRBuilder about correct use of the strictfp attribute. The IRBuilder needs to add the strictfp attribute to function definitions and calls when constrained floating point is enabled. Since so far all front ends have had to do is flip the constrained switch, I've made this patch always add the required attributes when said constrained switch is enabled. This continues to keep changes to front ends minimal. Differential Revision: D69312 --- llvm/include/llvm/IR/IRBuilder.h | 22 ++++++++++++++++++++++ llvm/unittests/IR/IRBuilderTest.cpp | 9 +++++++++ 2 files changed, 31 insertions(+) diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index d1ddb75..05f311d 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -255,6 +255,21 @@ public: 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,7 @@ public: CallInst *C = CreateIntrinsic(ID, {L->getType()}, {L, R, RoundingV, ExceptV}, nullptr, Name); + setConstrainedFPCallAttr(C); setFPAttrs(C, FPMathTag, UseFMF); return C; } @@ -2084,6 +2100,8 @@ public: Name); break; } + setConstrainedFPCallAttr(C); + if (isa(C)) setFPAttrs(C, FPMathTag, UseFMF); return C; @@ -2240,6 +2258,8 @@ public: ArrayRef Args = None, const Twine &Name = "", MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles); + if (IsFPConstrained) + setConstrainedFPCallAttr(CI); if (isa(CI)) setFPAttrs(CI, FPMathTag, FMF); return Insert(CI, Name); @@ -2249,6 +2269,8 @@ public: ArrayRef OpBundles, const Twine &Name = "", MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles); + if (IsFPConstrained) + setConstrainedFPCallAttr(CI); if (isa(CI)) setFPAttrs(CI, FPMathTag, FMF); return Insert(CI, Name); diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 3c9dbc7..c74f6301 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -229,6 +229,15 @@ TEST_F(IRBuilderTest, ConstrainedFP) { 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)); -- 2.7.4