Skip to content

Commit 03edfe6

Browse files
authored
Implement SoftPromoteHalf for FFREXP. (#74076)
`llvm/test/CodeGen/RISCV/llvm.frexp.ll` and `llvm/test/CodeGen/X86/llvm.frexp.ll` contain a number of disabled tests for unimplemented functionality. This implements one missing part of it.
1 parent 2f29ded commit 03edfe6

File tree

4 files changed

+633
-140
lines changed

4 files changed

+633
-140
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,6 +2774,8 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
27742774
case ISD::FPOWI:
27752775
case ISD::FLDEXP: R = SoftPromoteHalfRes_ExpOp(N); break;
27762776

2777+
case ISD::FFREXP: R = SoftPromoteHalfRes_FFREXP(N); break;
2778+
27772779
case ISD::LOAD: R = SoftPromoteHalfRes_LOAD(N); break;
27782780
case ISD::SELECT: R = SoftPromoteHalfRes_SELECT(N); break;
27792781
case ISD::SELECT_CC: R = SoftPromoteHalfRes_SELECT_CC(N); break;
@@ -2902,6 +2904,24 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ExpOp(SDNode *N) {
29022904
return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
29032905
}
29042906

2907+
SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FFREXP(SDNode *N) {
2908+
EVT OVT = N->getValueType(0);
2909+
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
2910+
SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
2911+
SDLoc dl(N);
2912+
2913+
// Promote to the larger FP type.
2914+
Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
2915+
2916+
SDValue Res = DAG.getNode(N->getOpcode(), dl,
2917+
DAG.getVTList(NVT, N->getValueType(1)), Op);
2918+
2919+
ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
2920+
2921+
// Convert back to FP16 as an integer.
2922+
return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
2923+
}
2924+
29052925
SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
29062926
EVT RVT = N->getValueType(0);
29072927
EVT SVT = N->getOperand(0).getValueType();

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
738738
SDValue SoftPromoteHalfRes_FCOPYSIGN(SDNode *N);
739739
SDValue SoftPromoteHalfRes_FMAD(SDNode *N);
740740
SDValue SoftPromoteHalfRes_ExpOp(SDNode *N);
741+
SDValue SoftPromoteHalfRes_FFREXP(SDNode *N);
741742
SDValue SoftPromoteHalfRes_FP_ROUND(SDNode *N);
742743
SDValue SoftPromoteHalfRes_LOAD(SDNode *N);
743744
SDValue SoftPromoteHalfRes_SELECT(SDNode *N);

llvm/test/CodeGen/RISCV/llvm.frexp.ll

Lines changed: 270 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,279 @@
1818

1919
; TODO: FIXMEs are copied blindly across from the X86 version of this test.
2020

21-
; FIXME
22-
; define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
23-
; %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
24-
; ret { half, i32 } %result
25-
; }
21+
define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
22+
; RV32IFD-LABEL: test_frexp_f16_i32:
23+
; RV32IFD: # %bb.0:
24+
; RV32IFD-NEXT: addi sp, sp, -16
25+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
26+
; RV32IFD-NEXT: call __extendhfsf2@plt
27+
; RV32IFD-NEXT: addi a0, sp, 8
28+
; RV32IFD-NEXT: call frexpf@plt
29+
; RV32IFD-NEXT: call __truncsfhf2@plt
30+
; RV32IFD-NEXT: fmv.x.w a1, fa0
31+
; RV32IFD-NEXT: lw a0, 8(sp)
32+
; RV32IFD-NEXT: lui a2, 1048560
33+
; RV32IFD-NEXT: or a1, a1, a2
34+
; RV32IFD-NEXT: fmv.w.x fa0, a1
35+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
36+
; RV32IFD-NEXT: addi sp, sp, 16
37+
; RV32IFD-NEXT: ret
38+
;
39+
; RV64IFD-LABEL: test_frexp_f16_i32:
40+
; RV64IFD: # %bb.0:
41+
; RV64IFD-NEXT: addi sp, sp, -16
42+
; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
43+
; RV64IFD-NEXT: call __extendhfsf2@plt
44+
; RV64IFD-NEXT: mv a0, sp
45+
; RV64IFD-NEXT: call frexpf@plt
46+
; RV64IFD-NEXT: call __truncsfhf2@plt
47+
; RV64IFD-NEXT: fmv.x.w a1, fa0
48+
; RV64IFD-NEXT: ld a0, 0(sp)
49+
; RV64IFD-NEXT: lui a2, 1048560
50+
; RV64IFD-NEXT: or a1, a1, a2
51+
; RV64IFD-NEXT: fmv.w.x fa0, a1
52+
; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
53+
; RV64IFD-NEXT: addi sp, sp, 16
54+
; RV64IFD-NEXT: ret
55+
;
56+
; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32:
57+
; RV32IZFINXZDINX: # %bb.0:
58+
; RV32IZFINXZDINX-NEXT: addi sp, sp, -16
59+
; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
60+
; RV32IZFINXZDINX-NEXT: call __extendhfsf2@plt
61+
; RV32IZFINXZDINX-NEXT: addi a1, sp, 8
62+
; RV32IZFINXZDINX-NEXT: call frexpf@plt
63+
; RV32IZFINXZDINX-NEXT: call __truncsfhf2@plt
64+
; RV32IZFINXZDINX-NEXT: lw a1, 8(sp)
65+
; RV32IZFINXZDINX-NEXT: lui a2, 1048560
66+
; RV32IZFINXZDINX-NEXT: or a0, a0, a2
67+
; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
68+
; RV32IZFINXZDINX-NEXT: addi sp, sp, 16
69+
; RV32IZFINXZDINX-NEXT: ret
70+
;
71+
; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32:
72+
; RV64IZFINXZDINX: # %bb.0:
73+
; RV64IZFINXZDINX-NEXT: addi sp, sp, -16
74+
; RV64IZFINXZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
75+
; RV64IZFINXZDINX-NEXT: call __extendhfsf2@plt
76+
; RV64IZFINXZDINX-NEXT: mv a1, sp
77+
; RV64IZFINXZDINX-NEXT: call frexpf@plt
78+
; RV64IZFINXZDINX-NEXT: call __truncsfhf2@plt
79+
; RV64IZFINXZDINX-NEXT: ld a1, 0(sp)
80+
; RV64IZFINXZDINX-NEXT: lui a2, 1048560
81+
; RV64IZFINXZDINX-NEXT: or a0, a0, a2
82+
; RV64IZFINXZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
83+
; RV64IZFINXZDINX-NEXT: addi sp, sp, 16
84+
; RV64IZFINXZDINX-NEXT: ret
85+
;
86+
; RV32I-LABEL: test_frexp_f16_i32:
87+
; RV32I: # %bb.0:
88+
; RV32I-NEXT: addi sp, sp, -16
89+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
90+
; RV32I-NEXT: slli a0, a0, 16
91+
; RV32I-NEXT: srli a0, a0, 16
92+
; RV32I-NEXT: call __extendhfsf2@plt
93+
; RV32I-NEXT: addi a1, sp, 8
94+
; RV32I-NEXT: call frexpf@plt
95+
; RV32I-NEXT: call __truncsfhf2@plt
96+
; RV32I-NEXT: lw a1, 8(sp)
97+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
98+
; RV32I-NEXT: addi sp, sp, 16
99+
; RV32I-NEXT: ret
100+
;
101+
; RV64I-LABEL: test_frexp_f16_i32:
102+
; RV64I: # %bb.0:
103+
; RV64I-NEXT: addi sp, sp, -16
104+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
105+
; RV64I-NEXT: slli a0, a0, 48
106+
; RV64I-NEXT: srli a0, a0, 48
107+
; RV64I-NEXT: call __extendhfsf2@plt
108+
; RV64I-NEXT: addi a1, sp, 4
109+
; RV64I-NEXT: call frexpf@plt
110+
; RV64I-NEXT: call __truncsfhf2@plt
111+
; RV64I-NEXT: lw a1, 4(sp)
112+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
113+
; RV64I-NEXT: addi sp, sp, 16
114+
; RV64I-NEXT: ret
115+
%result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
116+
ret { half, i32 } %result
117+
}
26118

27-
; define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
28-
; %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
29-
; %result.0 = extractvalue { half, i32 } %result, 0
30-
; ret half %result.0
31-
; }
119+
define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
120+
; RV32IFD-LABEL: test_frexp_f16_i32_only_use_fract:
121+
; RV32IFD: # %bb.0:
122+
; RV32IFD-NEXT: addi sp, sp, -16
123+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
124+
; RV32IFD-NEXT: call __extendhfsf2@plt
125+
; RV32IFD-NEXT: addi a0, sp, 8
126+
; RV32IFD-NEXT: call frexpf@plt
127+
; RV32IFD-NEXT: call __truncsfhf2@plt
128+
; RV32IFD-NEXT: fmv.x.w a0, fa0
129+
; RV32IFD-NEXT: lui a1, 1048560
130+
; RV32IFD-NEXT: or a0, a0, a1
131+
; RV32IFD-NEXT: fmv.w.x fa0, a0
132+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
133+
; RV32IFD-NEXT: addi sp, sp, 16
134+
; RV32IFD-NEXT: ret
135+
;
136+
; RV64IFD-LABEL: test_frexp_f16_i32_only_use_fract:
137+
; RV64IFD: # %bb.0:
138+
; RV64IFD-NEXT: addi sp, sp, -16
139+
; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
140+
; RV64IFD-NEXT: call __extendhfsf2@plt
141+
; RV64IFD-NEXT: mv a0, sp
142+
; RV64IFD-NEXT: call frexpf@plt
143+
; RV64IFD-NEXT: call __truncsfhf2@plt
144+
; RV64IFD-NEXT: fmv.x.w a0, fa0
145+
; RV64IFD-NEXT: lui a1, 1048560
146+
; RV64IFD-NEXT: or a0, a0, a1
147+
; RV64IFD-NEXT: fmv.w.x fa0, a0
148+
; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
149+
; RV64IFD-NEXT: addi sp, sp, 16
150+
; RV64IFD-NEXT: ret
151+
;
152+
; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_fract:
153+
; RV32IZFINXZDINX: # %bb.0:
154+
; RV32IZFINXZDINX-NEXT: addi sp, sp, -16
155+
; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
156+
; RV32IZFINXZDINX-NEXT: call __extendhfsf2@plt
157+
; RV32IZFINXZDINX-NEXT: addi a1, sp, 8
158+
; RV32IZFINXZDINX-NEXT: call frexpf@plt
159+
; RV32IZFINXZDINX-NEXT: call __truncsfhf2@plt
160+
; RV32IZFINXZDINX-NEXT: lui a1, 1048560
161+
; RV32IZFINXZDINX-NEXT: or a0, a0, a1
162+
; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
163+
; RV32IZFINXZDINX-NEXT: addi sp, sp, 16
164+
; RV32IZFINXZDINX-NEXT: ret
165+
;
166+
; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_fract:
167+
; RV64IZFINXZDINX: # %bb.0:
168+
; RV64IZFINXZDINX-NEXT: addi sp, sp, -16
169+
; RV64IZFINXZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
170+
; RV64IZFINXZDINX-NEXT: call __extendhfsf2@plt
171+
; RV64IZFINXZDINX-NEXT: mv a1, sp
172+
; RV64IZFINXZDINX-NEXT: call frexpf@plt
173+
; RV64IZFINXZDINX-NEXT: call __truncsfhf2@plt
174+
; RV64IZFINXZDINX-NEXT: lui a1, 1048560
175+
; RV64IZFINXZDINX-NEXT: or a0, a0, a1
176+
; RV64IZFINXZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
177+
; RV64IZFINXZDINX-NEXT: addi sp, sp, 16
178+
; RV64IZFINXZDINX-NEXT: ret
179+
;
180+
; RV32I-LABEL: test_frexp_f16_i32_only_use_fract:
181+
; RV32I: # %bb.0:
182+
; RV32I-NEXT: addi sp, sp, -16
183+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
184+
; RV32I-NEXT: slli a0, a0, 16
185+
; RV32I-NEXT: srli a0, a0, 16
186+
; RV32I-NEXT: call __extendhfsf2@plt
187+
; RV32I-NEXT: addi a1, sp, 8
188+
; RV32I-NEXT: call frexpf@plt
189+
; RV32I-NEXT: call __truncsfhf2@plt
190+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
191+
; RV32I-NEXT: addi sp, sp, 16
192+
; RV32I-NEXT: ret
193+
;
194+
; RV64I-LABEL: test_frexp_f16_i32_only_use_fract:
195+
; RV64I: # %bb.0:
196+
; RV64I-NEXT: addi sp, sp, -16
197+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
198+
; RV64I-NEXT: slli a0, a0, 48
199+
; RV64I-NEXT: srli a0, a0, 48
200+
; RV64I-NEXT: call __extendhfsf2@plt
201+
; RV64I-NEXT: addi a1, sp, 4
202+
; RV64I-NEXT: call frexpf@plt
203+
; RV64I-NEXT: call __truncsfhf2@plt
204+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
205+
; RV64I-NEXT: addi sp, sp, 16
206+
; RV64I-NEXT: ret
207+
%result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
208+
%result.0 = extractvalue { half, i32 } %result, 0
209+
ret half %result.0
210+
}
32211

33-
; define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
34-
; %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
35-
; %result.0 = extractvalue { half, i32 } %result, 1
36-
; ret i32 %result.0
37-
; }
212+
define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
213+
; RV32IFD-LABEL: test_frexp_f16_i32_only_use_exp:
214+
; RV32IFD: # %bb.0:
215+
; RV32IFD-NEXT: addi sp, sp, -16
216+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
217+
; RV32IFD-NEXT: call __extendhfsf2@plt
218+
; RV32IFD-NEXT: addi a0, sp, 8
219+
; RV32IFD-NEXT: call frexpf@plt
220+
; RV32IFD-NEXT: lw a0, 8(sp)
221+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
222+
; RV32IFD-NEXT: addi sp, sp, 16
223+
; RV32IFD-NEXT: ret
224+
;
225+
; RV64IFD-LABEL: test_frexp_f16_i32_only_use_exp:
226+
; RV64IFD: # %bb.0:
227+
; RV64IFD-NEXT: addi sp, sp, -16
228+
; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
229+
; RV64IFD-NEXT: call __extendhfsf2@plt
230+
; RV64IFD-NEXT: mv a0, sp
231+
; RV64IFD-NEXT: call frexpf@plt
232+
; RV64IFD-NEXT: ld a0, 0(sp)
233+
; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
234+
; RV64IFD-NEXT: addi sp, sp, 16
235+
; RV64IFD-NEXT: ret
236+
;
237+
; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_exp:
238+
; RV32IZFINXZDINX: # %bb.0:
239+
; RV32IZFINXZDINX-NEXT: addi sp, sp, -16
240+
; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
241+
; RV32IZFINXZDINX-NEXT: call __extendhfsf2@plt
242+
; RV32IZFINXZDINX-NEXT: addi a1, sp, 8
243+
; RV32IZFINXZDINX-NEXT: call frexpf@plt
244+
; RV32IZFINXZDINX-NEXT: lw a0, 8(sp)
245+
; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
246+
; RV32IZFINXZDINX-NEXT: addi sp, sp, 16
247+
; RV32IZFINXZDINX-NEXT: ret
248+
;
249+
; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_exp:
250+
; RV64IZFINXZDINX: # %bb.0:
251+
; RV64IZFINXZDINX-NEXT: addi sp, sp, -16
252+
; RV64IZFINXZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
253+
; RV64IZFINXZDINX-NEXT: call __extendhfsf2@plt
254+
; RV64IZFINXZDINX-NEXT: mv a1, sp
255+
; RV64IZFINXZDINX-NEXT: call frexpf@plt
256+
; RV64IZFINXZDINX-NEXT: ld a0, 0(sp)
257+
; RV64IZFINXZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
258+
; RV64IZFINXZDINX-NEXT: addi sp, sp, 16
259+
; RV64IZFINXZDINX-NEXT: ret
260+
;
261+
; RV32I-LABEL: test_frexp_f16_i32_only_use_exp:
262+
; RV32I: # %bb.0:
263+
; RV32I-NEXT: addi sp, sp, -16
264+
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
265+
; RV32I-NEXT: slli a0, a0, 16
266+
; RV32I-NEXT: srli a0, a0, 16
267+
; RV32I-NEXT: call __extendhfsf2@plt
268+
; RV32I-NEXT: addi a1, sp, 8
269+
; RV32I-NEXT: call frexpf@plt
270+
; RV32I-NEXT: lw a0, 8(sp)
271+
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
272+
; RV32I-NEXT: addi sp, sp, 16
273+
; RV32I-NEXT: ret
274+
;
275+
; RV64I-LABEL: test_frexp_f16_i32_only_use_exp:
276+
; RV64I: # %bb.0:
277+
; RV64I-NEXT: addi sp, sp, -16
278+
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
279+
; RV64I-NEXT: slli a0, a0, 48
280+
; RV64I-NEXT: srli a0, a0, 48
281+
; RV64I-NEXT: call __extendhfsf2@plt
282+
; RV64I-NEXT: addi a1, sp, 4
283+
; RV64I-NEXT: call frexpf@plt
284+
; RV64I-NEXT: lw a0, 4(sp)
285+
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
286+
; RV64I-NEXT: addi sp, sp, 16
287+
; RV64I-NEXT: ret
288+
%result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
289+
%result.0 = extractvalue { half, i32 } %result, 1
290+
ret i32 %result.0
291+
}
38292

293+
; FIXME
39294
; define { <2 x half>, <2 x i32> } @test_frexp_v2f16_v2i32(<2 x half> %a) nounwind {
40295
; %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
41296
; ret { <2 x half>, <2 x i32> } %result

0 commit comments

Comments
 (0)