1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefix=RV32I
4 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefix=RV64I
6 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \
7 ; RUN: -target-abi ilp32f < %s | FileCheck %s -check-prefix=RV32IF
8 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \
9 ; RUN: -target-abi ilp32d < %s | FileCheck %s -check-prefix=RV32IFD
10 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \
11 ; RUN: -target-abi lp64d < %s | FileCheck %s -check-prefix=RV64IFD
12 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \
13 ; RUN: -mattr=+zfh -target-abi ilp32f < %s \
14 ; RUN: | FileCheck %s -check-prefix=RV32IFZFH
15 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \
16 ; RUN: -mattr=+zfh -target-abi ilp32d < %s \
17 ; RUN: | FileCheck %s -check-prefix=RV32IFDZFH
18 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \
19 ; RUN: -mattr=+zfh -target-abi lp64d < %s \
20 ; RUN: | FileCheck %s -check-prefix=RV64IFDZFH
21 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \
22 ; RUN: -mattr=+zfhmin -target-abi ilp32f < %s \
23 ; RUN: | FileCheck %s -check-prefix=RV32IFZFHMIN
24 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \
25 ; RUN: -mattr=+zfhmin -target-abi ilp32d < %s \
26 ; RUN: | FileCheck %s -check-prefix=RV32IFDZFHMIN
27 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \
28 ; RUN: -mattr=+zfhmin -target-abi lp64d < %s \
29 ; RUN: | FileCheck %s -check-prefix=RV64IFDZFHMIN
30 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+zdinx \
31 ; RUN: -target-abi ilp32 < %s \
32 ; RUN: | FileCheck %s -check-prefix=RV32IZDINX
33 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+zdinx \
34 ; RUN: -target-abi lp64 < %s \
35 ; RUN: | FileCheck %s -check-prefix=RV64IZDINX
37 ; Test fcopysign scenarios where the sign argument is casted to the type of the
38 ; magnitude argument. Those casts can be folded away by the DAGCombiner.
40 declare double @llvm.copysign.f64(double, double)
41 declare float @llvm.copysign.f32(float, float)
42 declare half @llvm.copysign.f16(half, half)
44 define double @fold_promote_d_s(double %a, float %b) nounwind {
45 ; RV32I-LABEL: fold_promote_d_s:
47 ; RV32I-NEXT: lui a3, 524288
48 ; RV32I-NEXT: slli a1, a1, 1
49 ; RV32I-NEXT: and a2, a2, a3
50 ; RV32I-NEXT: srli a1, a1, 1
51 ; RV32I-NEXT: or a1, a1, a2
54 ; RV64I-LABEL: fold_promote_d_s:
56 ; RV64I-NEXT: lui a2, 524288
57 ; RV64I-NEXT: slli a0, a0, 1
58 ; RV64I-NEXT: and a1, a1, a2
59 ; RV64I-NEXT: slli a1, a1, 32
60 ; RV64I-NEXT: srli a0, a0, 1
61 ; RV64I-NEXT: or a0, a0, a1
64 ; RV32IF-LABEL: fold_promote_d_s:
66 ; RV32IF-NEXT: fmv.x.w a2, fa0
67 ; RV32IF-NEXT: lui a3, 524288
68 ; RV32IF-NEXT: slli a1, a1, 1
69 ; RV32IF-NEXT: and a2, a2, a3
70 ; RV32IF-NEXT: srli a1, a1, 1
71 ; RV32IF-NEXT: or a1, a1, a2
74 ; RV32IFD-LABEL: fold_promote_d_s:
76 ; RV32IFD-NEXT: fcvt.d.s fa5, fa1
77 ; RV32IFD-NEXT: fsgnj.d fa0, fa0, fa5
80 ; RV64IFD-LABEL: fold_promote_d_s:
82 ; RV64IFD-NEXT: fcvt.d.s fa5, fa1
83 ; RV64IFD-NEXT: fsgnj.d fa0, fa0, fa5
86 ; RV32IFZFH-LABEL: fold_promote_d_s:
88 ; RV32IFZFH-NEXT: fmv.x.w a2, fa0
89 ; RV32IFZFH-NEXT: lui a3, 524288
90 ; RV32IFZFH-NEXT: slli a1, a1, 1
91 ; RV32IFZFH-NEXT: and a2, a2, a3
92 ; RV32IFZFH-NEXT: srli a1, a1, 1
93 ; RV32IFZFH-NEXT: or a1, a1, a2
96 ; RV32IFDZFH-LABEL: fold_promote_d_s:
97 ; RV32IFDZFH: # %bb.0:
98 ; RV32IFDZFH-NEXT: fcvt.d.s fa5, fa1
99 ; RV32IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5
100 ; RV32IFDZFH-NEXT: ret
102 ; RV64IFDZFH-LABEL: fold_promote_d_s:
103 ; RV64IFDZFH: # %bb.0:
104 ; RV64IFDZFH-NEXT: fcvt.d.s fa5, fa1
105 ; RV64IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5
106 ; RV64IFDZFH-NEXT: ret
108 ; RV32IFZFHMIN-LABEL: fold_promote_d_s:
109 ; RV32IFZFHMIN: # %bb.0:
110 ; RV32IFZFHMIN-NEXT: fmv.x.w a2, fa0
111 ; RV32IFZFHMIN-NEXT: lui a3, 524288
112 ; RV32IFZFHMIN-NEXT: slli a1, a1, 1
113 ; RV32IFZFHMIN-NEXT: and a2, a2, a3
114 ; RV32IFZFHMIN-NEXT: srli a1, a1, 1
115 ; RV32IFZFHMIN-NEXT: or a1, a1, a2
116 ; RV32IFZFHMIN-NEXT: ret
118 ; RV32IFDZFHMIN-LABEL: fold_promote_d_s:
119 ; RV32IFDZFHMIN: # %bb.0:
120 ; RV32IFDZFHMIN-NEXT: fcvt.d.s fa5, fa1
121 ; RV32IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5
122 ; RV32IFDZFHMIN-NEXT: ret
124 ; RV64IFDZFHMIN-LABEL: fold_promote_d_s:
125 ; RV64IFDZFHMIN: # %bb.0:
126 ; RV64IFDZFHMIN-NEXT: fcvt.d.s fa5, fa1
127 ; RV64IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5
128 ; RV64IFDZFHMIN-NEXT: ret
130 ; RV32IZDINX-LABEL: fold_promote_d_s:
131 ; RV32IZDINX: # %bb.0:
132 ; RV32IZDINX-NEXT: fcvt.d.s a2, a2
133 ; RV32IZDINX-NEXT: fsgnj.d a0, a0, a2
134 ; RV32IZDINX-NEXT: ret
136 ; RV64IZDINX-LABEL: fold_promote_d_s:
137 ; RV64IZDINX: # %bb.0:
138 ; RV64IZDINX-NEXT: fcvt.d.s a1, a1
139 ; RV64IZDINX-NEXT: fsgnj.d a0, a0, a1
140 ; RV64IZDINX-NEXT: ret
141 %c = fpext float %b to double
142 %t = call double @llvm.copysign.f64(double %a, double %c)
146 define double @fold_promote_d_h(double %a, half %b) nounwind {
147 ; RV32I-LABEL: fold_promote_d_h:
149 ; RV32I-NEXT: lui a3, 8
150 ; RV32I-NEXT: slli a1, a1, 1
151 ; RV32I-NEXT: and a2, a2, a3
152 ; RV32I-NEXT: slli a2, a2, 16
153 ; RV32I-NEXT: srli a1, a1, 1
154 ; RV32I-NEXT: or a1, a1, a2
157 ; RV64I-LABEL: fold_promote_d_h:
159 ; RV64I-NEXT: lui a2, 8
160 ; RV64I-NEXT: slli a0, a0, 1
161 ; RV64I-NEXT: and a1, a1, a2
162 ; RV64I-NEXT: slli a1, a1, 48
163 ; RV64I-NEXT: srli a0, a0, 1
164 ; RV64I-NEXT: or a0, a0, a1
167 ; RV32IF-LABEL: fold_promote_d_h:
169 ; RV32IF-NEXT: fmv.x.w a2, fa0
170 ; RV32IF-NEXT: lui a3, 8
171 ; RV32IF-NEXT: slli a1, a1, 1
172 ; RV32IF-NEXT: and a2, a2, a3
173 ; RV32IF-NEXT: slli a2, a2, 16
174 ; RV32IF-NEXT: srli a1, a1, 1
175 ; RV32IF-NEXT: or a1, a1, a2
178 ; RV32IFD-LABEL: fold_promote_d_h:
180 ; RV32IFD-NEXT: addi sp, sp, -16
181 ; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
182 ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill
183 ; RV32IFD-NEXT: fmv.d fs0, fa0
184 ; RV32IFD-NEXT: fmv.s fa0, fa1
185 ; RV32IFD-NEXT: call __extendhfsf2
186 ; RV32IFD-NEXT: fcvt.d.s fa5, fa0
187 ; RV32IFD-NEXT: fsgnj.d fa0, fs0, fa5
188 ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
189 ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload
190 ; RV32IFD-NEXT: addi sp, sp, 16
193 ; RV64IFD-LABEL: fold_promote_d_h:
195 ; RV64IFD-NEXT: addi sp, sp, -16
196 ; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
197 ; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill
198 ; RV64IFD-NEXT: fmv.d fs0, fa0
199 ; RV64IFD-NEXT: fmv.s fa0, fa1
200 ; RV64IFD-NEXT: call __extendhfsf2
201 ; RV64IFD-NEXT: fcvt.d.s fa5, fa0
202 ; RV64IFD-NEXT: fsgnj.d fa0, fs0, fa5
203 ; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
204 ; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload
205 ; RV64IFD-NEXT: addi sp, sp, 16
208 ; RV32IFZFH-LABEL: fold_promote_d_h:
209 ; RV32IFZFH: # %bb.0:
210 ; RV32IFZFH-NEXT: fmv.x.h a2, fa0
211 ; RV32IFZFH-NEXT: lui a3, 8
212 ; RV32IFZFH-NEXT: slli a1, a1, 1
213 ; RV32IFZFH-NEXT: and a2, a2, a3
214 ; RV32IFZFH-NEXT: slli a2, a2, 16
215 ; RV32IFZFH-NEXT: srli a1, a1, 1
216 ; RV32IFZFH-NEXT: or a1, a1, a2
217 ; RV32IFZFH-NEXT: ret
219 ; RV32IFDZFH-LABEL: fold_promote_d_h:
220 ; RV32IFDZFH: # %bb.0:
221 ; RV32IFDZFH-NEXT: fcvt.d.h fa5, fa1
222 ; RV32IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5
223 ; RV32IFDZFH-NEXT: ret
225 ; RV64IFDZFH-LABEL: fold_promote_d_h:
226 ; RV64IFDZFH: # %bb.0:
227 ; RV64IFDZFH-NEXT: fcvt.d.h fa5, fa1
228 ; RV64IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5
229 ; RV64IFDZFH-NEXT: ret
231 ; RV32IFZFHMIN-LABEL: fold_promote_d_h:
232 ; RV32IFZFHMIN: # %bb.0:
233 ; RV32IFZFHMIN-NEXT: fmv.x.h a2, fa0
234 ; RV32IFZFHMIN-NEXT: lui a3, 8
235 ; RV32IFZFHMIN-NEXT: slli a1, a1, 1
236 ; RV32IFZFHMIN-NEXT: and a2, a2, a3
237 ; RV32IFZFHMIN-NEXT: slli a2, a2, 16
238 ; RV32IFZFHMIN-NEXT: srli a1, a1, 1
239 ; RV32IFZFHMIN-NEXT: or a1, a1, a2
240 ; RV32IFZFHMIN-NEXT: ret
242 ; RV32IFDZFHMIN-LABEL: fold_promote_d_h:
243 ; RV32IFDZFHMIN: # %bb.0:
244 ; RV32IFDZFHMIN-NEXT: fcvt.d.h fa5, fa1
245 ; RV32IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5
246 ; RV32IFDZFHMIN-NEXT: ret
248 ; RV64IFDZFHMIN-LABEL: fold_promote_d_h:
249 ; RV64IFDZFHMIN: # %bb.0:
250 ; RV64IFDZFHMIN-NEXT: fcvt.d.h fa5, fa1
251 ; RV64IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5
252 ; RV64IFDZFHMIN-NEXT: ret
254 ; RV32IZDINX-LABEL: fold_promote_d_h:
255 ; RV32IZDINX: # %bb.0:
256 ; RV32IZDINX-NEXT: addi sp, sp, -16
257 ; RV32IZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
258 ; RV32IZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
259 ; RV32IZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
260 ; RV32IZDINX-NEXT: mv s1, a1
261 ; RV32IZDINX-NEXT: mv s0, a0
262 ; RV32IZDINX-NEXT: mv a0, a2
263 ; RV32IZDINX-NEXT: call __extendhfsf2
264 ; RV32IZDINX-NEXT: fcvt.d.s a0, a0
265 ; RV32IZDINX-NEXT: fsgnj.d a0, s0, a0
266 ; RV32IZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
267 ; RV32IZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
268 ; RV32IZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
269 ; RV32IZDINX-NEXT: addi sp, sp, 16
270 ; RV32IZDINX-NEXT: ret
272 ; RV64IZDINX-LABEL: fold_promote_d_h:
273 ; RV64IZDINX: # %bb.0:
274 ; RV64IZDINX-NEXT: addi sp, sp, -16
275 ; RV64IZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
276 ; RV64IZDINX-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
277 ; RV64IZDINX-NEXT: mv s0, a0
278 ; RV64IZDINX-NEXT: mv a0, a1
279 ; RV64IZDINX-NEXT: call __extendhfsf2
280 ; RV64IZDINX-NEXT: fcvt.d.s a0, a0
281 ; RV64IZDINX-NEXT: fsgnj.d a0, s0, a0
282 ; RV64IZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
283 ; RV64IZDINX-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
284 ; RV64IZDINX-NEXT: addi sp, sp, 16
285 ; RV64IZDINX-NEXT: ret
286 %c = fpext half %b to double
287 %t = call double @llvm.copysign.f64(double %a, double %c)
291 define float @fold_promote_f_h(float %a, half %b) nounwind {
292 ; RV32I-LABEL: fold_promote_f_h:
294 ; RV32I-NEXT: lui a2, 8
295 ; RV32I-NEXT: slli a0, a0, 1
296 ; RV32I-NEXT: and a1, a1, a2
297 ; RV32I-NEXT: slli a1, a1, 16
298 ; RV32I-NEXT: srli a0, a0, 1
299 ; RV32I-NEXT: or a0, a0, a1
302 ; RV64I-LABEL: fold_promote_f_h:
304 ; RV64I-NEXT: lui a2, 8
305 ; RV64I-NEXT: slli a0, a0, 33
306 ; RV64I-NEXT: and a1, a1, a2
307 ; RV64I-NEXT: slliw a1, a1, 16
308 ; RV64I-NEXT: srli a0, a0, 33
309 ; RV64I-NEXT: or a0, a0, a1
312 ; RV32IF-LABEL: fold_promote_f_h:
314 ; RV32IF-NEXT: addi sp, sp, -16
315 ; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
316 ; RV32IF-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill
317 ; RV32IF-NEXT: fmv.s fs0, fa0
318 ; RV32IF-NEXT: fmv.s fa0, fa1
319 ; RV32IF-NEXT: call __extendhfsf2
320 ; RV32IF-NEXT: fsgnj.s fa0, fs0, fa0
321 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
322 ; RV32IF-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload
323 ; RV32IF-NEXT: addi sp, sp, 16
326 ; RV32IFD-LABEL: fold_promote_f_h:
328 ; RV32IFD-NEXT: addi sp, sp, -16
329 ; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
330 ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill
331 ; RV32IFD-NEXT: fmv.s fs0, fa0
332 ; RV32IFD-NEXT: fmv.s fa0, fa1
333 ; RV32IFD-NEXT: call __extendhfsf2
334 ; RV32IFD-NEXT: fsgnj.s fa0, fs0, fa0
335 ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
336 ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload
337 ; RV32IFD-NEXT: addi sp, sp, 16
340 ; RV64IFD-LABEL: fold_promote_f_h:
342 ; RV64IFD-NEXT: addi sp, sp, -16
343 ; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
344 ; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill
345 ; RV64IFD-NEXT: fmv.s fs0, fa0
346 ; RV64IFD-NEXT: fmv.s fa0, fa1
347 ; RV64IFD-NEXT: call __extendhfsf2
348 ; RV64IFD-NEXT: fsgnj.s fa0, fs0, fa0
349 ; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
350 ; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload
351 ; RV64IFD-NEXT: addi sp, sp, 16
354 ; RV32IFZFH-LABEL: fold_promote_f_h:
355 ; RV32IFZFH: # %bb.0:
356 ; RV32IFZFH-NEXT: fcvt.s.h fa5, fa1
357 ; RV32IFZFH-NEXT: fsgnj.s fa0, fa0, fa5
358 ; RV32IFZFH-NEXT: ret
360 ; RV32IFDZFH-LABEL: fold_promote_f_h:
361 ; RV32IFDZFH: # %bb.0:
362 ; RV32IFDZFH-NEXT: fcvt.s.h fa5, fa1
363 ; RV32IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5
364 ; RV32IFDZFH-NEXT: ret
366 ; RV64IFDZFH-LABEL: fold_promote_f_h:
367 ; RV64IFDZFH: # %bb.0:
368 ; RV64IFDZFH-NEXT: fcvt.s.h fa5, fa1
369 ; RV64IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5
370 ; RV64IFDZFH-NEXT: ret
372 ; RV32IFZFHMIN-LABEL: fold_promote_f_h:
373 ; RV32IFZFHMIN: # %bb.0:
374 ; RV32IFZFHMIN-NEXT: fcvt.s.h fa5, fa1
375 ; RV32IFZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
376 ; RV32IFZFHMIN-NEXT: ret
378 ; RV32IFDZFHMIN-LABEL: fold_promote_f_h:
379 ; RV32IFDZFHMIN: # %bb.0:
380 ; RV32IFDZFHMIN-NEXT: fcvt.s.h fa5, fa1
381 ; RV32IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
382 ; RV32IFDZFHMIN-NEXT: ret
384 ; RV64IFDZFHMIN-LABEL: fold_promote_f_h:
385 ; RV64IFDZFHMIN: # %bb.0:
386 ; RV64IFDZFHMIN-NEXT: fcvt.s.h fa5, fa1
387 ; RV64IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
388 ; RV64IFDZFHMIN-NEXT: ret
390 ; RV32IZDINX-LABEL: fold_promote_f_h:
391 ; RV32IZDINX: # %bb.0:
392 ; RV32IZDINX-NEXT: addi sp, sp, -16
393 ; RV32IZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
394 ; RV32IZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
395 ; RV32IZDINX-NEXT: mv s0, a0
396 ; RV32IZDINX-NEXT: mv a0, a1
397 ; RV32IZDINX-NEXT: call __extendhfsf2
398 ; RV32IZDINX-NEXT: fsgnj.s a0, s0, a0
399 ; RV32IZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
400 ; RV32IZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
401 ; RV32IZDINX-NEXT: addi sp, sp, 16
402 ; RV32IZDINX-NEXT: ret
404 ; RV64IZDINX-LABEL: fold_promote_f_h:
405 ; RV64IZDINX: # %bb.0:
406 ; RV64IZDINX-NEXT: addi sp, sp, -16
407 ; RV64IZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
408 ; RV64IZDINX-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
409 ; RV64IZDINX-NEXT: mv s0, a0
410 ; RV64IZDINX-NEXT: mv a0, a1
411 ; RV64IZDINX-NEXT: call __extendhfsf2
412 ; RV64IZDINX-NEXT: fsgnj.s a0, s0, a0
413 ; RV64IZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
414 ; RV64IZDINX-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
415 ; RV64IZDINX-NEXT: addi sp, sp, 16
416 ; RV64IZDINX-NEXT: ret
417 %c = fpext half %b to float
418 %t = call float @llvm.copysign.f32(float %a, float %c)
422 define float @fold_demote_s_d(float %a, double %b) nounwind {
423 ; RV32I-LABEL: fold_demote_s_d:
425 ; RV32I-NEXT: lui a1, 524288
426 ; RV32I-NEXT: slli a0, a0, 1
427 ; RV32I-NEXT: and a1, a2, a1
428 ; RV32I-NEXT: srli a0, a0, 1
429 ; RV32I-NEXT: or a0, a0, a1
432 ; RV64I-LABEL: fold_demote_s_d:
434 ; RV64I-NEXT: slli a0, a0, 33
435 ; RV64I-NEXT: srli a1, a1, 63
436 ; RV64I-NEXT: srli a0, a0, 33
437 ; RV64I-NEXT: slli a1, a1, 63
438 ; RV64I-NEXT: srli a1, a1, 32
439 ; RV64I-NEXT: or a0, a0, a1
442 ; RV32IF-LABEL: fold_demote_s_d:
444 ; RV32IF-NEXT: fmv.w.x fa5, a1
445 ; RV32IF-NEXT: fsgnj.s fa0, fa0, fa5
448 ; RV32IFD-LABEL: fold_demote_s_d:
450 ; RV32IFD-NEXT: fcvt.s.d fa5, fa1
451 ; RV32IFD-NEXT: fsgnj.s fa0, fa0, fa5
454 ; RV64IFD-LABEL: fold_demote_s_d:
456 ; RV64IFD-NEXT: fcvt.s.d fa5, fa1
457 ; RV64IFD-NEXT: fsgnj.s fa0, fa0, fa5
460 ; RV32IFZFH-LABEL: fold_demote_s_d:
461 ; RV32IFZFH: # %bb.0:
462 ; RV32IFZFH-NEXT: fmv.w.x fa5, a1
463 ; RV32IFZFH-NEXT: fsgnj.s fa0, fa0, fa5
464 ; RV32IFZFH-NEXT: ret
466 ; RV32IFDZFH-LABEL: fold_demote_s_d:
467 ; RV32IFDZFH: # %bb.0:
468 ; RV32IFDZFH-NEXT: fcvt.s.d fa5, fa1
469 ; RV32IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5
470 ; RV32IFDZFH-NEXT: ret
472 ; RV64IFDZFH-LABEL: fold_demote_s_d:
473 ; RV64IFDZFH: # %bb.0:
474 ; RV64IFDZFH-NEXT: fcvt.s.d fa5, fa1
475 ; RV64IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5
476 ; RV64IFDZFH-NEXT: ret
478 ; RV32IFZFHMIN-LABEL: fold_demote_s_d:
479 ; RV32IFZFHMIN: # %bb.0:
480 ; RV32IFZFHMIN-NEXT: fmv.w.x fa5, a1
481 ; RV32IFZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
482 ; RV32IFZFHMIN-NEXT: ret
484 ; RV32IFDZFHMIN-LABEL: fold_demote_s_d:
485 ; RV32IFDZFHMIN: # %bb.0:
486 ; RV32IFDZFHMIN-NEXT: fcvt.s.d fa5, fa1
487 ; RV32IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
488 ; RV32IFDZFHMIN-NEXT: ret
490 ; RV64IFDZFHMIN-LABEL: fold_demote_s_d:
491 ; RV64IFDZFHMIN: # %bb.0:
492 ; RV64IFDZFHMIN-NEXT: fcvt.s.d fa5, fa1
493 ; RV64IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5
494 ; RV64IFDZFHMIN-NEXT: ret
496 ; RV32IZDINX-LABEL: fold_demote_s_d:
497 ; RV32IZDINX: # %bb.0:
498 ; RV32IZDINX-NEXT: mv a3, a2
499 ; RV32IZDINX-NEXT: mv a2, a1
500 ; RV32IZDINX-NEXT: fcvt.s.d a1, a2
501 ; RV32IZDINX-NEXT: fsgnj.s a0, a0, a1
502 ; RV32IZDINX-NEXT: ret
504 ; RV64IZDINX-LABEL: fold_demote_s_d:
505 ; RV64IZDINX: # %bb.0:
506 ; RV64IZDINX-NEXT: fcvt.s.d a1, a1
507 ; RV64IZDINX-NEXT: fsgnj.s a0, a0, a1
508 ; RV64IZDINX-NEXT: ret
509 %c = fptrunc double %b to float
510 %t = call float @llvm.copysign.f32(float %a, float %c)
514 define half @fold_demote_h_s(half %a, float %b) nounwind {
515 ; RV32I-LABEL: fold_demote_h_s:
517 ; RV32I-NEXT: lui a2, 524288
518 ; RV32I-NEXT: slli a0, a0, 17
519 ; RV32I-NEXT: and a1, a1, a2
520 ; RV32I-NEXT: srli a1, a1, 16
521 ; RV32I-NEXT: srli a0, a0, 17
522 ; RV32I-NEXT: or a0, a0, a1
525 ; RV64I-LABEL: fold_demote_h_s:
527 ; RV64I-NEXT: srliw a1, a1, 31
528 ; RV64I-NEXT: slli a0, a0, 49
529 ; RV64I-NEXT: slli a1, a1, 15
530 ; RV64I-NEXT: srli a0, a0, 49
531 ; RV64I-NEXT: or a0, a0, a1
534 ; RV32IF-LABEL: fold_demote_h_s:
536 ; RV32IF-NEXT: fmv.x.w a0, fa0
537 ; RV32IF-NEXT: fmv.x.w a1, fa1
538 ; RV32IF-NEXT: lui a2, 524288
539 ; RV32IF-NEXT: and a1, a1, a2
540 ; RV32IF-NEXT: slli a0, a0, 17
541 ; RV32IF-NEXT: srli a1, a1, 16
542 ; RV32IF-NEXT: srli a0, a0, 17
543 ; RV32IF-NEXT: or a0, a0, a1
544 ; RV32IF-NEXT: lui a1, 1048560
545 ; RV32IF-NEXT: or a0, a0, a1
546 ; RV32IF-NEXT: fmv.w.x fa0, a0
549 ; RV32IFD-LABEL: fold_demote_h_s:
551 ; RV32IFD-NEXT: fmv.x.w a0, fa0
552 ; RV32IFD-NEXT: fmv.x.w a1, fa1
553 ; RV32IFD-NEXT: lui a2, 524288
554 ; RV32IFD-NEXT: and a1, a1, a2
555 ; RV32IFD-NEXT: slli a0, a0, 17
556 ; RV32IFD-NEXT: srli a1, a1, 16
557 ; RV32IFD-NEXT: srli a0, a0, 17
558 ; RV32IFD-NEXT: or a0, a0, a1
559 ; RV32IFD-NEXT: lui a1, 1048560
560 ; RV32IFD-NEXT: or a0, a0, a1
561 ; RV32IFD-NEXT: fmv.w.x fa0, a0
564 ; RV64IFD-LABEL: fold_demote_h_s:
566 ; RV64IFD-NEXT: fmv.x.w a0, fa0
567 ; RV64IFD-NEXT: fmv.x.w a1, fa1
568 ; RV64IFD-NEXT: lui a2, 524288
569 ; RV64IFD-NEXT: and a1, a1, a2
570 ; RV64IFD-NEXT: slli a0, a0, 49
571 ; RV64IFD-NEXT: srli a1, a1, 16
572 ; RV64IFD-NEXT: srli a0, a0, 49
573 ; RV64IFD-NEXT: or a0, a0, a1
574 ; RV64IFD-NEXT: lui a1, 1048560
575 ; RV64IFD-NEXT: or a0, a0, a1
576 ; RV64IFD-NEXT: fmv.w.x fa0, a0
579 ; RV32IFZFH-LABEL: fold_demote_h_s:
580 ; RV32IFZFH: # %bb.0:
581 ; RV32IFZFH-NEXT: fcvt.h.s fa5, fa1
582 ; RV32IFZFH-NEXT: fsgnj.h fa0, fa0, fa5
583 ; RV32IFZFH-NEXT: ret
585 ; RV32IFDZFH-LABEL: fold_demote_h_s:
586 ; RV32IFDZFH: # %bb.0:
587 ; RV32IFDZFH-NEXT: fcvt.h.s fa5, fa1
588 ; RV32IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5
589 ; RV32IFDZFH-NEXT: ret
591 ; RV64IFDZFH-LABEL: fold_demote_h_s:
592 ; RV64IFDZFH: # %bb.0:
593 ; RV64IFDZFH-NEXT: fcvt.h.s fa5, fa1
594 ; RV64IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5
595 ; RV64IFDZFH-NEXT: ret
597 ; RV32IFZFHMIN-LABEL: fold_demote_h_s:
598 ; RV32IFZFHMIN: # %bb.0:
599 ; RV32IFZFHMIN-NEXT: fmv.x.w a0, fa1
600 ; RV32IFZFHMIN-NEXT: fmv.x.h a1, fa0
601 ; RV32IFZFHMIN-NEXT: srli a0, a0, 31
602 ; RV32IFZFHMIN-NEXT: slli a1, a1, 17
603 ; RV32IFZFHMIN-NEXT: slli a0, a0, 15
604 ; RV32IFZFHMIN-NEXT: srli a1, a1, 17
605 ; RV32IFZFHMIN-NEXT: or a0, a1, a0
606 ; RV32IFZFHMIN-NEXT: fmv.h.x fa0, a0
607 ; RV32IFZFHMIN-NEXT: ret
609 ; RV32IFDZFHMIN-LABEL: fold_demote_h_s:
610 ; RV32IFDZFHMIN: # %bb.0:
611 ; RV32IFDZFHMIN-NEXT: fmv.x.w a0, fa1
612 ; RV32IFDZFHMIN-NEXT: fmv.x.h a1, fa0
613 ; RV32IFDZFHMIN-NEXT: srli a0, a0, 31
614 ; RV32IFDZFHMIN-NEXT: slli a1, a1, 17
615 ; RV32IFDZFHMIN-NEXT: slli a0, a0, 15
616 ; RV32IFDZFHMIN-NEXT: srli a1, a1, 17
617 ; RV32IFDZFHMIN-NEXT: or a0, a1, a0
618 ; RV32IFDZFHMIN-NEXT: fmv.h.x fa0, a0
619 ; RV32IFDZFHMIN-NEXT: ret
621 ; RV64IFDZFHMIN-LABEL: fold_demote_h_s:
622 ; RV64IFDZFHMIN: # %bb.0:
623 ; RV64IFDZFHMIN-NEXT: fmv.x.w a0, fa1
624 ; RV64IFDZFHMIN-NEXT: fmv.x.h a1, fa0
625 ; RV64IFDZFHMIN-NEXT: srli a0, a0, 31
626 ; RV64IFDZFHMIN-NEXT: slli a1, a1, 49
627 ; RV64IFDZFHMIN-NEXT: slli a0, a0, 15
628 ; RV64IFDZFHMIN-NEXT: srli a1, a1, 49
629 ; RV64IFDZFHMIN-NEXT: or a0, a1, a0
630 ; RV64IFDZFHMIN-NEXT: fmv.h.x fa0, a0
631 ; RV64IFDZFHMIN-NEXT: ret
633 ; RV32IZDINX-LABEL: fold_demote_h_s:
634 ; RV32IZDINX: # %bb.0:
635 ; RV32IZDINX-NEXT: # kill: def $x11_w killed $x11_w def $x11
636 ; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10
637 ; RV32IZDINX-NEXT: lui a2, 524288
638 ; RV32IZDINX-NEXT: slli a0, a0, 17
639 ; RV32IZDINX-NEXT: and a1, a1, a2
640 ; RV32IZDINX-NEXT: lui a2, 1048560
641 ; RV32IZDINX-NEXT: srli a0, a0, 17
642 ; RV32IZDINX-NEXT: srli a1, a1, 16
643 ; RV32IZDINX-NEXT: or a0, a0, a2
644 ; RV32IZDINX-NEXT: or a0, a0, a1
645 ; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10
646 ; RV32IZDINX-NEXT: ret
648 ; RV64IZDINX-LABEL: fold_demote_h_s:
649 ; RV64IZDINX: # %bb.0:
650 ; RV64IZDINX-NEXT: # kill: def $x11_w killed $x11_w def $x11
651 ; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10
652 ; RV64IZDINX-NEXT: lui a2, 524288
653 ; RV64IZDINX-NEXT: slli a0, a0, 49
654 ; RV64IZDINX-NEXT: and a1, a1, a2
655 ; RV64IZDINX-NEXT: lui a2, 1048560
656 ; RV64IZDINX-NEXT: srli a0, a0, 49
657 ; RV64IZDINX-NEXT: srli a1, a1, 16
658 ; RV64IZDINX-NEXT: or a0, a0, a2
659 ; RV64IZDINX-NEXT: or a0, a0, a1
660 ; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10
661 ; RV64IZDINX-NEXT: ret
662 %c = fptrunc float %b to half
663 %t = call half @llvm.copysign.f16(half %a, half %c)
667 define half @fold_demote_h_d(half %a, double %b) nounwind {
668 ; RV32I-LABEL: fold_demote_h_d:
670 ; RV32I-NEXT: lui a1, 524288
671 ; RV32I-NEXT: slli a0, a0, 17
672 ; RV32I-NEXT: and a1, a2, a1
673 ; RV32I-NEXT: srli a1, a1, 16
674 ; RV32I-NEXT: srli a0, a0, 17
675 ; RV32I-NEXT: or a0, a0, a1
678 ; RV64I-LABEL: fold_demote_h_d:
680 ; RV64I-NEXT: slli a0, a0, 49
681 ; RV64I-NEXT: srli a1, a1, 63
682 ; RV64I-NEXT: srli a0, a0, 49
683 ; RV64I-NEXT: slli a1, a1, 63
684 ; RV64I-NEXT: srli a1, a1, 48
685 ; RV64I-NEXT: or a0, a0, a1
688 ; RV32IF-LABEL: fold_demote_h_d:
690 ; RV32IF-NEXT: fmv.x.w a0, fa0
691 ; RV32IF-NEXT: lui a2, 524288
692 ; RV32IF-NEXT: and a1, a1, a2
693 ; RV32IF-NEXT: slli a0, a0, 17
694 ; RV32IF-NEXT: srli a1, a1, 16
695 ; RV32IF-NEXT: srli a0, a0, 17
696 ; RV32IF-NEXT: or a0, a0, a1
697 ; RV32IF-NEXT: lui a1, 1048560
698 ; RV32IF-NEXT: or a0, a0, a1
699 ; RV32IF-NEXT: fmv.w.x fa0, a0
702 ; RV32IFD-LABEL: fold_demote_h_d:
704 ; RV32IFD-NEXT: addi sp, sp, -16
705 ; RV32IFD-NEXT: fsd fa1, 8(sp)
706 ; RV32IFD-NEXT: lw a0, 12(sp)
707 ; RV32IFD-NEXT: fmv.x.w a1, fa0
708 ; RV32IFD-NEXT: lui a2, 524288
709 ; RV32IFD-NEXT: and a0, a0, a2
710 ; RV32IFD-NEXT: lui a2, 1048560
711 ; RV32IFD-NEXT: slli a1, a1, 17
712 ; RV32IFD-NEXT: srli a1, a1, 17
713 ; RV32IFD-NEXT: srli a0, a0, 16
714 ; RV32IFD-NEXT: or a1, a1, a2
715 ; RV32IFD-NEXT: or a0, a1, a0
716 ; RV32IFD-NEXT: fmv.w.x fa0, a0
717 ; RV32IFD-NEXT: addi sp, sp, 16
720 ; RV64IFD-LABEL: fold_demote_h_d:
722 ; RV64IFD-NEXT: fmv.x.d a0, fa1
723 ; RV64IFD-NEXT: fmv.x.w a1, fa0
724 ; RV64IFD-NEXT: lui a2, 1048560
725 ; RV64IFD-NEXT: slli a1, a1, 49
726 ; RV64IFD-NEXT: srli a0, a0, 63
727 ; RV64IFD-NEXT: srli a1, a1, 49
728 ; RV64IFD-NEXT: slli a0, a0, 63
729 ; RV64IFD-NEXT: srli a0, a0, 48
730 ; RV64IFD-NEXT: or a1, a1, a2
731 ; RV64IFD-NEXT: or a0, a1, a0
732 ; RV64IFD-NEXT: fmv.w.x fa0, a0
735 ; RV32IFZFH-LABEL: fold_demote_h_d:
736 ; RV32IFZFH: # %bb.0:
737 ; RV32IFZFH-NEXT: srli a1, a1, 16
738 ; RV32IFZFH-NEXT: fmv.h.x fa5, a1
739 ; RV32IFZFH-NEXT: fsgnj.h fa0, fa0, fa5
740 ; RV32IFZFH-NEXT: ret
742 ; RV32IFDZFH-LABEL: fold_demote_h_d:
743 ; RV32IFDZFH: # %bb.0:
744 ; RV32IFDZFH-NEXT: fcvt.h.d fa5, fa1
745 ; RV32IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5
746 ; RV32IFDZFH-NEXT: ret
748 ; RV64IFDZFH-LABEL: fold_demote_h_d:
749 ; RV64IFDZFH: # %bb.0:
750 ; RV64IFDZFH-NEXT: fcvt.h.d fa5, fa1
751 ; RV64IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5
752 ; RV64IFDZFH-NEXT: ret
754 ; RV32IFZFHMIN-LABEL: fold_demote_h_d:
755 ; RV32IFZFHMIN: # %bb.0:
756 ; RV32IFZFHMIN-NEXT: srli a1, a1, 31
757 ; RV32IFZFHMIN-NEXT: fmv.x.h a0, fa0
758 ; RV32IFZFHMIN-NEXT: slli a1, a1, 15
759 ; RV32IFZFHMIN-NEXT: slli a0, a0, 17
760 ; RV32IFZFHMIN-NEXT: srli a0, a0, 17
761 ; RV32IFZFHMIN-NEXT: or a0, a0, a1
762 ; RV32IFZFHMIN-NEXT: fmv.h.x fa0, a0
763 ; RV32IFZFHMIN-NEXT: ret
765 ; RV32IFDZFHMIN-LABEL: fold_demote_h_d:
766 ; RV32IFDZFHMIN: # %bb.0:
767 ; RV32IFDZFHMIN-NEXT: addi sp, sp, -16
768 ; RV32IFDZFHMIN-NEXT: fsd fa1, 8(sp)
769 ; RV32IFDZFHMIN-NEXT: lw a0, 12(sp)
770 ; RV32IFDZFHMIN-NEXT: fmv.x.h a1, fa0
771 ; RV32IFDZFHMIN-NEXT: slli a1, a1, 17
772 ; RV32IFDZFHMIN-NEXT: srli a0, a0, 31
773 ; RV32IFDZFHMIN-NEXT: slli a0, a0, 15
774 ; RV32IFDZFHMIN-NEXT: srli a1, a1, 17
775 ; RV32IFDZFHMIN-NEXT: or a0, a1, a0
776 ; RV32IFDZFHMIN-NEXT: fmv.h.x fa0, a0
777 ; RV32IFDZFHMIN-NEXT: addi sp, sp, 16
778 ; RV32IFDZFHMIN-NEXT: ret
780 ; RV64IFDZFHMIN-LABEL: fold_demote_h_d:
781 ; RV64IFDZFHMIN: # %bb.0:
782 ; RV64IFDZFHMIN-NEXT: fmv.x.d a0, fa1
783 ; RV64IFDZFHMIN-NEXT: fmv.x.h a1, fa0
784 ; RV64IFDZFHMIN-NEXT: srli a0, a0, 63
785 ; RV64IFDZFHMIN-NEXT: slli a1, a1, 49
786 ; RV64IFDZFHMIN-NEXT: slli a0, a0, 15
787 ; RV64IFDZFHMIN-NEXT: srli a1, a1, 49
788 ; RV64IFDZFHMIN-NEXT: or a0, a1, a0
789 ; RV64IFDZFHMIN-NEXT: fmv.h.x fa0, a0
790 ; RV64IFDZFHMIN-NEXT: ret
792 ; RV32IZDINX-LABEL: fold_demote_h_d:
793 ; RV32IZDINX: # %bb.0:
794 ; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10
795 ; RV32IZDINX-NEXT: lui a1, 524288
796 ; RV32IZDINX-NEXT: slli a0, a0, 17
797 ; RV32IZDINX-NEXT: and a1, a2, a1
798 ; RV32IZDINX-NEXT: lui a2, 1048560
799 ; RV32IZDINX-NEXT: srli a0, a0, 17
800 ; RV32IZDINX-NEXT: srli a1, a1, 16
801 ; RV32IZDINX-NEXT: or a0, a0, a2
802 ; RV32IZDINX-NEXT: or a0, a0, a1
803 ; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10
804 ; RV32IZDINX-NEXT: ret
806 ; RV64IZDINX-LABEL: fold_demote_h_d:
807 ; RV64IZDINX: # %bb.0:
808 ; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10
809 ; RV64IZDINX-NEXT: slli a0, a0, 49
810 ; RV64IZDINX-NEXT: srli a1, a1, 63
811 ; RV64IZDINX-NEXT: lui a2, 1048560
812 ; RV64IZDINX-NEXT: srli a0, a0, 49
813 ; RV64IZDINX-NEXT: slli a1, a1, 63
814 ; RV64IZDINX-NEXT: srli a1, a1, 48
815 ; RV64IZDINX-NEXT: or a0, a0, a2
816 ; RV64IZDINX-NEXT: or a0, a0, a1
817 ; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10
818 ; RV64IZDINX-NEXT: ret
819 %c = fptrunc double %b to half
820 %t = call half @llvm.copysign.f16(half %a, half %c)