Skip to content

Commit c979ce7

Browse files
authored
Add IRBuilder::CreateFMA (#131112)
This commit adds a function for creating fma intrinsic calls to the IRBuilder. If the "IsFPConstrained" flag of the builder is set, the function creates a call to "experimental.constrained.fma" instead of "llvm.fma" . To support the creation of the constrained intrinsic, a function "CreateConstrainedFPIntrinsic" is introduced.
1 parent e4a8969 commit c979ce7

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,19 @@ class IRBuilderBase {
10651065
{Src, Exp}, FMFSource, Name);
10661066
}
10671067

1068+
/// Create call to the fma intrinsic.
1069+
Value *CreateFMA(Value *Factor1, Value *Factor2, Value *Summand,
1070+
FMFSource FMFSource = {}, const Twine &Name = "") {
1071+
if (IsFPConstrained) {
1072+
return CreateConstrainedFPIntrinsic(
1073+
Intrinsic::experimental_constrained_fma, {Factor1->getType()},
1074+
{Factor1, Factor2, Summand}, FMFSource, Name);
1075+
}
1076+
1077+
return CreateIntrinsic(Intrinsic::fma, {Factor1->getType()},
1078+
{Factor1, Factor2, Summand}, FMFSource, Name);
1079+
}
1080+
10681081
/// Create a call to the arithmetic_fence intrinsic.
10691082
CallInst *CreateArithmeticFence(Value *Val, Type *DstType,
10701083
const Twine &Name = "") {
@@ -1723,6 +1736,17 @@ class IRBuilderBase {
17231736
return Accum;
17241737
}
17251738

1739+
/// This function is like @ref CreateIntrinsic for constrained fp
1740+
/// intrinsics. It sets the rounding mode and exception behavior of
1741+
/// the created intrinsic call according to \p Rounding and \p
1742+
/// Except and it sets \p FPMathTag as the 'fpmath' metadata, using
1743+
/// defaults if a value equals nullopt/null.
1744+
CallInst *CreateConstrainedFPIntrinsic(
1745+
Intrinsic::ID ID, ArrayRef<Type *> Types, ArrayRef<Value *> Args,
1746+
FMFSource FMFSource, const Twine &Name, MDNode *FPMathTag = nullptr,
1747+
std::optional<RoundingMode> Rounding = std::nullopt,
1748+
std::optional<fp::ExceptionBehavior> Except = std::nullopt);
1749+
17261750
CallInst *CreateConstrainedFPBinOp(
17271751
Intrinsic::ID ID, Value *L, Value *R, FMFSource FMFSource = {},
17281752
const Twine &Name = "", MDNode *FPMathTag = nullptr,

llvm/lib/IR/AutoUpgrade.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,7 +3755,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
37553755
IID = Intrinsic::x86_avx512_vfmadd_f32;
37563756
Rep = Builder.CreateIntrinsic(IID, {}, Ops);
37573757
} else {
3758-
Rep = Builder.CreateIntrinsic(Intrinsic::fma, A->getType(), {A, B, C});
3758+
Rep = Builder.CreateFMA(A, B, C);
37593759
}
37603760

37613761
Value *PassThru = IsMaskZ ? Constant::getNullValue(Rep->getType())
@@ -3808,7 +3808,7 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
38083808

38093809
Rep = Builder.CreateIntrinsic(IID, {}, {A, B, C, CI->getArgOperand(4)});
38103810
} else {
3811-
Rep = Builder.CreateIntrinsic(Intrinsic::fma, A->getType(), {A, B, C});
3811+
Rep = Builder.CreateFMA(A, B, C);
38123812
}
38133813

38143814
Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType())

llvm/lib/IR/IRBuilder.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,26 @@ CallInst *IRBuilderBase::CreateConstrainedFPBinOp(
950950
return C;
951951
}
952952

953+
CallInst *IRBuilderBase::CreateConstrainedFPIntrinsic(
954+
Intrinsic::ID ID, ArrayRef<Type *> Types, ArrayRef<Value *> Args,
955+
FMFSource FMFSource, const Twine &Name, MDNode *FPMathTag,
956+
std::optional<RoundingMode> Rounding,
957+
std::optional<fp::ExceptionBehavior> Except) {
958+
Value *RoundingV = getConstrainedFPRounding(Rounding);
959+
Value *ExceptV = getConstrainedFPExcept(Except);
960+
961+
FastMathFlags UseFMF = FMFSource.get(FMF);
962+
963+
llvm::SmallVector<Value *, 5> ExtArgs(Args);
964+
ExtArgs.push_back(RoundingV);
965+
ExtArgs.push_back(ExceptV);
966+
967+
CallInst *C = CreateIntrinsic(ID, Types, ExtArgs, nullptr, Name);
968+
setConstrainedFPCallAttr(C);
969+
setFPAttrs(C, FPMathTag, UseFMF);
970+
return C;
971+
}
972+
953973
CallInst *IRBuilderBase::CreateConstrainedFPUnroundedBinOp(
954974
Intrinsic::ID ID, Value *L, Value *R, FMFSource FMFSource,
955975
const Twine &Name, MDNode *FPMathTag,

llvm/unittests/IR/IRBuilderTest.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,23 @@ TEST_F(IRBuilderTest, Intrinsics) {
109109
EXPECT_TRUE(II->hasNoInfs());
110110
EXPECT_FALSE(II->hasNoNaNs());
111111

112-
Result = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V});
112+
Result = Builder.CreateFMA(V, V, V);
113113
II = cast<IntrinsicInst>(Result);
114114
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
115115
EXPECT_FALSE(II->hasNoInfs());
116116
EXPECT_FALSE(II->hasNoNaNs());
117117

118-
Result =
119-
Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
118+
Result = Builder.CreateFMA(V, V, V, I);
120119
II = cast<IntrinsicInst>(Result);
121120
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
122121
EXPECT_TRUE(II->hasNoInfs());
123122
EXPECT_FALSE(II->hasNoNaNs());
124123

125-
Result =
126-
Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
124+
Result = Builder.CreateFMA(V, V, V, FastMathFlags::getFast());
127125
II = cast<IntrinsicInst>(Result);
128126
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
129127
EXPECT_TRUE(II->hasNoInfs());
130-
EXPECT_FALSE(II->hasNoNaNs());
128+
EXPECT_TRUE(II->hasNoNaNs());
131129

132130
Result = Builder.CreateUnaryIntrinsic(Intrinsic::roundeven, V);
133131
II = cast<IntrinsicInst>(Result);
@@ -307,6 +305,11 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
307305
II = cast<IntrinsicInst>(V);
308306
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
309307

308+
V = Builder.CreateFMA(V, V, V);
309+
ASSERT_TRUE(isa<IntrinsicInst>(V));
310+
II = cast<IntrinsicInst>(V);
311+
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fma);
312+
310313
VInt = Builder.CreateFPToUI(VDouble, Builder.getInt32Ty());
311314
ASSERT_TRUE(isa<IntrinsicInst>(VInt));
312315
II = cast<IntrinsicInst>(VInt);
@@ -398,6 +401,15 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
398401
EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
399402
EXPECT_EQ(RoundingMode::TowardNegative, CII->getRoundingMode());
400403

404+
// Same as previous test for CreateConstrainedFPIntrinsic
405+
Call = Builder.CreateConstrainedFPIntrinsic(
406+
Intrinsic::experimental_constrained_fadd, {V->getType()}, {V, V}, nullptr,
407+
"", nullptr, RoundingMode::TowardNegative, fp::ebMayTrap);
408+
CII = cast<ConstrainedFPIntrinsic>(Call);
409+
EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
410+
EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
411+
EXPECT_EQ(RoundingMode::TowardNegative, CII->getRoundingMode());
412+
401413
Builder.CreateRetVoid();
402414
EXPECT_FALSE(verifyModule(*M));
403415
}

0 commit comments

Comments
 (0)