summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/LangRef.rst7
-rw-r--r--llvm/include/llvm/Bitcode/LLVMBitCodes.h3
-rw-r--r--llvm/include/llvm/IR/IRBuilder.h19
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp34
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp15
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp8
-rw-r--r--llvm/test/Bitcode/compatibility.ll22
-rw-r--r--llvm/test/Transforms/InstCombine/fast-math.ll34
-rw-r--r--llvm/test/Transforms/InstCombine/inline-intrinsic-assert.ll2
-rw-r--r--llvm/test/Transforms/InstCombine/log-pow.ll2
-rw-r--r--llvm/test/Transforms/InstCombine/no_cgscc_assert.ll2
-rw-r--r--llvm/test/Transforms/InstCombine/pow-exp.ll2
-rw-r--r--llvm/test/Transforms/InstCombine/pow-exp2.ll2
-rw-r--r--llvm/unittests/IR/IRBuilderTest.cpp22
14 files changed, 129 insertions, 45 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index a0c23f9a213..79856a304c1 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8314,7 +8314,7 @@ Syntax:
::
- <result> = [tail | musttail | notail ] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
+ <result> = [tail | musttail | notail ] call [fast-math flags] [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
[ operand bundles ]
Overview:
@@ -8371,6 +8371,11 @@ This instruction requires several arguments:
``tail`` or ``musttail`` markers to the call. It is used to prevent tail
call optimization from being performed on the call.
+#. The optional ``fast-math flags`` marker indicates that the call has one or more
+ :ref:`fast-math flags <fastmath>`, which are optimization hints to enable
+ otherwise unsafe floating-point optimizations. Fast-math flags are only valid
+ for calls that return a floating-point scalar or vector type.
+
#. The optional "cconv" marker indicates which :ref:`calling
convention <callingconv>` the call should use. If none is
specified, the call defaults to using C calling conventions. The
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index b967f58d847..6780c8e6a97 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -348,7 +348,8 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
CALL_CCONV = 1,
CALL_MUSTTAIL = 14,
CALL_EXPLICIT_TYPE = 15,
- CALL_NOTAIL = 16
+ CALL_NOTAIL = 16,
+ CALL_FMF = 17 // Call has optional fast-math-flags.
};
// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 1fa88013ef2..7fe04f2a091 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1532,19 +1532,26 @@ public:
const Twine &Name = "") {
return Insert(CallInst::Create(Callee, Args, OpBundles), Name);
}
+
CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
- const Twine &Name) {
- return Insert(CallInst::Create(Callee, Args), Name);
+ const Twine &Name, MDNode *FPMathTag = nullptr) {
+ PointerType *PTy = cast<PointerType>(Callee->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ return CreateCall(FTy, Callee, Args, Name, FPMathTag);
}
CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee,
- ArrayRef<Value *> Args, const Twine &Name = "") {
- return Insert(CallInst::Create(FTy, Callee, Args), Name);
+ ArrayRef<Value *> Args, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ CallInst *CI = CallInst::Create(FTy, Callee, Args);
+ if (isa<FPMathOperator>(CI))
+ CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF));
+ return Insert(CI, Name);
}
CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args,
- const Twine &Name = "") {
- return CreateCall(Callee->getFunctionType(), Callee, Args, Name);
+ const Twine &Name = "", MDNode *FPMathTag = nullptr) {
+ return CreateCall(Callee->getFunctionType(), Callee, Args, Name, FPMathTag);
}
Value *CreateSelect(Value *C, Value *True, Value *False,
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 3d43f81f49a..0b2880949f6 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5603,14 +5603,14 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) {
}
/// ParseCall
-/// ::= 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
-/// ::= 'tail' 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
-/// ::= 'musttail' 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
-/// ::= 'notail' 'call' OptionalCallingConv OptionalAttrs Type Value
-/// ParameterList OptionalAttrs
+/// ::= 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'tail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'musttail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
+/// ::= 'notail' 'call' OptionalFastMathFlags OptionalCallingConv
+/// OptionalAttrs Type Value ParameterList OptionalAttrs
bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
CallInst::TailCallKind TCK) {
AttrBuilder RetAttrs, FnAttrs;
@@ -5624,10 +5624,14 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
SmallVector<OperandBundleDef, 2> BundleList;
LocTy CallLoc = Lex.getLoc();
- if ((TCK != CallInst::TCK_None &&
- ParseToken(lltok::kw_call,
- "expected 'tail call', 'musttail call', or 'notail call'")) ||
- ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) ||
+ if (TCK != CallInst::TCK_None &&
+ ParseToken(lltok::kw_call,
+ "expected 'tail call', 'musttail call', or 'notail call'"))
+ return true;
+
+ FastMathFlags FMF = EatFastMathFlagsIfPresent();
+
+ if (ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
ParseValID(CalleeID) ||
ParseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail,
@@ -5636,6 +5640,10 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
ParseOptionalOperandBundles(BundleList, PFS))
return true;
+ if (FMF.any() && !RetType->isFPOrFPVectorTy())
+ return Error(CallLoc, "fast-math-flags specified for call without "
+ "floating-point scalar or vector return type");
+
// If RetType is a non-function pointer type, then this is the short syntax
// for the call, which means that RetType is just the return type. Infer the
// rest of the function argument types from the arguments that are present.
@@ -5708,6 +5716,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
CallInst *CI = CallInst::Create(Ty, Callee, Args, BundleList);
CI->setTailCallKind(TCK);
CI->setCallingConv(CC);
+ if (FMF.any())
+ CI->setFastMathFlags(FMF);
CI->setAttributes(PAL);
ForwardRefAttrGroups[CI] = FwdRefAttrGrps;
Inst = CI;
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 210ffd8d912..d59f12898e9 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -5006,7 +5006,7 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
break;
}
case bitc::FUNC_CODE_INST_CALL: {
- // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
+ // CALL: [paramattrs, cc, fmf, fnty, fnid, arg0, arg1...]
if (Record.size() < 3)
return error("Invalid record");
@@ -5014,6 +5014,13 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
AttributeSet PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
+ FastMathFlags FMF;
+ if ((CCInfo >> bitc::CALL_FMF) & 1) {
+ FMF = getDecodedFastMathFlags(Record[OpNum++]);
+ if (!FMF.any())
+ return error("Fast math flags indicator set for call with no FMF");
+ }
+
FunctionType *FTy = nullptr;
if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 &&
!(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
@@ -5075,6 +5082,12 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
+ if (FMF.any()) {
+ if (!isa<FPMathOperator>(I))
+ return error("Fast-math-flags specified for call without "
+ "floating-point scalar or vector return type");
+ I->setFastMathFlags(FMF);
+ }
break;
}
case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index dd4a16d985f..e34ce5ac430 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2153,11 +2153,17 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Code = bitc::FUNC_CODE_INST_CALL;
Vals.push_back(VE.getAttributeID(CI.getAttributes()));
+
+ unsigned Flags = GetOptimizationFlags(&I);
Vals.push_back(CI.getCallingConv() << bitc::CALL_CCONV |
unsigned(CI.isTailCall()) << bitc::CALL_TAIL |
unsigned(CI.isMustTailCall()) << bitc::CALL_MUSTTAIL |
1 << bitc::CALL_EXPLICIT_TYPE |
- unsigned(CI.isNoTailCall()) << bitc::CALL_NOTAIL);
+ unsigned(CI.isNoTailCall()) << bitc::CALL_NOTAIL |
+ unsigned(Flags != 0) << bitc::CALL_FMF);
+ if (Flags != 0)
+ Vals.push_back(Flags);
+
Vals.push_back(VE.getTypeID(FTy));
PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index de0fc137e53..465facc2a88 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -664,6 +664,28 @@ define void @fastmathflags(float %op1, float %op2) {
ret void
}
+; Check various fast math flags and floating-point types on calls.
+
+declare float @fmf1()
+declare double @fmf2()
+declare <4 x double> @fmf3()
+
+; CHECK-LABEL: fastMathFlagsForCalls(
+define void @fastMathFlagsForCalls(float %f, double %d1, <4 x double> %d2) {
+ %call.fast = call fast float @fmf1()
+ ; CHECK: %call.fast = call fast float @fmf1()
+
+ ; Throw in some other attributes to make sure those stay in the right places.
+
+ %call.nsz.arcp = notail call nsz arcp double @fmf2()
+ ; CHECK: %call.nsz.arcp = notail call nsz arcp double @fmf2()
+
+ %call.nnan.ninf = tail call nnan ninf fastcc <4 x double> @fmf3()
+ ; CHECK: %call.nnan.ninf = tail call nnan ninf fastcc <4 x double> @fmf3()
+
+ ret void
+}
+
;; Type System
%opaquety = type opaque
define void @typesystem() {
diff --git a/llvm/test/Transforms/InstCombine/fast-math.ll b/llvm/test/Transforms/InstCombine/fast-math.ll
index 06852497564..fd563481b3e 100644
--- a/llvm/test/Transforms/InstCombine/fast-math.ll
+++ b/llvm/test/Transforms/InstCombine/fast-math.ll
@@ -570,7 +570,7 @@ define double @sqrt_intrinsic_arg_squared(double %x) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_arg_squared(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
; CHECK-NEXT: ret double %fabs
}
@@ -584,8 +584,8 @@ define double @sqrt_intrinsic_three_args1(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args1(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -597,8 +597,8 @@ define double @sqrt_intrinsic_three_args2(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args2(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -610,8 +610,8 @@ define double @sqrt_intrinsic_three_args3(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args3(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -623,8 +623,8 @@ define double @sqrt_intrinsic_three_args4(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args4(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -636,8 +636,8 @@ define double @sqrt_intrinsic_three_args5(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args5(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -649,8 +649,8 @@ define double @sqrt_intrinsic_three_args6(double %x, double %y) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_intrinsic_three_args6(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y)
; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -675,7 +675,7 @@ define double @sqrt_intrinsic_arg_5th(double %x) #0 {
; CHECK-LABEL: sqrt_intrinsic_arg_5th(
; CHECK-NEXT: %mul = fmul fast double %x, %x
-; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %x)
+; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %x)
; CHECK-NEXT: %1 = fmul fast double %mul, %sqrt1
; CHECK-NEXT: ret double %1
}
@@ -692,7 +692,7 @@ define float @sqrt_call_squared_f32(float %x) #0 {
ret float %sqrt
; CHECK-LABEL: sqrt_call_squared_f32(
-; CHECK-NEXT: %fabs = call float @llvm.fabs.f32(float %x)
+; CHECK-NEXT: %fabs = call fast float @llvm.fabs.f32(float %x)
; CHECK-NEXT: ret float %fabs
}
@@ -702,7 +702,7 @@ define double @sqrt_call_squared_f64(double %x) #0 {
ret double %sqrt
; CHECK-LABEL: sqrt_call_squared_f64(
-; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x)
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x)
; CHECK-NEXT: ret double %fabs
}
@@ -712,7 +712,7 @@ define fp128 @sqrt_call_squared_f128(fp128 %x) #0 {
ret fp128 %sqrt
; CHECK-LABEL: sqrt_call_squared_f128(
-; CHECK-NEXT: %fabs = call fp128 @llvm.fabs.f128(fp128 %x)
+; CHECK-NEXT: %fabs = call fast fp128 @llvm.fabs.f128(fp128 %x)
; CHECK-NEXT: ret fp128 %fabs
}
diff --git a/llvm/test/Transforms/InstCombine/inline-intrinsic-assert.ll b/llvm/test/Transforms/InstCombine/inline-intrinsic-assert.ll
index af34277563e..c6446d43cff 100644
--- a/llvm/test/Transforms/InstCombine/inline-intrinsic-assert.ll
+++ b/llvm/test/Transforms/InstCombine/inline-intrinsic-assert.ll
@@ -9,7 +9,7 @@ define float @foo(float %f1) #0 {
ret float %call
; CHECK-LABEL: @foo(
-; CHECK-NEXT: call float @llvm.fabs.f32
+; CHECK-NEXT: call fast float @llvm.fabs.f32
; CHECK-NEXT: ret float
}
diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index 1acd0354431..c5ca1688d34 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -8,7 +8,7 @@ entry:
}
; CHECK-LABEL: define double @mylog(
-; CHECK: %log = call double @log(double %x) #0
+; CHECK: %log = call fast double @log(double %x) #0
; CHECK: %mul = fmul fast double %log, %y
; CHECK: ret double %mul
; CHECK: }
diff --git a/llvm/test/Transforms/InstCombine/no_cgscc_assert.ll b/llvm/test/Transforms/InstCombine/no_cgscc_assert.ll
index cec5297695b..3df04d2c890 100644
--- a/llvm/test/Transforms/InstCombine/no_cgscc_assert.ll
+++ b/llvm/test/Transforms/InstCombine/no_cgscc_assert.ll
@@ -10,7 +10,7 @@ define float @bar(float %f) #0 {
ret float %call1
; CHECK-LABEL: @bar(
-; CHECK-NEXT: call float @llvm.fabs.f32
+; CHECK-NEXT: call fast float @llvm.fabs.f32
; CHECK-NEXT: ret float
}
diff --git a/llvm/test/Transforms/InstCombine/pow-exp.ll b/llvm/test/Transforms/InstCombine/pow-exp.ll
index 7ac6fe4f8fd..acc512734ec 100644
--- a/llvm/test/Transforms/InstCombine/pow-exp.ll
+++ b/llvm/test/Transforms/InstCombine/pow-exp.ll
@@ -9,7 +9,7 @@ entry:
; CHECK-LABEL: define double @mypow(
; CHECK: %mul = fmul fast double %x, %y
-; CHECK: %exp = call double @exp(double %mul) #0
+; CHECK: %exp = call fast double @exp(double %mul) #0
; CHECK: ret double %exp
; CHECK: }
diff --git a/llvm/test/Transforms/InstCombine/pow-exp2.ll b/llvm/test/Transforms/InstCombine/pow-exp2.ll
index ad7931c07a6..c42cab391e6 100644
--- a/llvm/test/Transforms/InstCombine/pow-exp2.ll
+++ b/llvm/test/Transforms/InstCombine/pow-exp2.ll
@@ -9,7 +9,7 @@ entry:
; CHECK-LABEL: define double @mypow(
; CHECK: %mul = fmul fast double %x, %y
-; CHECK: %exp2 = call double @exp2(double %mul) #0
+; CHECK: %exp2 = call fast double @exp2(double %mul) #0
; CHECK: ret double %exp2
; CHECK: }
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index 0c602ed2b78..e0da018d7bf 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -131,7 +131,7 @@ TEST_F(IRBuilderTest, GetIntTy) {
TEST_F(IRBuilderTest, FastMathFlags) {
IRBuilder<> Builder(BB);
Value *F, *FC;
- Instruction *FDiv, *FAdd, *FCmp;
+ Instruction *FDiv, *FAdd, *FCmp, *FCall;
F = Builder.CreateLoad(GV);
F = Builder.CreateFAdd(F, F);
@@ -207,6 +207,26 @@ TEST_F(IRBuilderTest, FastMathFlags) {
EXPECT_TRUE(FCmp->hasAllowReciprocal());
Builder.clearFastMathFlags();
+
+ // Test a call with FMF.
+ auto CalleeTy = FunctionType::get(Type::getFloatTy(Ctx),
+ /*isVarArg=*/false);
+ auto Callee =
+ Function::Create(CalleeTy, Function::ExternalLinkage, "", M.get());
+
+ FCall = Builder.CreateCall(Callee, None);
+ EXPECT_FALSE(FCall->hasNoNaNs());
+
+ FMF.clear();
+ FMF.setNoNaNs();
+ Builder.SetFastMathFlags(FMF);
+
+ FCall = Builder.CreateCall(Callee, None);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().NoNaNs);
+ EXPECT_TRUE(FCall->hasNoNaNs());
+
+ Builder.clearFastMathFlags();
// To test a copy, make sure that a '0' and a '1' change state.
F = Builder.CreateFDiv(F, F);
OpenPOWER on IntegriCloud