xref: /llvm-project/llvm/test/CodeGen/RISCV/double-zfa.ll (revision 261d4bbb3bb847b90b9734daefe13618dea91613)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+zfa,+d < %s \
3; RUN:     | FileCheck --check-prefixes=CHECK,RV32IDZFA %s
4; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+zfa,+d < %s \
5; RUN:     | FileCheck --check-prefixes=CHECK,RV64DZFA %s
6
7define double @loadfpimm1() {
8; CHECK-LABEL: loadfpimm1:
9; CHECK:       # %bb.0:
10; CHECK-NEXT:    fli.d fa0, 0.0625
11; CHECK-NEXT:    ret
12  ret double 0.0625
13}
14
15define double @loadfpimm2() {
16; CHECK-LABEL: loadfpimm2:
17; CHECK:       # %bb.0:
18; CHECK-NEXT:    fli.d fa0, 0.75
19; CHECK-NEXT:    ret
20  ret double 0.75
21}
22
23define double @loadfpimm3() {
24; CHECK-LABEL: loadfpimm3:
25; CHECK:       # %bb.0:
26; CHECK-NEXT:    fli.d fa0, 1.25
27; CHECK-NEXT:    ret
28  ret double 1.25
29}
30
31define double @loadfpimm4() {
32; CHECK-LABEL: loadfpimm4:
33; CHECK:       # %bb.0:
34; CHECK-NEXT:    fli.d fa0, 3.0
35; CHECK-NEXT:    ret
36  ret double 3.0
37}
38
39define double @loadfpimm5() {
40; CHECK-LABEL: loadfpimm5:
41; CHECK:       # %bb.0:
42; CHECK-NEXT:    fli.d fa0, 256.0
43; CHECK-NEXT:    ret
44  ret double 256.0
45}
46
47define double @loadfpimm6() {
48; CHECK-LABEL: loadfpimm6:
49; CHECK:       # %bb.0:
50; CHECK-NEXT:    fli.d fa0, inf
51; CHECK-NEXT:    ret
52  ret double 0x7FF0000000000000
53}
54
55define double @loadfpimm7() {
56; CHECK-LABEL: loadfpimm7:
57; CHECK:       # %bb.0:
58; CHECK-NEXT:    fli.d fa0, nan
59; CHECK-NEXT:    ret
60  ret double 0x7FF8000000000000
61}
62
63define double @loadfpimm8() {
64; CHECK-LABEL: loadfpimm8:
65; CHECK:       # %bb.0:
66; CHECK-NEXT:    fli.d fa0, min
67; CHECK-NEXT:    ret
68  ret double 0x0010000000000000
69}
70
71define double @loadfpimm9() {
72; CHECK-LABEL: loadfpimm9:
73; CHECK:       # %bb.0:
74; CHECK-NEXT:    lui a0, %hi(.LCPI8_0)
75; CHECK-NEXT:    fld fa0, %lo(.LCPI8_0)(a0)
76; CHECK-NEXT:    ret
77  ret double 255.0
78}
79
80; Negative test. This is 1 * 2^256.
81define double @loadfpimm10() {
82; CHECK-LABEL: loadfpimm10:
83; CHECK:       # %bb.0:
84; CHECK-NEXT:    lui a0, %hi(.LCPI9_0)
85; CHECK-NEXT:    fld fa0, %lo(.LCPI9_0)(a0)
86; CHECK-NEXT:    ret
87  ret double 0x1000000000000000
88}
89
90; Negative test. This is a qnan with payload of 1.
91define double @loadfpimm11() {
92; CHECK-LABEL: loadfpimm11:
93; CHECK:       # %bb.0:
94; CHECK-NEXT:    lui a0, %hi(.LCPI10_0)
95; CHECK-NEXT:    fld fa0, %lo(.LCPI10_0)(a0)
96; CHECK-NEXT:    ret
97  ret double 0x7ff8000000000001
98}
99
100; Negative test. This is an snan with payload of 1.
101define double @loadfpimm12() {
102; CHECK-LABEL: loadfpimm12:
103; CHECK:       # %bb.0:
104; CHECK-NEXT:    lui a0, %hi(.LCPI11_0)
105; CHECK-NEXT:    fld fa0, %lo(.LCPI11_0)(a0)
106; CHECK-NEXT:    ret
107  ret double 0x7ff0000000000001
108}
109
110; Negative test. This is the smallest denormal.
111define double @loadfpimm13() {
112; RV32IDZFA-LABEL: loadfpimm13:
113; RV32IDZFA:       # %bb.0:
114; RV32IDZFA-NEXT:    lui a0, %hi(.LCPI12_0)
115; RV32IDZFA-NEXT:    fld fa0, %lo(.LCPI12_0)(a0)
116; RV32IDZFA-NEXT:    ret
117;
118; RV64DZFA-LABEL: loadfpimm13:
119; RV64DZFA:       # %bb.0:
120; RV64DZFA-NEXT:    li a0, 1
121; RV64DZFA-NEXT:    fmv.d.x fa0, a0
122; RV64DZFA-NEXT:    ret
123  ret double 0x0000000000000001
124}
125
126; Negative test. This is 2^-1023, a denormal.
127define double @loadfpimm15() {
128; CHECK-LABEL: loadfpimm15:
129; CHECK:       # %bb.0:
130; CHECK-NEXT:    lui a0, %hi(.LCPI13_0)
131; CHECK-NEXT:    fld fa0, %lo(.LCPI13_0)(a0)
132; CHECK-NEXT:    ret
133  ret double 0x0008000000000000
134}
135
136define double @loadfpimm16() {
137; CHECK-LABEL: loadfpimm16:
138; CHECK:       # %bb.0:
139; CHECK-NEXT:    fli.d fa0, -1.0
140; CHECK-NEXT:    ret
141  ret double -1.0
142}
143
144; Ensure fli isn't directly used for negated versions of numbers in the fli
145; table.
146define double @loadfpimm17() {
147; CHECK-LABEL: loadfpimm17:
148; CHECK:       # %bb.0:
149; CHECK-NEXT:    fli.d fa5, 2.0
150; CHECK-NEXT:    fneg.d fa0, fa5
151; CHECK-NEXT:    ret
152  ret double -2.0
153}
154
155; Ensure fli isn't directly used for negative min normal value.
156define double @loadfpimm18() {
157; CHECK-LABEL: loadfpimm18:
158; CHECK:       # %bb.0:
159; CHECK-NEXT:    fli.d fa5, min
160; CHECK-NEXT:    fneg.d fa0, fa5
161; CHECK-NEXT:    ret
162  ret double 0x8010000000000000
163}
164
165declare double @llvm.minimum.f64(double, double)
166
167define double @fminm_d(double %a, double %b) nounwind {
168; CHECK-LABEL: fminm_d:
169; CHECK:       # %bb.0:
170; CHECK-NEXT:    fminm.d fa0, fa0, fa1
171; CHECK-NEXT:    ret
172  %1 = call double @llvm.minimum.f64(double %a, double %b)
173  ret double %1
174}
175
176declare double @llvm.maximum.f64(double, double)
177
178define double @fmaxm_d(double %a, double %b) nounwind {
179; CHECK-LABEL: fmaxm_d:
180; CHECK:       # %bb.0:
181; CHECK-NEXT:    fmaxm.d fa0, fa0, fa1
182; CHECK-NEXT:    ret
183  %1 = call double @llvm.maximum.f64(double %a, double %b)
184  ret double %1
185}
186
187define double @fround_d_1(double %a) nounwind {
188; CHECK-LABEL: fround_d_1:
189; CHECK:       # %bb.0:
190; CHECK-NEXT:    fround.d fa0, fa0, rmm
191; CHECK-NEXT:    ret
192  %call = tail call double @round(double %a) nounwind readnone
193  ret double %call
194}
195
196declare double @round(double) nounwind readnone
197
198
199define double @fround_d_2(double %a) nounwind {
200; CHECK-LABEL: fround_d_2:
201; CHECK:       # %bb.0:
202; CHECK-NEXT:    fround.d fa0, fa0, rdn
203; CHECK-NEXT:    ret
204  %call = tail call double @floor(double %a) nounwind readnone
205  ret double %call
206}
207
208declare double @floor(double) nounwind readnone
209
210
211define double @fround_d_3(double %a) nounwind {
212; CHECK-LABEL: fround_d_3:
213; CHECK:       # %bb.0:
214; CHECK-NEXT:    fround.d fa0, fa0, rup
215; CHECK-NEXT:    ret
216  %call = tail call double @ceil(double %a) nounwind readnone
217  ret double %call
218}
219
220declare double @ceil(double) nounwind readnone
221
222
223define double @fround_d_4(double %a) nounwind {
224; CHECK-LABEL: fround_d_4:
225; CHECK:       # %bb.0:
226; CHECK-NEXT:    fround.d fa0, fa0, rtz
227; CHECK-NEXT:    ret
228  %call = tail call double @trunc(double %a) nounwind readnone
229  ret double %call
230}
231
232declare double @trunc(double) nounwind readnone
233
234
235define double @fround_d_5(double %a) nounwind {
236; CHECK-LABEL: fround_d_5:
237; CHECK:       # %bb.0:
238; CHECK-NEXT:    fround.d fa0, fa0
239; CHECK-NEXT:    ret
240  %call = tail call double @nearbyint(double %a) nounwind readnone
241  ret double %call
242}
243
244declare double @nearbyint(double) nounwind readnone
245
246define double @fround_d_6(double %a) nounwind {
247; CHECK-LABEL: fround_d_6:
248; CHECK:       # %bb.0:
249; CHECK-NEXT:    fround.d fa0, fa0, rne
250; CHECK-NEXT:    ret
251  %call = tail call double @llvm.roundeven.f64(double %a) nounwind readnone
252  ret double %call
253}
254
255declare double @llvm.roundeven.f64(double) nounwind readnone
256
257
258define double @froundnx_d(double %a) nounwind {
259; CHECK-LABEL: froundnx_d:
260; CHECK:       # %bb.0:
261; CHECK-NEXT:    froundnx.d fa0, fa0
262; CHECK-NEXT:    ret
263  %call = tail call double @rint(double %a) nounwind readnone
264  ret double %call
265}
266
267declare double @rint(double) nounwind readnone
268
269declare i1 @llvm.experimental.constrained.fcmp.f64(double, double, metadata, metadata)
270
271define i32 @fcmp_olt_q(double %a, double %b) nounwind strictfp {
272; CHECK-LABEL: fcmp_olt_q:
273; CHECK:       # %bb.0:
274; CHECK-NEXT:    fltq.d a0, fa0, fa1
275; CHECK-NEXT:    ret
276  %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"olt", metadata !"fpexcept.strict") strictfp
277  %2 = zext i1 %1 to i32
278  ret i32 %2
279}
280
281define i32 @fcmp_ole_q(double %a, double %b) nounwind strictfp {
282; CHECK-LABEL: fcmp_ole_q:
283; CHECK:       # %bb.0:
284; CHECK-NEXT:    fleq.d a0, fa0, fa1
285; CHECK-NEXT:    ret
286  %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"ole", metadata !"fpexcept.strict") strictfp
287  %2 = zext i1 %1 to i32
288  ret i32 %2
289}
290
291define i32 @fcmp_one_q(double %a, double %b) nounwind strictfp {
292; CHECK-LABEL: fcmp_one_q:
293; CHECK:       # %bb.0:
294; CHECK-NEXT:    fltq.d a0, fa0, fa1
295; CHECK-NEXT:    fltq.d a1, fa1, fa0
296; CHECK-NEXT:    or a0, a1, a0
297; CHECK-NEXT:    ret
298  %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"one", metadata !"fpexcept.strict") strictfp
299  %2 = zext i1 %1 to i32
300  ret i32 %2
301}
302
303define i32 @fcmp_ueq_q(double %a, double %b) nounwind strictfp {
304; CHECK-LABEL: fcmp_ueq_q:
305; CHECK:       # %bb.0:
306; CHECK-NEXT:    fltq.d a0, fa0, fa1
307; CHECK-NEXT:    fltq.d a1, fa1, fa0
308; CHECK-NEXT:    or a0, a1, a0
309; CHECK-NEXT:    xori a0, a0, 1
310; CHECK-NEXT:    ret
311  %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp
312  %2 = zext i1 %1 to i32
313  ret i32 %2
314}
315
316define i64 @fmvh_x_d(double %fa) {
317; RV32IDZFA-LABEL: fmvh_x_d:
318; RV32IDZFA:       # %bb.0:
319; RV32IDZFA-NEXT:    fmv.x.w a0, fa0
320; RV32IDZFA-NEXT:    fmvh.x.d a1, fa0
321; RV32IDZFA-NEXT:    ret
322;
323; RV64DZFA-LABEL: fmvh_x_d:
324; RV64DZFA:       # %bb.0:
325; RV64DZFA-NEXT:    fmv.x.d a0, fa0
326; RV64DZFA-NEXT:    ret
327  %i = bitcast double %fa to i64
328  ret i64 %i
329}
330
331define double @fmvp_d_x(i64 %a) {
332; RV32IDZFA-LABEL: fmvp_d_x:
333; RV32IDZFA:       # %bb.0:
334; RV32IDZFA-NEXT:    fmvp.d.x fa0, a0, a1
335; RV32IDZFA-NEXT:    ret
336;
337; RV64DZFA-LABEL: fmvp_d_x:
338; RV64DZFA:       # %bb.0:
339; RV64DZFA-NEXT:    fmv.d.x fa0, a0
340; RV64DZFA-NEXT:    ret
341  %or = bitcast i64 %a to double
342  ret double %or
343}
344
345define double @fadd_neg_0p5(double %x) {
346; CHECK-LABEL: fadd_neg_0p5:
347; CHECK:       # %bb.0:
348; CHECK-NEXT:    fli.d fa5, 0.5
349; CHECK-NEXT:    fsub.d fa0, fa0, fa5
350; CHECK-NEXT:    ret
351  %a = fadd double %x, -0.5
352  ret double %a
353}
354
355define double @fma_neg_addend(double %x, double %y) nounwind {
356; CHECK-LABEL: fma_neg_addend:
357; CHECK:       # %bb.0:
358; CHECK-NEXT:    fli.d fa5, 0.5
359; CHECK-NEXT:    fmsub.d fa0, fa0, fa1, fa5
360; CHECK-NEXT:    ret
361  %a = call double @llvm.fma.f32(double %x, double %y, double -0.5)
362  ret double %a
363}
364
365define double @fma_neg_multiplicand(double %x, double %y) nounwind {
366; CHECK-LABEL: fma_neg_multiplicand:
367; CHECK:       # %bb.0:
368; CHECK-NEXT:    fli.d fa5, 0.125
369; CHECK-NEXT:    fnmsub.d fa0, fa5, fa0, fa1
370; CHECK-NEXT:    ret
371  %a = call double @llvm.fma.f32(double %x, double -0.125, double %y)
372  ret double %a
373}
374
375define double @fma_neg_addend_multiplicand(double %x) nounwind {
376; CHECK-LABEL: fma_neg_addend_multiplicand:
377; CHECK:       # %bb.0:
378; CHECK-NEXT:    fli.d fa5, 0.25
379; CHECK-NEXT:    fli.d fa4, 0.5
380; CHECK-NEXT:    fnmadd.d fa0, fa4, fa0, fa5
381; CHECK-NEXT:    ret
382  %a = call double @llvm.fma.f32(double %x, double -0.5, double -0.25)
383  ret double %a
384}
385
386define double @select_loadfpimm(double %x) nounwind {
387; RV32IDZFA-LABEL: select_loadfpimm:
388; RV32IDZFA:       # %bb.0: # %entry
389; RV32IDZFA-NEXT:    fcvt.d.w fa5, zero
390; RV32IDZFA-NEXT:    fle.d a0, fa5, fa0
391; RV32IDZFA-NEXT:    fli.d fa0, 0.5
392; RV32IDZFA-NEXT:    bnez a0, .LBB36_2
393; RV32IDZFA-NEXT:  # %bb.1:
394; RV32IDZFA-NEXT:    fneg.d fa0, fa0
395; RV32IDZFA-NEXT:  .LBB36_2: # %entry
396; RV32IDZFA-NEXT:    ret
397;
398; RV64DZFA-LABEL: select_loadfpimm:
399; RV64DZFA:       # %bb.0: # %entry
400; RV64DZFA-NEXT:    fmv.d.x fa5, zero
401; RV64DZFA-NEXT:    fle.d a0, fa5, fa0
402; RV64DZFA-NEXT:    fli.d fa0, 0.5
403; RV64DZFA-NEXT:    bnez a0, .LBB36_2
404; RV64DZFA-NEXT:  # %bb.1:
405; RV64DZFA-NEXT:    fneg.d fa0, fa0
406; RV64DZFA-NEXT:  .LBB36_2: # %entry
407; RV64DZFA-NEXT:    ret
408entry:
409  %cmp = fcmp ult double %x, 0.000000e+00
410  %sel = select i1 %cmp, double -5.000000e-01, double 5.000000e-01
411  ret double %sel
412}
413