Skip to content

Commit b57cbbc

Browse files
committed
[RISCV][GISel] Improve fptos/ui and s/uitofp handling and testing.
Replace clampScalar of the integer type with minScalar. We can't narrow the integer type, we can only make it larger. If the type is larger than xLen we need to use a 2*xlen libcall. If it's larger than 2*xlen we can't handle it at all.
1 parent 375d192 commit b57cbbc

File tree

5 files changed

+839
-3
lines changed

5 files changed

+839
-3
lines changed

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
9090
const LLT s16 = LLT::scalar(16);
9191
const LLT s32 = LLT::scalar(32);
9292
const LLT s64 = LLT::scalar(64);
93+
const LLT s128 = LLT::scalar(128);
9394

9495
const LLT nxv1s1 = LLT::scalable_vector(1, s1);
9596
const LLT nxv2s1 = LLT::scalable_vector(2, s1);
@@ -535,13 +536,16 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
535536
getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
536537
.legalIf(all(typeInSet(0, {s32, sXLen}), typeIsScalarFPArith(1, ST)))
537538
.widenScalarToNextPow2(0)
538-
.clampScalar(0, s32, sXLen)
539-
.libcall();
539+
.minScalar(0, s32)
540+
.libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
541+
.libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}});
540542

541543
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
542544
.legalIf(all(typeIsScalarFPArith(0, ST), typeInSet(1, {s32, sXLen})))
543545
.widenScalarToNextPow2(1)
544-
.clampScalar(1, s32, sXLen);
546+
.minScalar(1, s32)
547+
.libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
548+
.libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}});
545549

546550
// FIXME: We can do custom inline expansion like SelectionDAG.
547551
// FIXME: Legal with Zfa.
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv32 -global-isel -mattr=+d -verify-machineinstrs < %s \
3+
; RUN: -target-abi=ilp32d | FileCheck -check-prefixes=CHECKIFD,RV32IFD %s
4+
; RUN: llc -mtriple=riscv64 -global-isel -mattr=+d -verify-machineinstrs < %s \
5+
; RUN: -target-abi=lp64d | FileCheck -check-prefixes=CHECKIFD,RV64IFD %s
6+
7+
define float @fcvt_s_d(double %a) nounwind {
8+
; CHECKIFD-LABEL: fcvt_s_d:
9+
; CHECKIFD: # %bb.0:
10+
; CHECKIFD-NEXT: fcvt.s.d fa0, fa0
11+
; CHECKIFD-NEXT: ret
12+
%1 = fptrunc double %a to float
13+
ret float %1
14+
}
15+
16+
define double @fcvt_d_s(float %a) nounwind {
17+
; CHECKIFD-LABEL: fcvt_d_s:
18+
; CHECKIFD: # %bb.0:
19+
; CHECKIFD-NEXT: fcvt.d.s fa0, fa0
20+
; CHECKIFD-NEXT: ret
21+
%1 = fpext float %a to double
22+
ret double %1
23+
}
24+
25+
define i32 @fcvt_w_d(double %a) nounwind {
26+
; CHECKIFD-LABEL: fcvt_w_d:
27+
; CHECKIFD: # %bb.0:
28+
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rtz
29+
; CHECKIFD-NEXT: ret
30+
%1 = fptosi double %a to i32
31+
ret i32 %1
32+
}
33+
34+
define i32 @fcvt_wu_d(double %a) nounwind {
35+
; CHECKIFD-LABEL: fcvt_wu_d:
36+
; CHECKIFD: # %bb.0:
37+
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rtz
38+
; CHECKIFD-NEXT: ret
39+
%1 = fptoui double %a to i32
40+
ret i32 %1
41+
}
42+
43+
define i32 @fcvt_wu_d_multiple_use(double %x, ptr %y) nounwind {
44+
; RV32IFD-LABEL: fcvt_wu_d_multiple_use:
45+
; RV32IFD: # %bb.0:
46+
; RV32IFD-NEXT: fcvt.wu.d a1, fa0, rtz
47+
; RV32IFD-NEXT: li a0, 1
48+
; RV32IFD-NEXT: beqz a1, .LBB4_2
49+
; RV32IFD-NEXT: # %bb.1:
50+
; RV32IFD-NEXT: mv a0, a1
51+
; RV32IFD-NEXT: .LBB4_2:
52+
; RV32IFD-NEXT: ret
53+
;
54+
; RV64IFD-LABEL: fcvt_wu_d_multiple_use:
55+
; RV64IFD: # %bb.0:
56+
; RV64IFD-NEXT: fcvt.wu.d a1, fa0, rtz
57+
; RV64IFD-NEXT: slli a0, a1, 32
58+
; RV64IFD-NEXT: srli a2, a0, 32
59+
; RV64IFD-NEXT: li a0, 1
60+
; RV64IFD-NEXT: beqz a2, .LBB4_2
61+
; RV64IFD-NEXT: # %bb.1:
62+
; RV64IFD-NEXT: mv a0, a1
63+
; RV64IFD-NEXT: .LBB4_2:
64+
; RV64IFD-NEXT: ret
65+
%a = fptoui double %x to i32
66+
%b = icmp eq i32 %a, 0
67+
%c = select i1 %b, i32 1, i32 %a
68+
ret i32 %c
69+
}
70+
71+
define double @fcvt_d_w(i32 %a) nounwind {
72+
; CHECKIFD-LABEL: fcvt_d_w:
73+
; CHECKIFD: # %bb.0:
74+
; CHECKIFD-NEXT: fcvt.d.w fa0, a0
75+
; CHECKIFD-NEXT: ret
76+
%1 = sitofp i32 %a to double
77+
ret double %1
78+
}
79+
80+
define double @fcvt_d_w_load(ptr %p) nounwind {
81+
; CHECKIFD-LABEL: fcvt_d_w_load:
82+
; CHECKIFD: # %bb.0:
83+
; CHECKIFD-NEXT: lw a0, 0(a0)
84+
; CHECKIFD-NEXT: fcvt.d.w fa0, a0
85+
; CHECKIFD-NEXT: ret
86+
%a = load i32, ptr %p
87+
%1 = sitofp i32 %a to double
88+
ret double %1
89+
}
90+
91+
define double @fcvt_d_wu(i32 %a) nounwind {
92+
; CHECKIFD-LABEL: fcvt_d_wu:
93+
; CHECKIFD: # %bb.0:
94+
; CHECKIFD-NEXT: fcvt.d.wu fa0, a0
95+
; CHECKIFD-NEXT: ret
96+
%1 = uitofp i32 %a to double
97+
ret double %1
98+
}
99+
100+
define double @fcvt_d_wu_load(ptr %p) nounwind {
101+
; CHECKIFD-LABEL: fcvt_d_wu_load:
102+
; CHECKIFD: # %bb.0:
103+
; CHECKIFD-NEXT: lw a0, 0(a0)
104+
; CHECKIFD-NEXT: fcvt.d.wu fa0, a0
105+
; CHECKIFD-NEXT: ret
106+
%a = load i32, ptr %p
107+
%1 = uitofp i32 %a to double
108+
ret double %1
109+
}
110+
111+
define i64 @fcvt_l_d(double %a) nounwind {
112+
; RV32IFD-LABEL: fcvt_l_d:
113+
; RV32IFD: # %bb.0:
114+
; RV32IFD-NEXT: addi sp, sp, -16
115+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
116+
; RV32IFD-NEXT: call __fixdfdi
117+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
118+
; RV32IFD-NEXT: addi sp, sp, 16
119+
; RV32IFD-NEXT: ret
120+
;
121+
; RV64IFD-LABEL: fcvt_l_d:
122+
; RV64IFD: # %bb.0:
123+
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rtz
124+
; RV64IFD-NEXT: ret
125+
%1 = fptosi double %a to i64
126+
ret i64 %1
127+
}
128+
129+
define i64 @fcvt_lu_d(double %a) nounwind {
130+
; RV32IFD-LABEL: fcvt_lu_d:
131+
; RV32IFD: # %bb.0:
132+
; RV32IFD-NEXT: addi sp, sp, -16
133+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
134+
; RV32IFD-NEXT: call __fixunsdfdi
135+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
136+
; RV32IFD-NEXT: addi sp, sp, 16
137+
; RV32IFD-NEXT: ret
138+
;
139+
; RV64IFD-LABEL: fcvt_lu_d:
140+
; RV64IFD: # %bb.0:
141+
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rtz
142+
; RV64IFD-NEXT: ret
143+
%1 = fptoui double %a to i64
144+
ret i64 %1
145+
}
146+
147+
define i64 @fmv_x_d(double %a, double %b) nounwind {
148+
; RV32IFD-LABEL: fmv_x_d:
149+
; RV32IFD: # %bb.0:
150+
; RV32IFD-NEXT: addi sp, sp, -16
151+
; RV32IFD-NEXT: fadd.d fa5, fa0, fa1
152+
; RV32IFD-NEXT: fsd fa5, 8(sp)
153+
; RV32IFD-NEXT: lw a0, 8(sp)
154+
; RV32IFD-NEXT: lw a1, 12(sp)
155+
; RV32IFD-NEXT: addi sp, sp, 16
156+
; RV32IFD-NEXT: ret
157+
;
158+
; RV64IFD-LABEL: fmv_x_d:
159+
; RV64IFD: # %bb.0:
160+
; RV64IFD-NEXT: fadd.d fa5, fa0, fa1
161+
; RV64IFD-NEXT: fmv.x.d a0, fa5
162+
; RV64IFD-NEXT: ret
163+
%1 = fadd double %a, %b
164+
%2 = bitcast double %1 to i64
165+
ret i64 %2
166+
}
167+
168+
define double @fcvt_d_l(i64 %a) nounwind {
169+
; RV32IFD-LABEL: fcvt_d_l:
170+
; RV32IFD: # %bb.0:
171+
; RV32IFD-NEXT: addi sp, sp, -16
172+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
173+
; RV32IFD-NEXT: call __floatdidf
174+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
175+
; RV32IFD-NEXT: addi sp, sp, 16
176+
; RV32IFD-NEXT: ret
177+
;
178+
; RV64IFD-LABEL: fcvt_d_l:
179+
; RV64IFD: # %bb.0:
180+
; RV64IFD-NEXT: fcvt.d.l fa0, a0
181+
; RV64IFD-NEXT: ret
182+
%1 = sitofp i64 %a to double
183+
ret double %1
184+
}
185+
186+
define double @fcvt_d_lu(i64 %a) nounwind {
187+
; RV32IFD-LABEL: fcvt_d_lu:
188+
; RV32IFD: # %bb.0:
189+
; RV32IFD-NEXT: addi sp, sp, -16
190+
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
191+
; RV32IFD-NEXT: call __floatundidf
192+
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
193+
; RV32IFD-NEXT: addi sp, sp, 16
194+
; RV32IFD-NEXT: ret
195+
;
196+
; RV64IFD-LABEL: fcvt_d_lu:
197+
; RV64IFD: # %bb.0:
198+
; RV64IFD-NEXT: fcvt.d.lu fa0, a0
199+
; RV64IFD-NEXT: ret
200+
%1 = uitofp i64 %a to double
201+
ret double %1
202+
}
203+
204+
define double @fmv_d_x(i64 %a, i64 %b) nounwind {
205+
; RV32IFD-LABEL: fmv_d_x:
206+
; RV32IFD: # %bb.0:
207+
; RV32IFD-NEXT: addi sp, sp, -16
208+
; RV32IFD-NEXT: sw a0, 8(sp)
209+
; RV32IFD-NEXT: sw a1, 12(sp)
210+
; RV32IFD-NEXT: fld fa5, 8(sp)
211+
; RV32IFD-NEXT: sw a2, 8(sp)
212+
; RV32IFD-NEXT: sw a3, 12(sp)
213+
; RV32IFD-NEXT: fld fa4, 8(sp)
214+
; RV32IFD-NEXT: fadd.d fa0, fa5, fa4
215+
; RV32IFD-NEXT: addi sp, sp, 16
216+
; RV32IFD-NEXT: ret
217+
;
218+
; RV64IFD-LABEL: fmv_d_x:
219+
; RV64IFD: # %bb.0:
220+
; RV64IFD-NEXT: fmv.d.x fa5, a0
221+
; RV64IFD-NEXT: fmv.d.x fa4, a1
222+
; RV64IFD-NEXT: fadd.d fa0, fa5, fa4
223+
; RV64IFD-NEXT: ret
224+
%1 = bitcast i64 %a to double
225+
%2 = bitcast i64 %b to double
226+
%3 = fadd double %1, %2
227+
ret double %3
228+
}
229+
230+
define double @fcvt_d_w_i8(i8 signext %a) nounwind {
231+
; CHECKIFD-LABEL: fcvt_d_w_i8:
232+
; CHECKIFD: # %bb.0:
233+
; CHECKIFD-NEXT: fcvt.d.w fa0, a0
234+
; CHECKIFD-NEXT: ret
235+
%1 = sitofp i8 %a to double
236+
ret double %1
237+
}
238+
239+
define double @fcvt_d_wu_i8(i8 zeroext %a) nounwind {
240+
; CHECKIFD-LABEL: fcvt_d_wu_i8:
241+
; CHECKIFD: # %bb.0:
242+
; CHECKIFD-NEXT: fcvt.d.wu fa0, a0
243+
; CHECKIFD-NEXT: ret
244+
%1 = uitofp i8 %a to double
245+
ret double %1
246+
}
247+
248+
define double @fcvt_d_w_i16(i16 signext %a) nounwind {
249+
; CHECKIFD-LABEL: fcvt_d_w_i16:
250+
; CHECKIFD: # %bb.0:
251+
; CHECKIFD-NEXT: fcvt.d.w fa0, a0
252+
; CHECKIFD-NEXT: ret
253+
%1 = sitofp i16 %a to double
254+
ret double %1
255+
}
256+
257+
define double @fcvt_d_wu_i16(i16 zeroext %a) nounwind {
258+
; CHECKIFD-LABEL: fcvt_d_wu_i16:
259+
; CHECKIFD: # %bb.0:
260+
; CHECKIFD-NEXT: fcvt.d.wu fa0, a0
261+
; CHECKIFD-NEXT: ret
262+
%1 = uitofp i16 %a to double
263+
ret double %1
264+
}
265+
266+
define signext i32 @fcvt_d_w_demanded_bits(i32 signext %0, ptr %1) nounwind {
267+
; RV32IFD-LABEL: fcvt_d_w_demanded_bits:
268+
; RV32IFD: # %bb.0:
269+
; RV32IFD-NEXT: addi a0, a0, 1
270+
; RV32IFD-NEXT: fcvt.d.w fa5, a0
271+
; RV32IFD-NEXT: fsd fa5, 0(a1)
272+
; RV32IFD-NEXT: ret
273+
;
274+
; RV64IFD-LABEL: fcvt_d_w_demanded_bits:
275+
; RV64IFD: # %bb.0:
276+
; RV64IFD-NEXT: addiw a0, a0, 1
277+
; RV64IFD-NEXT: fcvt.d.w fa5, a0
278+
; RV64IFD-NEXT: fsd fa5, 0(a1)
279+
; RV64IFD-NEXT: ret
280+
%3 = add i32 %0, 1
281+
%4 = sitofp i32 %3 to double
282+
store double %4, ptr %1, align 8
283+
ret i32 %3
284+
}
285+
286+
define signext i32 @fcvt_d_wu_demanded_bits(i32 signext %0, ptr %1) nounwind {
287+
; RV32IFD-LABEL: fcvt_d_wu_demanded_bits:
288+
; RV32IFD: # %bb.0:
289+
; RV32IFD-NEXT: addi a0, a0, 1
290+
; RV32IFD-NEXT: fcvt.d.wu fa5, a0
291+
; RV32IFD-NEXT: fsd fa5, 0(a1)
292+
; RV32IFD-NEXT: ret
293+
;
294+
; RV64IFD-LABEL: fcvt_d_wu_demanded_bits:
295+
; RV64IFD: # %bb.0:
296+
; RV64IFD-NEXT: addiw a0, a0, 1
297+
; RV64IFD-NEXT: fcvt.d.wu fa5, a0
298+
; RV64IFD-NEXT: fsd fa5, 0(a1)
299+
; RV64IFD-NEXT: ret
300+
%3 = add i32 %0, 1
301+
%4 = uitofp i32 %3 to double
302+
store double %4, ptr %1, align 8
303+
ret i32 %3
304+
}
305+
306+
define signext i16 @fcvt_w_s_i16(double %a) nounwind {
307+
; RV32IFD-LABEL: fcvt_w_s_i16:
308+
; RV32IFD: # %bb.0:
309+
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rtz
310+
; RV32IFD-NEXT: slli a0, a0, 16
311+
; RV32IFD-NEXT: srai a0, a0, 16
312+
; RV32IFD-NEXT: ret
313+
;
314+
; RV64IFD-LABEL: fcvt_w_s_i16:
315+
; RV64IFD: # %bb.0:
316+
; RV64IFD-NEXT: fcvt.w.d a0, fa0, rtz
317+
; RV64IFD-NEXT: slli a0, a0, 48
318+
; RV64IFD-NEXT: srai a0, a0, 48
319+
; RV64IFD-NEXT: ret
320+
%1 = fptosi double %a to i16
321+
ret i16 %1
322+
}
323+
324+
define zeroext i16 @fcvt_wu_s_i16(double %a) nounwind {
325+
; RV32IFD-LABEL: fcvt_wu_s_i16:
326+
; RV32IFD: # %bb.0:
327+
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rtz
328+
; RV32IFD-NEXT: lui a1, 16
329+
; RV32IFD-NEXT: addi a1, a1, -1
330+
; RV32IFD-NEXT: and a0, a0, a1
331+
; RV32IFD-NEXT: ret
332+
;
333+
; RV64IFD-LABEL: fcvt_wu_s_i16:
334+
; RV64IFD: # %bb.0:
335+
; RV64IFD-NEXT: fcvt.wu.d a0, fa0, rtz
336+
; RV64IFD-NEXT: lui a1, 16
337+
; RV64IFD-NEXT: addiw a1, a1, -1
338+
; RV64IFD-NEXT: and a0, a0, a1
339+
; RV64IFD-NEXT: ret
340+
%1 = fptoui double %a to i16
341+
ret i16 %1
342+
}
343+
344+
define signext i8 @fcvt_w_s_i8(double %a) nounwind {
345+
; RV32IFD-LABEL: fcvt_w_s_i8:
346+
; RV32IFD: # %bb.0:
347+
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rtz
348+
; RV32IFD-NEXT: slli a0, a0, 24
349+
; RV32IFD-NEXT: srai a0, a0, 24
350+
; RV32IFD-NEXT: ret
351+
;
352+
; RV64IFD-LABEL: fcvt_w_s_i8:
353+
; RV64IFD: # %bb.0:
354+
; RV64IFD-NEXT: fcvt.w.d a0, fa0, rtz
355+
; RV64IFD-NEXT: slli a0, a0, 56
356+
; RV64IFD-NEXT: srai a0, a0, 56
357+
; RV64IFD-NEXT: ret
358+
%1 = fptosi double %a to i8
359+
ret i8 %1
360+
}
361+
362+
define zeroext i8 @fcvt_wu_s_i8(double %a) nounwind {
363+
; CHECKIFD-LABEL: fcvt_wu_s_i8:
364+
; CHECKIFD: # %bb.0:
365+
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rtz
366+
; CHECKIFD-NEXT: andi a0, a0, 255
367+
; CHECKIFD-NEXT: ret
368+
%1 = fptoui double %a to i8
369+
ret i8 %1
370+
}

0 commit comments

Comments
 (0)