[llvm] 57e7cee - [IRBuilder] Add FMFSource overloads for CreateCall (#208171)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 8 18:23:07 PDT 2026
Author: Kito Cheng
Date: 2026-07-09T09:23:03+08:00
New Revision: 57e7ceed3398ed1ddf28afdf78ba81cc2638c665
URL: https://github.com/llvm/llvm-project/commit/57e7ceed3398ed1ddf28afdf78ba81cc2638c665
DIFF: https://github.com/llvm/llvm-project/commit/57e7ceed3398ed1ddf28afdf78ba81cc2638c665.diff
LOG: [IRBuilder] Add FMFSource overloads for CreateCall (#208171)
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
Added:
Modified:
llvm/include/llvm/IR/IRBuilder.h
llvm/lib/CodeGen/ReplaceWithVeclib.cpp
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
llvm/unittests/Analysis/ValueTrackingTest.cpp
llvm/unittests/IR/IRBuilderTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index c935bf16e71b2..f2621bbe298df 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2562,6 +2562,13 @@ class IRBuilderBase {
return Insert(CI, Name);
}
+ CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
+ FMFSource FMFSource, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateCall(FTy, Callee, Args, DefaultOperandBundles, FMFSource, Name,
+ FPMathTag);
+ }
+
CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> OpBundles,
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
@@ -2573,12 +2580,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) {
@@ -2586,6 +2612,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/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
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));
More information about the llvm-commits
mailing list