[llvm] [FPEnv][IRBuilder] Set strictfp mode automatically when possible. (PR #98677)

Kevin P. Neal via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 11:28:12 PDT 2024


https://github.com/kpneal created https://github.com/llvm/llvm-project/pull/98677

The IRBuilder has a strictfp mode that replaces FP instructions with the matching constrained intrinsic, and it adds the strictfp attribute to all function calls. Check the function definition to see if the strictfp attribute is present and, if it is, enable the strictfp mode in the constructor.

Not all cases can be handled since some IRBuilder constructors don't provide a way to get the Function*, and additionally operations with a BasicBlock that doesn't belong to a Function are allowed by LLVM.

>From 9cbb67df36c6c887c4ee1621e15bf1f4da5e4b8b Mon Sep 17 00:00:00 2001
From: "Kevin P. Neal" <kevin.neal at sas.com>
Date: Fri, 12 Jul 2024 14:11:43 -0400
Subject: [PATCH] [FPEnv][IRBuilder] Set strictfp mode automatically when
 possible.

The IRBuilder has a strictfp mode that replaces FP instructions with
the matching constrained intrinsic, and it adds the strictfp attribute
to all function calls. Check the function definition to see if the
strictfp attribute is present and, if it is, enable the strictfp mode
in the constructor.

Not all cases can be handled since some IRBuilder constructors don't
provide a way to get the Function*, and additionally operations with
a BasicBlock that doesn't belong to a Function are allowed by LLVM.
---
 llvm/include/llvm/IR/IRBuilder.h    | 20 +++++++++++++++
 llvm/unittests/IR/IRBuilderTest.cpp | 40 +++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 31a1fef321995..7f2a853b06567 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2691,6 +2691,10 @@ class IRBuilder : public IRBuilderBase {
                       FPMathTag, OpBundles),
         Folder(Folder) {
     SetInsertPoint(TheBB);
+    Function *F = TheBB->getParent();
+    if (F && F->hasFnAttribute(Attribute::StrictFP)) {
+      setIsFPConstrained(true);
+    }
   }
 
   explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
@@ -2698,6 +2702,10 @@ class IRBuilder : public IRBuilderBase {
       : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
                       FPMathTag, OpBundles) {
     SetInsertPoint(TheBB);
+    Function *F = TheBB->getParent();
+    if (F && F->hasFnAttribute(Attribute::StrictFP)) {
+      setIsFPConstrained(true);
+    }
   }
 
   explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
@@ -2705,6 +2713,10 @@ class IRBuilder : public IRBuilderBase {
       : IRBuilderBase(IP->getContext(), this->Folder, this->Inserter, FPMathTag,
                       OpBundles) {
     SetInsertPoint(IP);
+    Function *F = IP->getParent()->getParent();
+    if (F && F->hasFnAttribute(Attribute::StrictFP)) {
+      setIsFPConstrained(true);
+    }
   }
 
   IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, FolderTy Folder,
@@ -2714,6 +2726,10 @@ class IRBuilder : public IRBuilderBase {
                       FPMathTag, OpBundles),
         Folder(Folder) {
     SetInsertPoint(TheBB, IP);
+    Function *F = TheBB->getParent();
+    if (F && F->hasFnAttribute(Attribute::StrictFP)) {
+      setIsFPConstrained(true);
+    }
   }
 
   IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
@@ -2722,6 +2738,10 @@ class IRBuilder : public IRBuilderBase {
       : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
                       FPMathTag, OpBundles) {
     SetInsertPoint(TheBB, IP);
+    Function *F = TheBB->getParent();
+    if (F && F->hasFnAttribute(Attribute::StrictFP)) {
+      setIsFPConstrained(true);
+    }
   }
 
   /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index ff96df8581200..215390334b0be 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -448,6 +448,46 @@ TEST_F(IRBuilderTest, ConstrainedFPFunctionCall) {
   EXPECT_FALSE(verifyModule(*M));
 }
 
+TEST_F(IRBuilderTest, DetectDefaultStrictFP) {
+  // Create an empty constrained FP function.
+  FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
+                                        /*isVarArg=*/false);
+  Function *FStrict = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
+  FStrict->addFnAttr(Attribute::StrictFP);
+  BasicBlock *BBStrict = BasicBlock::Create(Ctx, "", FStrict);
+
+  struct TestInserter : public IRBuilderDefaultInserter {
+    TestInserter() = default;
+  };
+  InstSimplifyFolder Folder(M->getDataLayout());
+
+  IRBuilder Builder1(BBStrict, Folder);
+
+  // A simple check is sufficient since we already check that StrictFP
+  // mode works correctly in previous tests above.
+  EXPECT_TRUE(Builder1.getIsFPConstrained());
+
+  MDBuilder MDB(M->getContext());
+  MDNode *FPMath = MDB.createFPMath(0.01f);
+
+  IRBuilder Builder2(BBStrict, FPMath);
+  EXPECT_TRUE(Builder2.getIsFPConstrained());
+
+  Value *V = Builder2.CreateLoad(GV->getValueType(), GV);
+  V = Builder2.CreateFAdd(V, V);
+  ASSERT_TRUE(isa<IntrinsicInst>(V));
+  auto *II = cast<IntrinsicInst>(V);
+
+  IRBuilder Builder3(II, FPMath);
+  EXPECT_TRUE(Builder3.getIsFPConstrained());
+
+  IRBuilder Builder4(BBStrict, BBStrict->back().getIterator(), Folder);
+  EXPECT_TRUE(Builder4.getIsFPConstrained());
+
+  IRBuilder Builder5(BBStrict, BBStrict->back().getIterator(), FPMath);
+  EXPECT_TRUE(Builder5.getIsFPConstrained());
+}
+
 TEST_F(IRBuilderTest, Lifetime) {
   IRBuilder<> Builder(BB);
   AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty());



More information about the llvm-commits mailing list