Skip to content

Commit a0065c1

Browse files
committed
[IR] Add fast-math support for fcmp intrinsics
1 parent a611074 commit a0065c1

File tree

7 files changed

+58
-10
lines changed

7 files changed

+58
-10
lines changed

llvm/docs/LangRef.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,9 +4065,11 @@ Fast-Math Flags
40654065
LLVM IR floating-point operations (:ref:`fneg <i_fneg>`, :ref:`fadd <i_fadd>`,
40664066
:ref:`fsub <i_fsub>`, :ref:`fmul <i_fmul>`, :ref:`fdiv <i_fdiv>`,
40674067
:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`, :ref:`fptrunc <i_fptrunc>`,
4068-
:ref:`fpext <i_fpext>`), and :ref:`phi <i_phi>`, :ref:`select <i_select>`, or
4069-
:ref:`call <i_call>` instructions that return floating-point types may use the
4070-
following flags to enable otherwise unsafe floating-point transformations.
4068+
:ref:`fpext <i_fpext>`), and :ref:`phi <i_phi>`, :ref:`select <i_select>`,
4069+
:ref:`call <i_call>` instructions that return floating-point types, or
4070+
:ref:`call <i_call>` instructions that call fcmp related intrinsics
4071+
may use the following flags to enable otherwise unsafe floating-point
4072+
transformations.
40714073

40724074
``fast``
40734075
This flag is a shorthand for specifying all fast-math flags at once, and

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace llvm {
3939
class Value;
4040
class BasicBlock;
4141
class Instruction;
42+
class CallInst;
4243
class Constant;
4344
class GlobalValue;
4445
class Comdat;
@@ -177,6 +178,10 @@ namespace llvm {
177178
// Map of module ID to path.
178179
std::map<unsigned, StringRef> ModuleIdMap;
179180

181+
// FIXME: Only after validateEndOfModule, these intrinsic
182+
// calls are FPMathOperator.
183+
std::map<CallInst *, FastMathFlags> FCmpIntrinsicFMFs;
184+
180185
/// Only the llvm-as tool may set this to false to bypass
181186
/// UpgradeDebuginfo so it can generate broken bitcode.
182187
bool UpgradeDebugInfo;

llvm/include/llvm/IR/Operator.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ class FPMathOperator : public Operator {
346346
isComposedOfHomogeneousFloatingPointTypes(Ty);
347347
}
348348

349+
/// Returns true if the intrinsic is fcmp.
350+
static bool isFCmpIntrinsic(const Instruction &Inst);
351+
349352
static bool classof(const Value *V) {
350353
unsigned Opcode;
351354
if (auto *I = dyn_cast<Instruction>(V))
@@ -372,7 +375,8 @@ class FPMathOperator : public Operator {
372375
case Instruction::PHI:
373376
case Instruction::Select:
374377
case Instruction::Call: {
375-
return isSupportedFloatingPointType(V->getType());
378+
return isSupportedFloatingPointType(V->getType()) ||
379+
isFCmpIntrinsic(*dyn_cast<Instruction>(V));
376380
}
377381
default:
378382
return false;

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
403403
"use of undefined value '@" +
404404
Twine(ForwardRefValIDs.begin()->first) + "'");
405405

406+
for (auto [CI, FMF] : FCmpIntrinsicFMFs)
407+
CI->setFastMathFlags(FMF);
408+
406409
if (AllowIncompleteIR && !ForwardRefMDNodes.empty())
407410
dropUnknownMetadataReferences();
408411

@@ -8446,12 +8449,26 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS,
84468449
CI->setTailCallKind(TCK);
84478450
CI->setCallingConv(CC);
84488451
if (FMF.any()) {
8452+
bool IsFCmpIntrinsic = false;
84498453
if (!isa<FPMathOperator>(CI)) {
8450-
CI->deleteValue();
8451-
return error(CallLoc, "fast-math-flags specified for call without "
8452-
"floating-point scalar or vector return type");
8454+
auto FCmpName = StringRef(CalleeID.StrVal);
8455+
if (FCmpName.starts_with("llvm.") &&
8456+
CalleeID.Kind == ValID::t_GlobalName) {
8457+
unsigned IID = Intrinsic::lookupIntrinsicID(FCmpName);
8458+
IsFCmpIntrinsic = IID == Intrinsic::vp_fcmp ||
8459+
IID == Intrinsic::experimental_constrained_fcmp ||
8460+
IID == Intrinsic::experimental_constrained_fcmps;
8461+
}
8462+
if (!IsFCmpIntrinsic) {
8463+
CI->deleteValue();
8464+
return error(CallLoc, "fast-math-flags specified for call without "
8465+
"floating-point scalar or vector return type "
8466+
"or callee is not fcmp intrinsic");
8467+
}
8468+
FCmpIntrinsicFMFs[CI] = FMF;
84538469
}
8454-
CI->setFastMathFlags(FMF);
8470+
if (!IsFCmpIntrinsic)
8471+
CI->setFastMathFlags(FMF);
84558472
}
84568473

84578474
if (CalleeID.Kind == ValID::t_GlobalName &&

llvm/lib/IR/Operator.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ bool Operator::hasPoisonGeneratingAnnotations() const {
6767
I->hasPoisonGeneratingMetadata());
6868
}
6969

70+
bool FPMathOperator::isFCmpIntrinsic(const Instruction &Inst) {
71+
const auto *I = dyn_cast<CallInst>(&Inst);
72+
if (!I)
73+
return false;
74+
75+
unsigned IID = Intrinsic::not_intrinsic;
76+
if (Function *F = I->getCalledFunction())
77+
IID = F->getIntrinsicID();
78+
79+
return IID == Intrinsic::vp_fcmp ||
80+
IID == Intrinsic::experimental_constrained_fcmp ||
81+
IID == Intrinsic::experimental_constrained_fcmps;
82+
}
83+
7084
Type *GEPOperator::getSourceElementType() const {
7185
if (auto *I = dyn_cast<GetElementPtrInst>(this))
7286
return I->getSourceElementType();

llvm/test/Assembler/fast-math-flags.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ entry:
108108
%h_vec = fptrunc nnan <3 x float> %vec to <3 x half>
109109
; CHECK: %h_scalable = fptrunc nnan <vscale x 3 x float> %scalable to <vscale x 3 x half>
110110
%h_scalable = fptrunc nnan <vscale x 3 x float> %scalable to <vscale x 3 x half>
111+
; CHECK: %i_fcmp_result = call nnan <3 x i1> @llvm.vp.fcmp.v3f32(<3 x float> %vec, <3 x float> %vec, metadata !"oeq", <3 x i1> <i1 false, i1 true, i1 false>, i32 3)
112+
%i_fcmp_result = call nnan <3 x i1> @llvm.vp.fcmp.v3f32(<3 x float> %vec, <3 x float> %vec, metadata !"oeq", <3 x i1> <i1 false, i1 true, i1 false>, i32 3)
111113
; CHECK: ret float %f
112114
ret float %f
113115
}

llvm/test/Bitcode/compatibility.ll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,9 @@ define void @fastMathFlagsForCalls(float %f, double %d1, <4 x double> %d2) {
11571157
%call.nnan.ninf = tail call nnan ninf fastcc <4 x double> @fmf_v4f64()
11581158
; CHECK: %call.nnan.ninf = tail call nnan ninf fastcc <4 x double> @fmf_v4f64()
11591159

1160+
%call.fcmp.intrinsic = call nnan i1 @llvm.experimental.constrained.fcmp.f32(float %f, float %f, metadata !"oeq", metadata !"fpexcept.ignore")
1161+
; CHECK: %call.fcmp.intrinsic = call nnan i1 @llvm.experimental.constrained.fcmp.f32(float %f, float %f, metadata !"oeq", metadata !"fpexcept.ignore")
1162+
11601163
ret void
11611164
}
11621165

@@ -1718,7 +1721,7 @@ exit:
17181721
; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2>
17191722

17201723
call void @f.nobuiltin() builtin
1721-
; CHECK: call void @f.nobuiltin() #55
1724+
; CHECK: call void @f.nobuiltin() #56
17221725

17231726
call fastcc noalias ptr @f.noalias() noinline
17241727
; CHECK: call fastcc noalias ptr @f.noalias() #12
@@ -2288,7 +2291,8 @@ define float @nofpclass_callsites(float %arg, { float } %arg1) {
22882291
; CHECK: attributes #52 = { sanitize_realtime }
22892292
; CHECK: attributes #53 = { sanitize_realtime_blocking }
22902293
; CHECK: attributes #54 = { sanitize_alloc_token }
2291-
; CHECK: attributes #55 = { builtin }
2294+
; CHECK: attributes #55 = { nocallback nofree nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite) }
2295+
; CHECK: attributes #56 = { builtin }
22922296

22932297
;; Metadata
22942298

0 commit comments

Comments
 (0)