Skip to content

Commit e4a0e7e

Browse files
asbGroverkss
authored andcommitted
[LegalizeTypes] Support softening FMINIMUM/FMAXIMUM (llvm#115463)
Without this, you get an error "Do not know how to soften the result of this operator!" when compiling for a soft float target. The libcall names match those defined in glibc <https://www.gnu.org/software/libc/manual/html_node/Misc-FP-Arithmetic.html> and more recently added to LLVM's libc <llvm#86016>.
1 parent e33baa4 commit e4a0e7e

File tree

4 files changed

+204
-0
lines changed

4 files changed

+204
-0
lines changed

llvm/include/llvm/IR/RuntimeLibcalls.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,16 @@ HANDLE_LIBCALL(FMAX_F64, "fmax")
304304
HANDLE_LIBCALL(FMAX_F80, "fmaxl")
305305
HANDLE_LIBCALL(FMAX_F128, "fmaxl")
306306
HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl")
307+
HANDLE_LIBCALL(FMINIMUM_F32, "fminimumf")
308+
HANDLE_LIBCALL(FMINIMUM_F64, "fminimum")
309+
HANDLE_LIBCALL(FMINIMUM_F80, "fminimuml")
310+
HANDLE_LIBCALL(FMINIMUM_F128, "fminmuml")
311+
HANDLE_LIBCALL(FMINIMUM_PPCF128, "fminimuml")
312+
HANDLE_LIBCALL(FMAXIMUM_F32, "fmaximumf")
313+
HANDLE_LIBCALL(FMAXIMUM_F64, "fmaximum")
314+
HANDLE_LIBCALL(FMAXIMUM_F80, "fmaximuml")
315+
HANDLE_LIBCALL(FMAXIMUM_F128, "fmaxmuml")
316+
HANDLE_LIBCALL(FMAXIMUM_PPCF128, "fmaximum_numl")
307317
HANDLE_LIBCALL(FMINIMUMNUM_F32, "fminimum_numf")
308318
HANDLE_LIBCALL(FMINIMUMNUM_F64, "fminimum_num")
309319
HANDLE_LIBCALL(FMINIMUMNUM_F80, "fminimum_numl")

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
7676
case ISD::FMAXNUM: R = SoftenFloatRes_FMAXNUM(N); break;
7777
case ISD::FMINIMUMNUM: R = SoftenFloatRes_FMINIMUMNUM(N); break;
7878
case ISD::FMAXIMUMNUM: R = SoftenFloatRes_FMAXIMUMNUM(N); break;
79+
case ISD::FMINIMUM: R = SoftenFloatRes_FMINIMUM(N); break;
80+
case ISD::FMAXIMUM: R = SoftenFloatRes_FMAXIMUM(N); break;
7981
case ISD::STRICT_FADD:
8082
case ISD::FADD: R = SoftenFloatRes_FADD(N); break;
8183
case ISD::STRICT_FACOS:
@@ -342,6 +344,20 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUMNUM(SDNode *N) {
342344
RTLIB::FMAXIMUMNUM_F128, RTLIB::FMAXIMUMNUM_PPCF128));
343345
}
344346

347+
SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUM(SDNode *N) {
348+
return SoftenFloatRes_Binary(
349+
N, GetFPLibCall(N->getValueType(0), RTLIB::FMINIMUM_F32,
350+
RTLIB::FMINIMUM_F64, RTLIB::FMINIMUM_F80,
351+
RTLIB::FMINIMUM_F128, RTLIB::FMINIMUM_PPCF128));
352+
}
353+
354+
SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUM(SDNode *N) {
355+
return SoftenFloatRes_Binary(
356+
N, GetFPLibCall(N->getValueType(0), RTLIB::FMAXIMUM_F32,
357+
RTLIB::FMAXIMUM_F64, RTLIB::FMAXIMUM_F80,
358+
RTLIB::FMAXIMUM_F128, RTLIB::FMAXIMUM_PPCF128));
359+
}
360+
345361
SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
346362
return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
347363
RTLIB::ADD_F32,

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
572572
SDValue SoftenFloatRes_FMAXNUM(SDNode *N);
573573
SDValue SoftenFloatRes_FMINIMUMNUM(SDNode *N);
574574
SDValue SoftenFloatRes_FMAXIMUMNUM(SDNode *N);
575+
SDValue SoftenFloatRes_FMINIMUM(SDNode *N);
576+
SDValue SoftenFloatRes_FMAXIMUM(SDNode *N);
575577
SDValue SoftenFloatRes_FADD(SDNode *N);
576578
SDValue SoftenFloatRes_FCBRT(SDNode *N);
577579
SDValue SoftenFloatRes_FCEIL(SDNode *N);

llvm/test/CodeGen/RISCV/float-maximum-minimum.ll

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+d \
99
; RUN: -verify-machineinstrs -target-abi=ilp32f \
1010
; RUN: | FileCheck -check-prefix=RV32IF %s
11+
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 \
12+
; RUN: -verify-machineinstrs -target-abi=ilp32 \
13+
; RUN: | FileCheck -check-prefix=RV32I %s
1114
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f \
1215
; RUN: -verify-machineinstrs -target-abi=lp64f \
1316
; RUN: | FileCheck -check-prefix=RV64IF %s
@@ -17,6 +20,9 @@
1720
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+d \
1821
; RUN: -verify-machineinstrs -target-abi=lp64d \
1922
; RUN: | FileCheck -check-prefix=RV64IF %s
23+
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 \
24+
; RUN: -verify-machineinstrs -target-abi=lp64 \
25+
; RUN: | FileCheck -check-prefix=RV64I %s
2026

2127
declare float @llvm.minimum.f32(float, float)
2228

@@ -59,6 +65,15 @@ define float @fminimum_f32(float %a, float %b) nounwind {
5965
; RV32IZFINX-NEXT: fmin.s a0, a1, a2
6066
; RV32IZFINX-NEXT: ret
6167
;
68+
; RV32I-LABEL: fminimum_f32:
69+
; RV32I: # %bb.0:
70+
; RV32I-NEXT: addi sp, sp, -16
71+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
72+
; RV32I-NEXT: call fminimumf
73+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
74+
; RV32I-NEXT: addi sp, sp, 16
75+
; RV32I-NEXT: ret
76+
;
6277
; RV64IF-LABEL: fminimum_f32:
6378
; RV64IF: # %bb.0:
6479
; RV64IF-NEXT: feq.s a0, fa0, fa0
@@ -96,6 +111,15 @@ define float @fminimum_f32(float %a, float %b) nounwind {
96111
; RV64IZFINX-NEXT: .LBB0_4:
97112
; RV64IZFINX-NEXT: fmin.s a0, a1, a2
98113
; RV64IZFINX-NEXT: ret
114+
;
115+
; RV64I-LABEL: fminimum_f32:
116+
; RV64I: # %bb.0:
117+
; RV64I-NEXT: addi sp, sp, -16
118+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
119+
; RV64I-NEXT: call fminimumf
120+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
121+
; RV64I-NEXT: addi sp, sp, 16
122+
; RV64I-NEXT: ret
99123
%1 = call float @llvm.minimum.f32(float %a, float %b)
100124
ret float %1
101125
}
@@ -141,6 +165,15 @@ define float @fmaximum_f32(float %a, float %b) nounwind {
141165
; RV32IZFINX-NEXT: fmax.s a0, a1, a2
142166
; RV32IZFINX-NEXT: ret
143167
;
168+
; RV32I-LABEL: fmaximum_f32:
169+
; RV32I: # %bb.0:
170+
; RV32I-NEXT: addi sp, sp, -16
171+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
172+
; RV32I-NEXT: call fmaximumf
173+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
174+
; RV32I-NEXT: addi sp, sp, 16
175+
; RV32I-NEXT: ret
176+
;
144177
; RV64IF-LABEL: fmaximum_f32:
145178
; RV64IF: # %bb.0:
146179
; RV64IF-NEXT: feq.s a0, fa0, fa0
@@ -178,6 +211,15 @@ define float @fmaximum_f32(float %a, float %b) nounwind {
178211
; RV64IZFINX-NEXT: .LBB1_4:
179212
; RV64IZFINX-NEXT: fmax.s a0, a1, a2
180213
; RV64IZFINX-NEXT: ret
214+
;
215+
; RV64I-LABEL: fmaximum_f32:
216+
; RV64I: # %bb.0:
217+
; RV64I-NEXT: addi sp, sp, -16
218+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
219+
; RV64I-NEXT: call fmaximumf
220+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
221+
; RV64I-NEXT: addi sp, sp, 16
222+
; RV64I-NEXT: ret
181223
%1 = call float @llvm.maximum.f32(float %a, float %b)
182224
ret float %1
183225
}
@@ -193,6 +235,15 @@ define float @fminimum_nnan_f32(float %a, float %b) nounwind {
193235
; RV32IZFINX-NEXT: fmin.s a0, a0, a1
194236
; RV32IZFINX-NEXT: ret
195237
;
238+
; RV32I-LABEL: fminimum_nnan_f32:
239+
; RV32I: # %bb.0:
240+
; RV32I-NEXT: addi sp, sp, -16
241+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
242+
; RV32I-NEXT: call fminimumf
243+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
244+
; RV32I-NEXT: addi sp, sp, 16
245+
; RV32I-NEXT: ret
246+
;
196247
; RV64IF-LABEL: fminimum_nnan_f32:
197248
; RV64IF: # %bb.0:
198249
; RV64IF-NEXT: fmin.s fa0, fa0, fa1
@@ -202,6 +253,15 @@ define float @fminimum_nnan_f32(float %a, float %b) nounwind {
202253
; RV64IZFINX: # %bb.0:
203254
; RV64IZFINX-NEXT: fmin.s a0, a0, a1
204255
; RV64IZFINX-NEXT: ret
256+
;
257+
; RV64I-LABEL: fminimum_nnan_f32:
258+
; RV64I: # %bb.0:
259+
; RV64I-NEXT: addi sp, sp, -16
260+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
261+
; RV64I-NEXT: call fminimumf
262+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
263+
; RV64I-NEXT: addi sp, sp, 16
264+
; RV64I-NEXT: ret
205265
%1 = call nnan float @llvm.minimum.f32(float %a, float %b)
206266
ret float %1
207267
}
@@ -217,6 +277,15 @@ define float @fmaximum_nnan_f32(float %a, float %b) nounwind {
217277
; RV32IZFINX-NEXT: fmax.s a0, a0, a1
218278
; RV32IZFINX-NEXT: ret
219279
;
280+
; RV32I-LABEL: fmaximum_nnan_f32:
281+
; RV32I: # %bb.0:
282+
; RV32I-NEXT: addi sp, sp, -16
283+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
284+
; RV32I-NEXT: call fmaximumf
285+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
286+
; RV32I-NEXT: addi sp, sp, 16
287+
; RV32I-NEXT: ret
288+
;
220289
; RV64IF-LABEL: fmaximum_nnan_f32:
221290
; RV64IF: # %bb.0:
222291
; RV64IF-NEXT: fmax.s fa0, fa0, fa1
@@ -226,6 +295,15 @@ define float @fmaximum_nnan_f32(float %a, float %b) nounwind {
226295
; RV64IZFINX: # %bb.0:
227296
; RV64IZFINX-NEXT: fmax.s a0, a0, a1
228297
; RV64IZFINX-NEXT: ret
298+
;
299+
; RV64I-LABEL: fmaximum_nnan_f32:
300+
; RV64I: # %bb.0:
301+
; RV64I-NEXT: addi sp, sp, -16
302+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
303+
; RV64I-NEXT: call fmaximumf
304+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
305+
; RV64I-NEXT: addi sp, sp, 16
306+
; RV64I-NEXT: ret
229307
%1 = call nnan float @llvm.maximum.f32(float %a, float %b)
230308
ret float %1
231309
}
@@ -241,6 +319,15 @@ define float @fminimum_nnan_attr_f32(float %a, float %b) nounwind "no-nans-fp-ma
241319
; RV32IZFINX-NEXT: fmin.s a0, a0, a1
242320
; RV32IZFINX-NEXT: ret
243321
;
322+
; RV32I-LABEL: fminimum_nnan_attr_f32:
323+
; RV32I: # %bb.0:
324+
; RV32I-NEXT: addi sp, sp, -16
325+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
326+
; RV32I-NEXT: call fminimumf
327+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
328+
; RV32I-NEXT: addi sp, sp, 16
329+
; RV32I-NEXT: ret
330+
;
244331
; RV64IF-LABEL: fminimum_nnan_attr_f32:
245332
; RV64IF: # %bb.0:
246333
; RV64IF-NEXT: fmin.s fa0, fa0, fa1
@@ -250,6 +337,15 @@ define float @fminimum_nnan_attr_f32(float %a, float %b) nounwind "no-nans-fp-ma
250337
; RV64IZFINX: # %bb.0:
251338
; RV64IZFINX-NEXT: fmin.s a0, a0, a1
252339
; RV64IZFINX-NEXT: ret
340+
;
341+
; RV64I-LABEL: fminimum_nnan_attr_f32:
342+
; RV64I: # %bb.0:
343+
; RV64I-NEXT: addi sp, sp, -16
344+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
345+
; RV64I-NEXT: call fminimumf
346+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
347+
; RV64I-NEXT: addi sp, sp, 16
348+
; RV64I-NEXT: ret
253349
%1 = call float @llvm.minimum.f32(float %a, float %b)
254350
ret float %1
255351
}
@@ -279,6 +375,22 @@ define float @fminimum_nnan_op_f32(float %a, float %b) nounwind {
279375
; RV32IZFINX-NEXT: fmin.s a0, a0, a1
280376
; RV32IZFINX-NEXT: ret
281377
;
378+
; RV32I-LABEL: fminimum_nnan_op_f32:
379+
; RV32I: # %bb.0:
380+
; RV32I-NEXT: addi sp, sp, -16
381+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
382+
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
383+
; RV32I-NEXT: mv s0, a0
384+
; RV32I-NEXT: mv a1, a0
385+
; RV32I-NEXT: call __addsf3
386+
; RV32I-NEXT: mv a1, a0
387+
; RV32I-NEXT: mv a0, s0
388+
; RV32I-NEXT: call fminimumf
389+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
390+
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
391+
; RV32I-NEXT: addi sp, sp, 16
392+
; RV32I-NEXT: ret
393+
;
282394
; RV64IF-LABEL: fminimum_nnan_op_f32:
283395
; RV64IF: # %bb.0:
284396
; RV64IF-NEXT: feq.s a0, fa0, fa0
@@ -302,6 +414,22 @@ define float @fminimum_nnan_op_f32(float %a, float %b) nounwind {
302414
; RV64IZFINX-NEXT: fadd.s a1, a0, a0
303415
; RV64IZFINX-NEXT: fmin.s a0, a0, a1
304416
; RV64IZFINX-NEXT: ret
417+
;
418+
; RV64I-LABEL: fminimum_nnan_op_f32:
419+
; RV64I: # %bb.0:
420+
; RV64I-NEXT: addi sp, sp, -16
421+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
422+
; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
423+
; RV64I-NEXT: mv s0, a0
424+
; RV64I-NEXT: mv a1, a0
425+
; RV64I-NEXT: call __addsf3
426+
; RV64I-NEXT: mv a1, a0
427+
; RV64I-NEXT: mv a0, s0
428+
; RV64I-NEXT: call fminimumf
429+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
430+
; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
431+
; RV64I-NEXT: addi sp, sp, 16
432+
; RV64I-NEXT: ret
305433
%c = fadd nnan float %a, %a
306434
%1 = call float @llvm.minimum.f32(float %a, float %c)
307435
ret float %1
@@ -322,6 +450,30 @@ define float @fmaximum_nnan_op_f32(float %a, float %b) nounwind {
322450
; RV32IZFINX-NEXT: fmax.s a0, a2, a0
323451
; RV32IZFINX-NEXT: ret
324452
;
453+
; RV32I-LABEL: fmaximum_nnan_op_f32:
454+
; RV32I: # %bb.0:
455+
; RV32I-NEXT: addi sp, sp, -16
456+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
457+
; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
458+
; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
459+
; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
460+
; RV32I-NEXT: mv s0, a1
461+
; RV32I-NEXT: mv s1, a0
462+
; RV32I-NEXT: call __addsf3
463+
; RV32I-NEXT: mv s2, a0
464+
; RV32I-NEXT: mv a0, s1
465+
; RV32I-NEXT: mv a1, s0
466+
; RV32I-NEXT: call __subsf3
467+
; RV32I-NEXT: mv a1, a0
468+
; RV32I-NEXT: mv a0, s2
469+
; RV32I-NEXT: call fmaximumf
470+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
471+
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
472+
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
473+
; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
474+
; RV32I-NEXT: addi sp, sp, 16
475+
; RV32I-NEXT: ret
476+
;
325477
; RV64IF-LABEL: fmaximum_nnan_op_f32:
326478
; RV64IF: # %bb.0:
327479
; RV64IF-NEXT: fadd.s fa5, fa0, fa1
@@ -335,6 +487,30 @@ define float @fmaximum_nnan_op_f32(float %a, float %b) nounwind {
335487
; RV64IZFINX-NEXT: fsub.s a0, a0, a1
336488
; RV64IZFINX-NEXT: fmax.s a0, a2, a0
337489
; RV64IZFINX-NEXT: ret
490+
;
491+
; RV64I-LABEL: fmaximum_nnan_op_f32:
492+
; RV64I: # %bb.0:
493+
; RV64I-NEXT: addi sp, sp, -32
494+
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
495+
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
496+
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
497+
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
498+
; RV64I-NEXT: mv s0, a1
499+
; RV64I-NEXT: mv s1, a0
500+
; RV64I-NEXT: call __addsf3
501+
; RV64I-NEXT: mv s2, a0
502+
; RV64I-NEXT: mv a0, s1
503+
; RV64I-NEXT: mv a1, s0
504+
; RV64I-NEXT: call __subsf3
505+
; RV64I-NEXT: mv a1, a0
506+
; RV64I-NEXT: mv a0, s2
507+
; RV64I-NEXT: call fmaximumf
508+
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
509+
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
510+
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
511+
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
512+
; RV64I-NEXT: addi sp, sp, 32
513+
; RV64I-NEXT: ret
338514
%c = fadd nnan float %a, %b
339515
%d = fsub nnan float %a, %b
340516
%1 = call float @llvm.maximum.f32(float %c, float %d)

0 commit comments

Comments
 (0)