[llvm] [IRBuilder] Add FMFSource overloads for CreateCall (PR #208171)

Kito Cheng via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 8 02:53:11 PDT 2026


https://github.com/kito-cheng updated https://github.com/llvm/llvm-project/pull/208171

>From d4990685ca5ef62be5f66085a72073889e54f137 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 8 Jul 2026 16:52:19 +0800
Subject: [PATCH 1/3] [IRBuilder] Add FMFSource overloads for CreateCall

CreateCall had no way to set fast-math-flags at creation time, so callers
had to build the call and copy the flags in a second step:

  CallInst *C = B.CreateCall(Fn, Args);
  C->copyFastMathFlags(Src);

Add FMFSource overloads (mirroring CreateIntrinsic) so the flags can be
copied from a source instruction or FastMathFlags in one call:

  CallInst *C = B.CreateCall(Fn, Args, /*FMFSource=*/Src);

The FMFSource parameter has no default, so existing CreateCall callers are
unaffected and overload resolution stays unambiguous.

Assisted-by: Opus 4.8
---
 llvm/include/llvm/IR/IRBuilder.h              | 38 +++++++++++++++++++
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp        |  8 ++--
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp |  6 +--
 llvm/unittests/IR/IRBuilderTest.cpp           | 20 ++++++++++
 4 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 692990f93c6fb..dde7897ca3135 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2551,6 +2551,17 @@ class IRBuilderBase {
     return Insert(CI, Name);
   }
 
+  CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
+                       FMFSource FMFSource, const Twine &Name = "",
+                       MDNode *FPMathTag = nullptr) {
+    CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
+    if (IsFPConstrained)
+      setConstrainedFPCallAttr(CI);
+    if (isa<FPMathOperator>(CI))
+      setFPAttrs(CI, FPMathTag, FMFSource.get(FMF));
+    return Insert(CI, Name);
+  }
+
   CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
                        ArrayRef<OperandBundleDef> OpBundles,
                        const Twine &Name = "", MDNode *FPMathTag = nullptr) {
@@ -2562,12 +2573,31 @@ class IRBuilderBase {
     return Insert(CI, Name);
   }
 
+  CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
+                       ArrayRef<OperandBundleDef> OpBundles,
+                       FMFSource FMFSource, const Twine &Name = "",
+                       MDNode *FPMathTag = nullptr) {
+    CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles);
+    if (IsFPConstrained)
+      setConstrainedFPCallAttr(CI);
+    if (isa<FPMathOperator>(CI))
+      setFPAttrs(CI, FPMathTag, FMFSource.get(FMF));
+    return Insert(CI, Name);
+  }
+
   CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = {},
                        const Twine &Name = "", MDNode *FPMathTag = nullptr) {
     return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
                       FPMathTag);
   }
 
+  CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
+                       FMFSource FMFSource, const Twine &Name = "",
+                       MDNode *FPMathTag = nullptr) {
+    return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args,
+                      FMFSource, Name, FPMathTag);
+  }
+
   CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
                        ArrayRef<OperandBundleDef> OpBundles,
                        const Twine &Name = "", MDNode *FPMathTag = nullptr) {
@@ -2575,6 +2605,14 @@ class IRBuilderBase {
                       OpBundles, Name, FPMathTag);
   }
 
+  CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
+                       ArrayRef<OperandBundleDef> OpBundles,
+                       FMFSource FMFSource, const Twine &Name = "",
+                       MDNode *FPMathTag = nullptr) {
+    return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args,
+                      OpBundles, FMFSource, Name, FPMathTag);
+  }
+
   LLVM_ABI CallInst *CreateConstrainedFPCall(
       Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
       std::optional<RoundingMode> Rounding = std::nullopt,
diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 587bed5f9bc00..600b8d84e3926 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -90,11 +90,11 @@ static void replaceWithTLIFunction(IntrinsicInst *II, VFInfo &Info,
   SmallVector<OperandBundleDef, 1> OpBundles;
   II->getOperandBundlesAsDefs(OpBundles);
 
-  auto *Replacement = IRBuilder.CreateCall(TLIVecFunc, Args, OpBundles);
+  // Preserve fast math flags for FP math (getFastMathFlagsOrNone keeps this
+  // safe for non-FP intrinsics, whose flags are simply empty).
+  auto *Replacement = IRBuilder.CreateCall(
+      TLIVecFunc, Args, OpBundles, /*FMFSource=*/II->getFastMathFlagsOrNone());
   II->replaceAllUsesWith(Replacement);
-  // Preserve fast math flags for FP math.
-  if (isa<FPMathOperator>(Replacement))
-    Replacement->copyFastMathFlags(II);
   Replacement->setCallingConv(TLIVecFunc->getCallingConv());
 }
 
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 8d15cb5217031..b524c9dd83f4e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2999,8 +2999,7 @@ static Value *optimizeSymmetricCall(CallInst *CI, bool IsEven,
   Value *Src = CI->getArgOperand(0);
 
   if (match(Src, m_OneUse(m_FNeg(m_Value(X))))) {
-    auto *Call = B.CreateCall(CI->getCalledFunction(), {X});
-    Call->copyFastMathFlags(CI);
+    auto *Call = B.CreateCall(CI->getCalledFunction(), {X}, /*FMFSource=*/CI);
     auto *CallInst = copyFlags(*CI, Call);
     if (IsEven) {
       // Even function: f(-x) = f(x)
@@ -3013,8 +3012,7 @@ static Value *optimizeSymmetricCall(CallInst *CI, bool IsEven,
   // Even function: f(abs(x)) = f(x), f(copysign(x, y)) = f(x)
   if (IsEven && (match(Src, m_FAbs(m_Value(X))) ||
                  match(Src, m_CopySign(m_Value(X), m_Value())))) {
-    auto *Call = B.CreateCall(CI->getCalledFunction(), {X});
-    Call->copyFastMathFlags(CI);
+    auto *Call = B.CreateCall(CI->getCalledFunction(), {X}, /*FMFSource=*/CI);
     return copyFlags(*CI, Call);
   }
 
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index 813b1d6e07a3a..6befc403c6f30 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -800,6 +800,26 @@ TEST_F(IRBuilderTest, FastMathFlags) {
 
   Builder.clearFastMathFlags();
 
+  // The FMFSource overload copies flags from the source, ignoring the builder's
+  // (here empty) flags.
+  FastMathFlags CallFMF;
+  CallFMF.setAllowContract();
+  FCall = Builder.CreateCall(Callee, {}, /*FMFSource=*/CallFMF);
+  EXPECT_FALSE(Builder.getFastMathFlags().any());
+  EXPECT_FALSE(FCall->hasNoNaNs());
+  EXPECT_TRUE(FCall->hasAllowContract());
+
+  // A source instruction forwards its flags too.
+  Instruction *FCall2 = Builder.CreateCall(V, {}, /*FMFSource=*/FCall);
+  EXPECT_TRUE(FCall2->hasAllowContract());
+
+  // The OpBundles + FMFSource overload behaves the same.
+  Instruction *FCall3 = Builder.CreateCall(
+      Callee, {}, ArrayRef<OperandBundleDef>{}, /*FMFSource=*/CallFMF);
+  EXPECT_TRUE(FCall3->hasAllowContract());
+
+  Builder.clearFastMathFlags();
+
   // To test a copy, make sure that a '0' and a '1' change state.
   F = Builder.CreateFDiv(F, F);
   ASSERT_TRUE(isa<Instruction>(F));

>From 299799deb258e5945f915f118f04780a957f5c81 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 8 Jul 2026 17:22:50 +0800
Subject: [PATCH 2/3] fixup! [IRBuilder] Add FMFSource overloads for CreateCall

---
 llvm/include/llvm/IR/IRBuilder.h | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index dde7897ca3135..0941f6695b308 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2554,12 +2554,8 @@ class IRBuilderBase {
   CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
                        FMFSource FMFSource, const Twine &Name = "",
                        MDNode *FPMathTag = nullptr) {
-    CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
-    if (IsFPConstrained)
-      setConstrainedFPCallAttr(CI);
-    if (isa<FPMathOperator>(CI))
-      setFPAttrs(CI, FPMathTag, FMFSource.get(FMF));
-    return Insert(CI, Name);
+    return CreateCall(FTy, Callee, Args, DefaultOperandBundles, FMFSource, Name,
+                      FPMathTag);
   }
 
   CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,

>From 5e16e24c3b1dbd2bd51b1dbeb34ccb1765462c75 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at sifive.com>
Date: Wed, 8 Jul 2026 17:46:40 +0800
Subject: [PATCH 3/3] fixup! [IRBuilder] Add FMFSource overloads for CreateCall

---
 llvm/unittests/Analysis/ValueTrackingTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index d40022d640290..382cf0f2b57ed 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -2879,7 +2879,7 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownBitsUnknownVScale) {
   IRBuilder<> Builder(Context);
   Function *TheFn = Intrinsic::getOrInsertDeclaration(&M, Intrinsic::vscale,
                                                       {Builder.getInt32Ty()});
-  CallInst *CI = Builder.CreateCall(TheFn, {}, {}, "");
+  CallInst *CI = Builder.CreateCall(TheFn, {});
 
   KnownBits Known = computeKnownBits(CI, M.getDataLayout());
   // There is no parent function so we cannot look up the vscale_range



More information about the llvm-commits mailing list