xref: /llvm-project/llvm/test/CodeGen/RISCV/float-zfa.ll (revision 261d4bbb3bb847b90b9734daefe13618dea91613)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -target-abi ilp32f -mattr=+zfa < %s \
3; RUN:     | FileCheck %s
4; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+zfa < %s \
5; RUN:     | FileCheck %s
6
7define float @loadfpimm1() {
8; CHECK-LABEL: loadfpimm1:
9; CHECK:       # %bb.0:
10; CHECK-NEXT:    fli.s fa0, 0.0625
11; CHECK-NEXT:    ret
12  ret float 0.0625
13}
14
15define float @loadfpimm2() {
16; CHECK-LABEL: loadfpimm2:
17; CHECK:       # %bb.0:
18; CHECK-NEXT:    fli.s fa0, 0.75
19; CHECK-NEXT:    ret
20  ret float 0.75
21}
22
23define float @loadfpimm3() {
24; CHECK-LABEL: loadfpimm3:
25; CHECK:       # %bb.0:
26; CHECK-NEXT:    fli.s fa0, 1.25
27; CHECK-NEXT:    ret
28  ret float 1.25
29}
30
31define float @loadfpimm4() {
32; CHECK-LABEL: loadfpimm4:
33; CHECK:       # %bb.0:
34; CHECK-NEXT:    fli.s fa0, 3.0
35; CHECK-NEXT:    ret
36  ret float 3.0
37}
38
39define float @loadfpimm5() {
40; CHECK-LABEL: loadfpimm5:
41; CHECK:       # %bb.0:
42; CHECK-NEXT:    fli.s fa0, 256.0
43; CHECK-NEXT:    ret
44  ret float 256.0
45}
46
47define float @loadfpimm6() {
48; CHECK-LABEL: loadfpimm6:
49; CHECK:       # %bb.0:
50; CHECK-NEXT:    fli.s fa0, inf
51; CHECK-NEXT:    ret
52  ret float 0x7FF0000000000000
53}
54
55define float @loadfpimm7() {
56; CHECK-LABEL: loadfpimm7:
57; CHECK:       # %bb.0:
58; CHECK-NEXT:    fli.s fa0, nan
59; CHECK-NEXT:    ret
60  ret float 0x7FF8000000000000
61}
62
63define float @loadfpimm8() {
64; CHECK-LABEL: loadfpimm8:
65; CHECK:       # %bb.0:
66; CHECK-NEXT:    fli.s fa0, min
67; CHECK-NEXT:    ret
68  ret float 0x3810000000000000
69}
70
71define float @loadfpimm9() {
72; CHECK-LABEL: loadfpimm9:
73; CHECK:       # %bb.0:
74; CHECK-NEXT:    lui a0, 276464
75; CHECK-NEXT:    fmv.w.x fa0, a0
76; CHECK-NEXT:    ret
77  ret float 255.0
78}
79
80; This is the f16 minimum value. Make sure we don't use fli.s.
81define float @loadfpimm10() {
82; CHECK-LABEL: loadfpimm10:
83; CHECK:       # %bb.0:
84; CHECK-NEXT:    lui a0, 231424
85; CHECK-NEXT:    fmv.w.x fa0, a0
86; CHECK-NEXT:    ret
87  ret float 0.00006103515625
88}
89
90define float @loadfpimm11() {
91; CHECK-LABEL: loadfpimm11:
92; CHECK:       # %bb.0:
93; CHECK-NEXT:    fli.s fa0, -1.0
94; CHECK-NEXT:    ret
95  ret float -1.0
96}
97
98; Ensure fli isn't directly used for negated versions of numbers in the fli
99; table.
100define float @loadfpimm12() {
101; CHECK-LABEL: loadfpimm12:
102; CHECK:       # %bb.0:
103; CHECK-NEXT:    fli.s fa5, 2.0
104; CHECK-NEXT:    fneg.s fa0, fa5
105; CHECK-NEXT:    ret
106  ret float -2.0
107}
108
109; Ensure fli isn't directly used for negative min normal value.
110define float @loadfpimm13() {
111; CHECK-LABEL: loadfpimm13:
112; CHECK:       # %bb.0:
113; CHECK-NEXT:    fli.s fa5, min
114; CHECK-NEXT:    fneg.s fa0, fa5
115; CHECK-NEXT:    ret
116  ret float 0xb810000000000000
117}
118
119declare float @llvm.minimum.f32(float, float)
120
121define float @fminm_s(float %a, float %b) nounwind {
122; CHECK-LABEL: fminm_s:
123; CHECK:       # %bb.0:
124; CHECK-NEXT:    fminm.s fa0, fa0, fa1
125; CHECK-NEXT:    ret
126  %1 = call float @llvm.minimum.f32(float %a, float %b)
127  ret float %1
128}
129
130declare float @llvm.maximum.f32(float, float)
131
132define float @fmaxm_s(float %a, float %b) nounwind {
133; CHECK-LABEL: fmaxm_s:
134; CHECK:       # %bb.0:
135; CHECK-NEXT:    fmaxm.s fa0, fa0, fa1
136; CHECK-NEXT:    ret
137  %1 = call float @llvm.maximum.f32(float %a, float %b)
138  ret float %1
139}
140
141
142define float @fround_s_1(float %a) nounwind {
143; CHECK-LABEL: fround_s_1:
144; CHECK:       # %bb.0:
145; CHECK-NEXT:    fround.s fa0, fa0, rmm
146; CHECK-NEXT:    ret
147  %call = tail call float @roundf(float %a) nounwind readnone
148  ret float %call
149}
150
151declare float @roundf(float) nounwind readnone
152
153
154define float @fround_s_2(float %a) nounwind {
155; CHECK-LABEL: fround_s_2:
156; CHECK:       # %bb.0:
157; CHECK-NEXT:    fround.s fa0, fa0, rdn
158; CHECK-NEXT:    ret
159  %call = tail call float @floorf(float %a) nounwind readnone
160  ret float %call
161}
162
163declare float @floorf(float) nounwind readnone
164
165
166define float @fround_s_3(float %a) nounwind {
167; CHECK-LABEL: fround_s_3:
168; CHECK:       # %bb.0:
169; CHECK-NEXT:    fround.s fa0, fa0, rup
170; CHECK-NEXT:    ret
171  %call = tail call float @ceilf(float %a) nounwind readnone
172  ret float %call
173}
174
175declare float @ceilf(float) nounwind readnone
176
177
178define float @fround_s_4(float %a) nounwind {
179; CHECK-LABEL: fround_s_4:
180; CHECK:       # %bb.0:
181; CHECK-NEXT:    fround.s fa0, fa0, rtz
182; CHECK-NEXT:    ret
183  %call = tail call float @truncf(float %a) nounwind readnone
184  ret float %call
185}
186
187declare float @truncf(float) nounwind readnone
188
189
190define float @fround_s_5(float %a) nounwind {
191; CHECK-LABEL: fround_s_5:
192; CHECK:       # %bb.0:
193; CHECK-NEXT:    fround.s fa0, fa0
194; CHECK-NEXT:    ret
195  %call = tail call float @nearbyintf(float %a) nounwind readnone
196  ret float %call
197}
198
199declare float @nearbyintf(float) nounwind readnone
200
201define float @fround_s_6(float %a) nounwind {
202; CHECK-LABEL: fround_s_6:
203; CHECK:       # %bb.0:
204; CHECK-NEXT:    fround.s fa0, fa0, rne
205; CHECK-NEXT:    ret
206  %call = tail call float @llvm.roundeven.f32(float %a) nounwind readnone
207  ret float %call
208}
209
210declare float @llvm.roundeven.f32(float) nounwind readnone
211
212
213define float @froundnx_s(float %a) nounwind {
214; CHECK-LABEL: froundnx_s:
215; CHECK:       # %bb.0:
216; CHECK-NEXT:    froundnx.s fa0, fa0
217; CHECK-NEXT:    ret
218  %call = tail call float @rintf(float %a) nounwind readnone
219  ret float %call
220}
221
222declare float @rintf(float) nounwind readnone
223
224declare i1 @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata)
225
226define i32 @fcmp_olt_q(float %a, float %b) nounwind strictfp {
227; CHECK-LABEL: fcmp_olt_q:
228; CHECK:       # %bb.0:
229; CHECK-NEXT:    fltq.s a0, fa0, fa1
230; CHECK-NEXT:    ret
231  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"olt", metadata !"fpexcept.strict") strictfp
232  %2 = zext i1 %1 to i32
233  ret i32 %2
234}
235
236define i32 @fcmp_ole_q(float %a, float %b) nounwind strictfp {
237; CHECK-LABEL: fcmp_ole_q:
238; CHECK:       # %bb.0:
239; CHECK-NEXT:    fleq.s a0, fa0, fa1
240; CHECK-NEXT:    ret
241  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ole", metadata !"fpexcept.strict") strictfp
242  %2 = zext i1 %1 to i32
243  ret i32 %2
244}
245
246define i32 @fcmp_one_q(float %a, float %b) nounwind strictfp {
247; CHECK-LABEL: fcmp_one_q:
248; CHECK:       # %bb.0:
249; CHECK-NEXT:    fltq.s a0, fa0, fa1
250; CHECK-NEXT:    fltq.s a1, fa1, fa0
251; CHECK-NEXT:    or a0, a1, a0
252; CHECK-NEXT:    ret
253  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"one", metadata !"fpexcept.strict") strictfp
254  %2 = zext i1 %1 to i32
255  ret i32 %2
256}
257
258define i32 @fcmp_ueq_q(float %a, float %b) nounwind strictfp {
259; CHECK-LABEL: fcmp_ueq_q:
260; CHECK:       # %bb.0:
261; CHECK-NEXT:    fltq.s a0, fa0, fa1
262; CHECK-NEXT:    fltq.s a1, fa1, fa0
263; CHECK-NEXT:    or a0, a1, a0
264; CHECK-NEXT:    xori a0, a0, 1
265; CHECK-NEXT:    ret
266  %1 = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp
267  %2 = zext i1 %1 to i32
268  ret i32 %2
269}
270
271declare void @foo(float, float)
272
273; Make sure we use two fli instructions instead of copying.
274define void @fli_remat() {
275; CHECK-LABEL: fli_remat:
276; CHECK:       # %bb.0:
277; CHECK-NEXT:    fli.s fa0, 1.0
278; CHECK-NEXT:    fli.s fa1, 1.0
279; CHECK-NEXT:    tail foo
280  tail call void @foo(float 1.000000e+00, float 1.000000e+00)
281  ret void
282}
283
284define float @fadd_neg_0p5(float %x) {
285; CHECK-LABEL: fadd_neg_0p5:
286; CHECK:       # %bb.0:
287; CHECK-NEXT:    fli.s fa5, 0.5
288; CHECK-NEXT:    fsub.s fa0, fa0, fa5
289; CHECK-NEXT:    ret
290  %a = fadd float %x, -0.5
291  ret float %a
292}
293
294define float @fma_neg_addend(float %x, float %y) nounwind {
295; CHECK-LABEL: fma_neg_addend:
296; CHECK:       # %bb.0:
297; CHECK-NEXT:    fli.s fa5, 0.5
298; CHECK-NEXT:    fmsub.s fa0, fa0, fa1, fa5
299; CHECK-NEXT:    ret
300  %a = call float @llvm.fma.f32(float %x, float %y, float -0.5)
301  ret float %a
302}
303
304define float @fma_neg_multiplicand(float %x, float %y) nounwind {
305; CHECK-LABEL: fma_neg_multiplicand:
306; CHECK:       # %bb.0:
307; CHECK-NEXT:    fli.s fa5, 0.125
308; CHECK-NEXT:    fnmsub.s fa0, fa5, fa0, fa1
309; CHECK-NEXT:    ret
310  %a = call float @llvm.fma.f32(float %x, float -0.125, float %y)
311  ret float %a
312}
313
314define float @fma_neg_addend_multiplicand(float %x) nounwind {
315; CHECK-LABEL: fma_neg_addend_multiplicand:
316; CHECK:       # %bb.0:
317; CHECK-NEXT:    fli.s fa5, 0.25
318; CHECK-NEXT:    fli.s fa4, 0.5
319; CHECK-NEXT:    fnmadd.s fa0, fa4, fa0, fa5
320; CHECK-NEXT:    ret
321  %a = call float @llvm.fma.f32(float %x, float -0.5, float -0.25)
322  ret float %a
323}
324
325define float @select_loadfpimm(float %x) nounwind {
326; CHECK-LABEL: select_loadfpimm:
327; CHECK:       # %bb.0: # %entry
328; CHECK-NEXT:    fmv.w.x fa5, zero
329; CHECK-NEXT:    fle.s a0, fa5, fa0
330; CHECK-NEXT:    fli.s fa0, 0.5
331; CHECK-NEXT:    bnez a0, .LBB31_2
332; CHECK-NEXT:  # %bb.1:
333; CHECK-NEXT:    fneg.s fa0, fa0
334; CHECK-NEXT:  .LBB31_2: # %entry
335; CHECK-NEXT:    ret
336entry:
337  %cmp = fcmp ult float %x, 0.000000e+00
338  %sel = select i1 %cmp, float -5.000000e-01, float 5.000000e-01
339  ret float %sel
340}
341