Skip to content

Commit d5c9530

Browse files
authored
[C API] Add getters and setters for fast-math flags on relevant instructions (#75123)
These flags are usable on floating point arithmetic, as well as call, select, and phi instructions whose resulting type is floating point, or a vector of, or an array of, a valid type. Whether or not the flags are valid for a given instruction can be checked with the new LLVMCanValueUseFastMathFlags function. These are exposed using a new LLVMFastMathFlags type, which is an alias for unsigned. An anonymous enum defines the bit values for it. Tests are added in echo.ll for select/phil/call, and the floating point types in the new float_ops.ll bindings test. Select and the floating point arithmetic instructions were not implemented in llvm-c-test/echo.cpp, so they were added as well.
1 parent ed210f9 commit d5c9530

File tree

6 files changed

+350
-0
lines changed

6 files changed

+350
-0
lines changed

llvm/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ Changes to the C API
226226
* ``LLVMGetOperandBundleArgAtIndex``
227227
* ``LLVMGetOperandBundleTag``
228228

229+
* Added ``LLVMGetFastMathFlags`` and ``LLVMSetFastMathFlags`` for getting/setting
230+
the fast-math flags of an instruction, as well as ``LLVMCanValueUseFastMathFlags``
231+
for checking if an instruction can use such flags
232+
229233
Changes to the CodeGen infrastructure
230234
-------------------------------------
231235

llvm/include/llvm-c/Core.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,29 @@ typedef enum {
483483

484484
typedef unsigned LLVMAttributeIndex;
485485

486+
enum {
487+
LLVMFastMathAllowReassoc = (1 << 0),
488+
LLVMFastMathNoNaNs = (1 << 1),
489+
LLVMFastMathNoInfs = (1 << 2),
490+
LLVMFastMathNoSignedZeros = (1 << 3),
491+
LLVMFastMathAllowReciprocal = (1 << 4),
492+
LLVMFastMathAllowContract = (1 << 5),
493+
LLVMFastMathApproxFunc = (1 << 6),
494+
LLVMFastMathNone = 0,
495+
LLVMFastMathAll = LLVMFastMathAllowReassoc | LLVMFastMathNoNaNs |
496+
LLVMFastMathNoInfs | LLVMFastMathNoSignedZeros |
497+
LLVMFastMathAllowReciprocal | LLVMFastMathAllowContract |
498+
LLVMFastMathApproxFunc,
499+
};
500+
501+
/**
502+
* Flags to indicate what fast-math-style optimizations are allowed
503+
* on operations.
504+
*
505+
* See https://llvm.org/docs/LangRef.html#fast-math-flags
506+
*/
507+
typedef unsigned LLVMFastMathFlags;
508+
486509
/**
487510
* @}
488511
*/
@@ -4075,6 +4098,33 @@ LLVMBool LLVMGetNNeg(LLVMValueRef NonNegInst);
40754098
*/
40764099
void LLVMSetNNeg(LLVMValueRef NonNegInst, LLVMBool IsNonNeg);
40774100

4101+
/**
4102+
* Get the flags for which fast-math-style optimizations are allowed for this
4103+
* value.
4104+
*
4105+
* Only valid on floating point instructions.
4106+
* @see LLVMCanValueUseFastMathFlags
4107+
*/
4108+
LLVMFastMathFlags LLVMGetFastMathFlags(LLVMValueRef FPMathInst);
4109+
4110+
/**
4111+
* Sets the flags for which fast-math-style optimizations are allowed for this
4112+
* value.
4113+
*
4114+
* Only valid on floating point instructions.
4115+
* @see LLVMCanValueUseFastMathFlags
4116+
*/
4117+
void LLVMSetFastMathFlags(LLVMValueRef FPMathInst, LLVMFastMathFlags FMF);
4118+
4119+
/**
4120+
* Check if a given value can potentially have fast math flags.
4121+
*
4122+
* Will return true for floating point arithmetic instructions, and for select,
4123+
* phi, and call instructions whose type is a floating point type, or a vector
4124+
* or array thereof. See https://llvm.org/docs/LangRef.html#fast-math-flags
4125+
*/
4126+
LLVMBool LLVMCanValueUseFastMathFlags(LLVMValueRef Inst);
4127+
40784128
/**
40794129
* Gets whether the instruction has the disjoint flag set.
40804130
* Only valid for or instructions.

llvm/lib/IR/Core.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3319,6 +3319,39 @@ void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value) {
33193319

33203320
/*--.. Arithmetic ..........................................................--*/
33213321

3322+
static FastMathFlags mapFromLLVMFastMathFlags(LLVMFastMathFlags FMF) {
3323+
FastMathFlags NewFMF;
3324+
NewFMF.setAllowReassoc((FMF & LLVMFastMathAllowReassoc) != 0);
3325+
NewFMF.setNoNaNs((FMF & LLVMFastMathNoNaNs) != 0);
3326+
NewFMF.setNoInfs((FMF & LLVMFastMathNoInfs) != 0);
3327+
NewFMF.setNoSignedZeros((FMF & LLVMFastMathNoSignedZeros) != 0);
3328+
NewFMF.setAllowReciprocal((FMF & LLVMFastMathAllowReciprocal) != 0);
3329+
NewFMF.setAllowContract((FMF & LLVMFastMathAllowContract) != 0);
3330+
NewFMF.setApproxFunc((FMF & LLVMFastMathApproxFunc) != 0);
3331+
3332+
return NewFMF;
3333+
}
3334+
3335+
static LLVMFastMathFlags mapToLLVMFastMathFlags(FastMathFlags FMF) {
3336+
LLVMFastMathFlags NewFMF = LLVMFastMathNone;
3337+
if (FMF.allowReassoc())
3338+
NewFMF |= LLVMFastMathAllowReassoc;
3339+
if (FMF.noNaNs())
3340+
NewFMF |= LLVMFastMathNoNaNs;
3341+
if (FMF.noInfs())
3342+
NewFMF |= LLVMFastMathNoInfs;
3343+
if (FMF.noSignedZeros())
3344+
NewFMF |= LLVMFastMathNoSignedZeros;
3345+
if (FMF.allowReciprocal())
3346+
NewFMF |= LLVMFastMathAllowReciprocal;
3347+
if (FMF.allowContract())
3348+
NewFMF |= LLVMFastMathAllowContract;
3349+
if (FMF.approxFunc())
3350+
NewFMF |= LLVMFastMathApproxFunc;
3351+
3352+
return NewFMF;
3353+
}
3354+
33223355
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
33233356
const char *Name) {
33243357
return wrap(unwrap(B)->CreateAdd(unwrap(LHS), unwrap(RHS), Name));
@@ -3518,6 +3551,22 @@ void LLVMSetNNeg(LLVMValueRef NonNegInst, LLVMBool IsNonNeg) {
35183551
cast<Instruction>(P)->setNonNeg(IsNonNeg);
35193552
}
35203553

3554+
LLVMFastMathFlags LLVMGetFastMathFlags(LLVMValueRef FPMathInst) {
3555+
Value *P = unwrap<Value>(FPMathInst);
3556+
FastMathFlags FMF = cast<Instruction>(P)->getFastMathFlags();
3557+
return mapToLLVMFastMathFlags(FMF);
3558+
}
3559+
3560+
void LLVMSetFastMathFlags(LLVMValueRef FPMathInst, LLVMFastMathFlags FMF) {
3561+
Value *P = unwrap<Value>(FPMathInst);
3562+
cast<Instruction>(P)->setFastMathFlags(mapFromLLVMFastMathFlags(FMF));
3563+
}
3564+
3565+
LLVMBool LLVMCanValueUseFastMathFlags(LLVMValueRef V) {
3566+
Value *Val = unwrap<Value>(V);
3567+
return isa<FPMathOperator>(Val);
3568+
}
3569+
35213570
LLVMBool LLVMGetIsDisjoint(LLVMValueRef Inst) {
35223571
Value *P = unwrap<Value>(Inst);
35233572
return cast<PossiblyDisjointInst>(P)->isDisjoint();

llvm/test/Bindings/llvm-c/echo.ll

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,41 @@ entry:
299299
ret void
300300
}
301301

302+
define void @test_fast_math_flags(i1 %c, float %a, float %b) {
303+
entry:
304+
%select.f.1 = select i1 %c, float %a, float %b
305+
%select.f.2 = select nsz i1 %c, float %a, float %b
306+
%select.f.3 = select fast i1 %c, float %a, float %b
307+
%select.f.4 = select nnan arcp afn i1 %c, float %a, float %b
308+
309+
br i1 %c, label %choose_a, label %choose_b
310+
311+
choose_a:
312+
br label %final
313+
314+
choose_b:
315+
br label %final
316+
317+
final:
318+
%phi.f.1 = phi float [ %a, %choose_a ], [ %b, %choose_b ]
319+
%phi.f.2 = phi nsz float [ %a, %choose_a ], [ %b, %choose_b ]
320+
%phi.f.3 = phi fast float [ %a, %choose_a ], [ %b, %choose_b ]
321+
%phi.f.4 = phi nnan arcp afn float [ %a, %choose_a ], [ %b, %choose_b ]
322+
ret void
323+
}
324+
325+
define float @test_fast_math_flags_call_inner(float %a) {
326+
ret float %a
327+
}
328+
329+
define void @test_fast_math_flags_call_outer(float %a) {
330+
%a.1 = call float @test_fast_math_flags_call_inner(float %a)
331+
%a.2 = call nsz float @test_fast_math_flags_call_inner(float %a)
332+
%a.3 = call fast float @test_fast_math_flags_call_inner(float %a)
333+
%a.4 = call nnan arcp afn float @test_fast_math_flags_call_inner(float %a)
334+
ret void
335+
}
336+
302337
!llvm.dbg.cu = !{!0, !2}
303338
!llvm.module.flags = !{!3}
304339

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
; RUN: llvm-as < %s | llvm-dis > %t.orig
2+
; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
3+
; RUN: diff -w %t.orig %t.echo
4+
;
5+
source_filename = "/test/Bindings/float_ops.ll"
6+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
7+
8+
9+
define float @float_ops_f32(float %a, float %b) {
10+
%1 = fneg float %a
11+
12+
%2 = fadd float %a, %b
13+
%3 = fsub float %a, %b
14+
%4 = fmul float %a, %b
15+
%5 = fdiv float %a, %b
16+
%6 = frem float %a, %b
17+
18+
ret float %1
19+
}
20+
21+
define double @float_ops_f64(double %a, double %b) {
22+
%1 = fneg double %a
23+
24+
%2 = fadd double %a, %b
25+
%3 = fsub double %a, %b
26+
%4 = fmul double %a, %b
27+
%5 = fdiv double %a, %b
28+
%6 = frem double %a, %b
29+
30+
ret double %1
31+
}
32+
33+
define void @float_cmp_f32(float %a, float %b) {
34+
%1 = fcmp oeq float %a, %b
35+
%2 = fcmp ogt float %a, %b
36+
%3 = fcmp olt float %a, %b
37+
%4 = fcmp ole float %a, %b
38+
%5 = fcmp one float %a, %b
39+
40+
%6 = fcmp ueq float %a, %b
41+
%7 = fcmp ugt float %a, %b
42+
%8 = fcmp ult float %a, %b
43+
%9 = fcmp ule float %a, %b
44+
%10 = fcmp une float %a, %b
45+
46+
%11 = fcmp ord float %a, %b
47+
%12 = fcmp false float %a, %b
48+
%13 = fcmp true float %a, %b
49+
50+
ret void
51+
}
52+
53+
define void @float_cmp_f64(double %a, double %b) {
54+
%1 = fcmp oeq double %a, %b
55+
%2 = fcmp ogt double %a, %b
56+
%3 = fcmp olt double %a, %b
57+
%4 = fcmp ole double %a, %b
58+
%5 = fcmp one double %a, %b
59+
60+
%6 = fcmp ueq double %a, %b
61+
%7 = fcmp ugt double %a, %b
62+
%8 = fcmp ult double %a, %b
63+
%9 = fcmp ule double %a, %b
64+
%10 = fcmp une double %a, %b
65+
66+
%11 = fcmp ord double %a, %b
67+
%12 = fcmp false double %a, %b
68+
%13 = fcmp true double %a, %b
69+
70+
ret void
71+
}
72+
73+
define void @float_cmp_fast_f32(float %a, float %b) {
74+
%1 = fcmp fast oeq float %a, %b
75+
%2 = fcmp nsz ogt float %a, %b
76+
%3 = fcmp nsz nnan olt float %a, %b
77+
%4 = fcmp contract ole float %a, %b
78+
%5 = fcmp nnan one float %a, %b
79+
80+
%6 = fcmp nnan ninf nsz ueq float %a, %b
81+
%7 = fcmp arcp ugt float %a, %b
82+
%8 = fcmp fast ult float %a, %b
83+
%9 = fcmp fast ule float %a, %b
84+
%10 = fcmp fast une float %a, %b
85+
86+
%11 = fcmp fast ord float %a, %b
87+
%12 = fcmp nnan ninf false float %a, %b
88+
%13 = fcmp nnan ninf true float %a, %b
89+
90+
ret void
91+
}
92+
93+
define void @float_cmp_fast_f64(double %a, double %b) {
94+
%1 = fcmp fast oeq double %a, %b
95+
%2 = fcmp nsz ogt double %a, %b
96+
%3 = fcmp nsz nnan olt double %a, %b
97+
%4 = fcmp contract ole double %a, %b
98+
%5 = fcmp nnan one double %a, %b
99+
100+
%6 = fcmp nnan ninf nsz ueq double %a, %b
101+
%7 = fcmp arcp ugt double %a, %b
102+
%8 = fcmp fast ult double %a, %b
103+
%9 = fcmp fast ule double %a, %b
104+
%10 = fcmp fast une double %a, %b
105+
106+
%11 = fcmp fast ord double %a, %b
107+
%12 = fcmp nnan ninf false double %a, %b
108+
%13 = fcmp nnan ninf true double %a, %b
109+
110+
ret void
111+
}
112+
113+
define float @float_ops_fast_f32(float %a, float %b) {
114+
%1 = fneg nnan float %a
115+
116+
%2 = fadd ninf float %a, %b
117+
%3 = fsub nsz float %a, %b
118+
%4 = fmul arcp float %a, %b
119+
%5 = fdiv contract float %a, %b
120+
%6 = frem afn float %a, %b
121+
122+
%7 = fadd reassoc float %a, %b
123+
%8 = fadd reassoc float %7, %b
124+
125+
%9 = fadd fast float %a, %b
126+
%10 = fadd nnan nsz float %a, %b
127+
%11 = frem nnan nsz float %a, %b
128+
%12 = fdiv nnan nsz arcp float %a, %b
129+
%13 = fmul nnan nsz ninf contract float %a, %b
130+
%14 = fmul nnan nsz ninf arcp contract afn reassoc float %a, %b
131+
132+
ret float %1
133+
}
134+
135+
define double @float_ops_fast_f64(double %a, double %b) {
136+
%1 = fneg nnan double %a
137+
138+
%2 = fadd ninf double %a, %b
139+
%3 = fsub nsz double %a, %b
140+
%4 = fmul arcp double %a, %b
141+
%5 = fdiv contract double %a, %b
142+
%6 = frem afn double %a, %b
143+
144+
%7 = fadd reassoc double %a, %b
145+
%8 = fadd reassoc double %7, %b
146+
147+
%9 = fadd fast double %a, %b
148+
%10 = fadd nnan nsz double %a, %b
149+
%11 = frem nnan nsz double %a, %b
150+
%12 = fdiv nnan nsz arcp double %a, %b
151+
%13 = fmul nnan nsz ninf contract double %a, %b
152+
%14 = fmul nnan nsz ninf arcp contract afn reassoc double %a, %b
153+
154+
ret double %1
155+
}
156+

0 commit comments

Comments
 (0)