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
22; Test fcopysign scenarios where the sign argument is casted to the type of the
23; magnitude argument. Those casts can be folded away by the DAGCombiner.
24
25declare double @llvm.copysign.f64(double, double)
26declare float @llvm.copysign.f32(float, float)
27declare half @llvm.copysign.f16(half, half)
28
29define double @fold_promote_d_s(double %a, float %b) nounwind {
30; RV32I-LABEL: fold_promote_d_s:
31; RV32I:       # %bb.0:
32; RV32I-NEXT:    lui a3, 524288
33; RV32I-NEXT:    and a2, a2, a3
34; RV32I-NEXT:    slli a1, a1, 1
35; RV32I-NEXT:    srli a1, a1, 1
36; RV32I-NEXT:    or a1, a1, a2
37; RV32I-NEXT:    ret
38;
39; RV64I-LABEL: fold_promote_d_s:
40; RV64I:       # %bb.0:
41; RV64I-NEXT:    lui a2, 524288
42; RV64I-NEXT:    and a1, a1, a2
43; RV64I-NEXT:    slli a1, a1, 32
44; RV64I-NEXT:    slli a0, a0, 1
45; RV64I-NEXT:    srli a0, a0, 1
46; RV64I-NEXT:    or a0, a0, a1
47; RV64I-NEXT:    ret
48;
49; RV32IF-LABEL: fold_promote_d_s:
50; RV32IF:       # %bb.0:
51; RV32IF-NEXT:    fmv.x.w a2, fa0
52; RV32IF-NEXT:    lui a3, 524288
53; RV32IF-NEXT:    and a2, a2, a3
54; RV32IF-NEXT:    slli a1, a1, 1
55; RV32IF-NEXT:    srli a1, a1, 1
56; RV32IF-NEXT:    or a1, a1, a2
57; RV32IF-NEXT:    ret
58;
59; RV32IFD-LABEL: fold_promote_d_s:
60; RV32IFD:       # %bb.0:
61; RV32IFD-NEXT:    fcvt.d.s ft0, fa1
62; RV32IFD-NEXT:    fsgnj.d fa0, fa0, ft0
63; RV32IFD-NEXT:    ret
64;
65; RV64IFD-LABEL: fold_promote_d_s:
66; RV64IFD:       # %bb.0:
67; RV64IFD-NEXT:    fcvt.d.s ft0, fa1
68; RV64IFD-NEXT:    fsgnj.d fa0, fa0, ft0
69; RV64IFD-NEXT:    ret
70;
71; RV32IFZFH-LABEL: fold_promote_d_s:
72; RV32IFZFH:       # %bb.0:
73; RV32IFZFH-NEXT:    fmv.x.w a2, fa0
74; RV32IFZFH-NEXT:    lui a3, 524288
75; RV32IFZFH-NEXT:    and a2, a2, a3
76; RV32IFZFH-NEXT:    slli a1, a1, 1
77; RV32IFZFH-NEXT:    srli a1, a1, 1
78; RV32IFZFH-NEXT:    or a1, a1, a2
79; RV32IFZFH-NEXT:    ret
80;
81; RV32IFDZFH-LABEL: fold_promote_d_s:
82; RV32IFDZFH:       # %bb.0:
83; RV32IFDZFH-NEXT:    fcvt.d.s ft0, fa1
84; RV32IFDZFH-NEXT:    fsgnj.d fa0, fa0, ft0
85; RV32IFDZFH-NEXT:    ret
86;
87; RV64IFDZFH-LABEL: fold_promote_d_s:
88; RV64IFDZFH:       # %bb.0:
89; RV64IFDZFH-NEXT:    fcvt.d.s ft0, fa1
90; RV64IFDZFH-NEXT:    fsgnj.d fa0, fa0, ft0
91; RV64IFDZFH-NEXT:    ret
92  %c = fpext float %b to double
93  %t = call double @llvm.copysign.f64(double %a, double %c)
94  ret double %t
95}
96
97define double @fold_promote_d_h(double %a, half %b) nounwind {
98; RV32I-LABEL: fold_promote_d_h:
99; RV32I:       # %bb.0:
100; RV32I-NEXT:    lui a3, 8
101; RV32I-NEXT:    and a2, a2, a3
102; RV32I-NEXT:    slli a2, a2, 16
103; RV32I-NEXT:    slli a1, a1, 1
104; RV32I-NEXT:    srli a1, a1, 1
105; RV32I-NEXT:    or a1, a1, a2
106; RV32I-NEXT:    ret
107;
108; RV64I-LABEL: fold_promote_d_h:
109; RV64I:       # %bb.0:
110; RV64I-NEXT:    lui a2, 8
111; RV64I-NEXT:    and a1, a1, a2
112; RV64I-NEXT:    slli a1, a1, 48
113; RV64I-NEXT:    slli a0, a0, 1
114; RV64I-NEXT:    srli a0, a0, 1
115; RV64I-NEXT:    or a0, a0, a1
116; RV64I-NEXT:    ret
117;
118; RV32IF-LABEL: fold_promote_d_h:
119; RV32IF:       # %bb.0:
120; RV32IF-NEXT:    fmv.x.w a2, fa0
121; RV32IF-NEXT:    lui a3, 8
122; RV32IF-NEXT:    and a2, a2, a3
123; RV32IF-NEXT:    slli a2, a2, 16
124; RV32IF-NEXT:    slli a1, a1, 1
125; RV32IF-NEXT:    srli a1, a1, 1
126; RV32IF-NEXT:    or a1, a1, a2
127; RV32IF-NEXT:    ret
128;
129; RV32IFD-LABEL: fold_promote_d_h:
130; RV32IFD:       # %bb.0:
131; RV32IFD-NEXT:    addi sp, sp, -16
132; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
133; RV32IFD-NEXT:    fsd fs0, 0(sp) # 8-byte Folded Spill
134; RV32IFD-NEXT:    fmv.d fs0, fa0
135; RV32IFD-NEXT:    fmv.x.w a0, fa1
136; RV32IFD-NEXT:    call __extendhfsf2@plt
137; RV32IFD-NEXT:    fcvt.d.s ft0, fa0
138; RV32IFD-NEXT:    fsgnj.d fa0, fs0, ft0
139; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
140; RV32IFD-NEXT:    fld fs0, 0(sp) # 8-byte Folded Reload
141; RV32IFD-NEXT:    addi sp, sp, 16
142; RV32IFD-NEXT:    ret
143;
144; RV64IFD-LABEL: fold_promote_d_h:
145; RV64IFD:       # %bb.0:
146; RV64IFD-NEXT:    addi sp, sp, -16
147; RV64IFD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
148; RV64IFD-NEXT:    fsd fs0, 0(sp) # 8-byte Folded Spill
149; RV64IFD-NEXT:    fmv.d fs0, fa0
150; RV64IFD-NEXT:    fmv.x.w a0, fa1
151; RV64IFD-NEXT:    call __extendhfsf2@plt
152; RV64IFD-NEXT:    fcvt.d.s ft0, fa0
153; RV64IFD-NEXT:    fsgnj.d fa0, fs0, ft0
154; RV64IFD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
155; RV64IFD-NEXT:    fld fs0, 0(sp) # 8-byte Folded Reload
156; RV64IFD-NEXT:    addi sp, sp, 16
157; RV64IFD-NEXT:    ret
158;
159; RV32IFZFH-LABEL: fold_promote_d_h:
160; RV32IFZFH:       # %bb.0:
161; RV32IFZFH-NEXT:    fmv.x.h a2, fa0
162; RV32IFZFH-NEXT:    lui a3, 8
163; RV32IFZFH-NEXT:    and a2, a2, a3
164; RV32IFZFH-NEXT:    slli a2, a2, 16
165; RV32IFZFH-NEXT:    slli a1, a1, 1
166; RV32IFZFH-NEXT:    srli a1, a1, 1
167; RV32IFZFH-NEXT:    or a1, a1, a2
168; RV32IFZFH-NEXT:    ret
169;
170; RV32IFDZFH-LABEL: fold_promote_d_h:
171; RV32IFDZFH:       # %bb.0:
172; RV32IFDZFH-NEXT:    fcvt.d.h ft0, fa1
173; RV32IFDZFH-NEXT:    fsgnj.d fa0, fa0, ft0
174; RV32IFDZFH-NEXT:    ret
175;
176; RV64IFDZFH-LABEL: fold_promote_d_h:
177; RV64IFDZFH:       # %bb.0:
178; RV64IFDZFH-NEXT:    fcvt.d.h ft0, fa1
179; RV64IFDZFH-NEXT:    fsgnj.d fa0, fa0, ft0
180; RV64IFDZFH-NEXT:    ret
181  %c = fpext half %b to double
182  %t = call double @llvm.copysign.f64(double %a, double %c)
183  ret double %t
184}
185
186define float @fold_promote_f_h(float %a, half %b) nounwind {
187; RV32I-LABEL: fold_promote_f_h:
188; RV32I:       # %bb.0:
189; RV32I-NEXT:    lui a2, 8
190; RV32I-NEXT:    and a1, a1, a2
191; RV32I-NEXT:    slli a1, a1, 16
192; RV32I-NEXT:    slli a0, a0, 1
193; RV32I-NEXT:    srli a0, a0, 1
194; RV32I-NEXT:    or a0, a0, a1
195; RV32I-NEXT:    ret
196;
197; RV64I-LABEL: fold_promote_f_h:
198; RV64I:       # %bb.0:
199; RV64I-NEXT:    lui a2, 8
200; RV64I-NEXT:    and a1, a1, a2
201; RV64I-NEXT:    slliw a1, a1, 16
202; RV64I-NEXT:    slli a0, a0, 33
203; RV64I-NEXT:    srli a0, a0, 33
204; RV64I-NEXT:    or a0, a0, a1
205; RV64I-NEXT:    ret
206;
207; RV32IF-LABEL: fold_promote_f_h:
208; RV32IF:       # %bb.0:
209; RV32IF-NEXT:    addi sp, sp, -16
210; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
211; RV32IF-NEXT:    fsw fs0, 8(sp) # 4-byte Folded Spill
212; RV32IF-NEXT:    fmv.s fs0, fa0
213; RV32IF-NEXT:    fmv.x.w a0, fa1
214; RV32IF-NEXT:    call __extendhfsf2@plt
215; RV32IF-NEXT:    fsgnj.s fa0, fs0, fa0
216; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
217; RV32IF-NEXT:    flw fs0, 8(sp) # 4-byte Folded Reload
218; RV32IF-NEXT:    addi sp, sp, 16
219; RV32IF-NEXT:    ret
220;
221; RV32IFD-LABEL: fold_promote_f_h:
222; RV32IFD:       # %bb.0:
223; RV32IFD-NEXT:    addi sp, sp, -16
224; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
225; RV32IFD-NEXT:    fsd fs0, 0(sp) # 8-byte Folded Spill
226; RV32IFD-NEXT:    fmv.s fs0, fa0
227; RV32IFD-NEXT:    fmv.x.w a0, fa1
228; RV32IFD-NEXT:    call __extendhfsf2@plt
229; RV32IFD-NEXT:    fsgnj.s fa0, fs0, fa0
230; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
231; RV32IFD-NEXT:    fld fs0, 0(sp) # 8-byte Folded Reload
232; RV32IFD-NEXT:    addi sp, sp, 16
233; RV32IFD-NEXT:    ret
234;
235; RV64IFD-LABEL: fold_promote_f_h:
236; RV64IFD:       # %bb.0:
237; RV64IFD-NEXT:    addi sp, sp, -16
238; RV64IFD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
239; RV64IFD-NEXT:    fsd fs0, 0(sp) # 8-byte Folded Spill
240; RV64IFD-NEXT:    fmv.s fs0, fa0
241; RV64IFD-NEXT:    fmv.x.w a0, fa1
242; RV64IFD-NEXT:    call __extendhfsf2@plt
243; RV64IFD-NEXT:    fsgnj.s fa0, fs0, fa0
244; RV64IFD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
245; RV64IFD-NEXT:    fld fs0, 0(sp) # 8-byte Folded Reload
246; RV64IFD-NEXT:    addi sp, sp, 16
247; RV64IFD-NEXT:    ret
248;
249; RV32IFZFH-LABEL: fold_promote_f_h:
250; RV32IFZFH:       # %bb.0:
251; RV32IFZFH-NEXT:    fcvt.s.h ft0, fa1
252; RV32IFZFH-NEXT:    fsgnj.s fa0, fa0, ft0
253; RV32IFZFH-NEXT:    ret
254;
255; RV32IFDZFH-LABEL: fold_promote_f_h:
256; RV32IFDZFH:       # %bb.0:
257; RV32IFDZFH-NEXT:    fcvt.s.h ft0, fa1
258; RV32IFDZFH-NEXT:    fsgnj.s fa0, fa0, ft0
259; RV32IFDZFH-NEXT:    ret
260;
261; RV64IFDZFH-LABEL: fold_promote_f_h:
262; RV64IFDZFH:       # %bb.0:
263; RV64IFDZFH-NEXT:    fcvt.s.h ft0, fa1
264; RV64IFDZFH-NEXT:    fsgnj.s fa0, fa0, ft0
265; RV64IFDZFH-NEXT:    ret
266  %c = fpext half %b to float
267  %t = call float @llvm.copysign.f32(float %a, float %c)
268  ret float %t
269}
270
271define float @fold_demote_s_d(float %a, double %b) nounwind {
272; RV32I-LABEL: fold_demote_s_d:
273; RV32I:       # %bb.0:
274; RV32I-NEXT:    lui a1, 524288
275; RV32I-NEXT:    and a1, a2, a1
276; RV32I-NEXT:    slli a0, a0, 1
277; RV32I-NEXT:    srli a0, a0, 1
278; RV32I-NEXT:    or a0, a0, a1
279; RV32I-NEXT:    ret
280;
281; RV64I-LABEL: fold_demote_s_d:
282; RV64I:       # %bb.0:
283; RV64I-NEXT:    slli a0, a0, 33
284; RV64I-NEXT:    srli a0, a0, 33
285; RV64I-NEXT:    srli a1, a1, 63
286; RV64I-NEXT:    slli a1, a1, 63
287; RV64I-NEXT:    srli a1, a1, 32
288; RV64I-NEXT:    or a0, a0, a1
289; RV64I-NEXT:    ret
290;
291; RV32IF-LABEL: fold_demote_s_d:
292; RV32IF:       # %bb.0:
293; RV32IF-NEXT:    fmv.w.x ft0, a1
294; RV32IF-NEXT:    fsgnj.s fa0, fa0, ft0
295; RV32IF-NEXT:    ret
296;
297; RV32IFD-LABEL: fold_demote_s_d:
298; RV32IFD:       # %bb.0:
299; RV32IFD-NEXT:    fcvt.s.d ft0, fa1
300; RV32IFD-NEXT:    fsgnj.s fa0, fa0, ft0
301; RV32IFD-NEXT:    ret
302;
303; RV64IFD-LABEL: fold_demote_s_d:
304; RV64IFD:       # %bb.0:
305; RV64IFD-NEXT:    fcvt.s.d ft0, fa1
306; RV64IFD-NEXT:    fsgnj.s fa0, fa0, ft0
307; RV64IFD-NEXT:    ret
308;
309; RV32IFZFH-LABEL: fold_demote_s_d:
310; RV32IFZFH:       # %bb.0:
311; RV32IFZFH-NEXT:    fmv.w.x ft0, a1
312; RV32IFZFH-NEXT:    fsgnj.s fa0, fa0, ft0
313; RV32IFZFH-NEXT:    ret
314;
315; RV32IFDZFH-LABEL: fold_demote_s_d:
316; RV32IFDZFH:       # %bb.0:
317; RV32IFDZFH-NEXT:    fcvt.s.d ft0, fa1
318; RV32IFDZFH-NEXT:    fsgnj.s fa0, fa0, ft0
319; RV32IFDZFH-NEXT:    ret
320;
321; RV64IFDZFH-LABEL: fold_demote_s_d:
322; RV64IFDZFH:       # %bb.0:
323; RV64IFDZFH-NEXT:    fcvt.s.d ft0, fa1
324; RV64IFDZFH-NEXT:    fsgnj.s fa0, fa0, ft0
325; RV64IFDZFH-NEXT:    ret
326  %c = fptrunc double %b to float
327  %t = call float @llvm.copysign.f32(float %a, float %c)
328  ret float %t
329}
330
331define half @fold_demote_h_s(half %a, float %b) nounwind {
332; RV32I-LABEL: fold_demote_h_s:
333; RV32I:       # %bb.0:
334; RV32I-NEXT:    lui a2, 524288
335; RV32I-NEXT:    and a1, a1, a2
336; RV32I-NEXT:    srli a1, a1, 16
337; RV32I-NEXT:    slli a0, a0, 17
338; RV32I-NEXT:    srli a0, a0, 17
339; RV32I-NEXT:    or a0, a0, a1
340; RV32I-NEXT:    ret
341;
342; RV64I-LABEL: fold_demote_h_s:
343; RV64I:       # %bb.0:
344; RV64I-NEXT:    srliw a1, a1, 31
345; RV64I-NEXT:    slli a1, a1, 15
346; RV64I-NEXT:    slli a0, a0, 49
347; RV64I-NEXT:    srli a0, a0, 49
348; RV64I-NEXT:    or a0, a0, a1
349; RV64I-NEXT:    ret
350;
351; RV32IF-LABEL: fold_demote_h_s:
352; RV32IF:       # %bb.0:
353; RV32IF-NEXT:    fmv.x.w a0, fa0
354; RV32IF-NEXT:    fmv.x.w a1, fa1
355; RV32IF-NEXT:    lui a2, 524288
356; RV32IF-NEXT:    and a1, a1, a2
357; RV32IF-NEXT:    srli a1, a1, 16
358; RV32IF-NEXT:    slli a0, a0, 17
359; RV32IF-NEXT:    srli a0, a0, 17
360; RV32IF-NEXT:    or a0, a0, a1
361; RV32IF-NEXT:    lui a1, 1048560
362; RV32IF-NEXT:    or a0, a0, a1
363; RV32IF-NEXT:    fmv.w.x fa0, a0
364; RV32IF-NEXT:    ret
365;
366; RV32IFD-LABEL: fold_demote_h_s:
367; RV32IFD:       # %bb.0:
368; RV32IFD-NEXT:    fmv.x.w a0, fa0
369; RV32IFD-NEXT:    fmv.x.w a1, fa1
370; RV32IFD-NEXT:    lui a2, 524288
371; RV32IFD-NEXT:    and a1, a1, a2
372; RV32IFD-NEXT:    srli a1, a1, 16
373; RV32IFD-NEXT:    slli a0, a0, 17
374; RV32IFD-NEXT:    srli a0, a0, 17
375; RV32IFD-NEXT:    or a0, a0, a1
376; RV32IFD-NEXT:    lui a1, 1048560
377; RV32IFD-NEXT:    or a0, a0, a1
378; RV32IFD-NEXT:    fmv.w.x fa0, a0
379; RV32IFD-NEXT:    ret
380;
381; RV64IFD-LABEL: fold_demote_h_s:
382; RV64IFD:       # %bb.0:
383; RV64IFD-NEXT:    fmv.x.w a0, fa0
384; RV64IFD-NEXT:    fmv.x.w a1, fa1
385; RV64IFD-NEXT:    lui a2, 524288
386; RV64IFD-NEXT:    and a1, a1, a2
387; RV64IFD-NEXT:    srli a1, a1, 16
388; RV64IFD-NEXT:    slli a0, a0, 49
389; RV64IFD-NEXT:    srli a0, a0, 49
390; RV64IFD-NEXT:    or a0, a0, a1
391; RV64IFD-NEXT:    lui a1, 1048560
392; RV64IFD-NEXT:    or a0, a0, a1
393; RV64IFD-NEXT:    fmv.w.x fa0, a0
394; RV64IFD-NEXT:    ret
395;
396; RV32IFZFH-LABEL: fold_demote_h_s:
397; RV32IFZFH:       # %bb.0:
398; RV32IFZFH-NEXT:    fcvt.h.s ft0, fa1
399; RV32IFZFH-NEXT:    fsgnj.h fa0, fa0, ft0
400; RV32IFZFH-NEXT:    ret
401;
402; RV32IFDZFH-LABEL: fold_demote_h_s:
403; RV32IFDZFH:       # %bb.0:
404; RV32IFDZFH-NEXT:    fcvt.h.s ft0, fa1
405; RV32IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
406; RV32IFDZFH-NEXT:    ret
407;
408; RV64IFDZFH-LABEL: fold_demote_h_s:
409; RV64IFDZFH:       # %bb.0:
410; RV64IFDZFH-NEXT:    fcvt.h.s ft0, fa1
411; RV64IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
412; RV64IFDZFH-NEXT:    ret
413  %c = fptrunc float %b to half
414  %t = call half @llvm.copysign.f16(half %a, half %c)
415  ret half %t
416}
417
418define half @fold_demote_h_d(half %a, double %b) nounwind {
419; RV32I-LABEL: fold_demote_h_d:
420; RV32I:       # %bb.0:
421; RV32I-NEXT:    lui a1, 524288
422; RV32I-NEXT:    and a1, a2, a1
423; RV32I-NEXT:    srli a1, a1, 16
424; RV32I-NEXT:    slli a0, a0, 17
425; RV32I-NEXT:    srli a0, a0, 17
426; RV32I-NEXT:    or a0, a0, a1
427; RV32I-NEXT:    ret
428;
429; RV64I-LABEL: fold_demote_h_d:
430; RV64I:       # %bb.0:
431; RV64I-NEXT:    slli a0, a0, 49
432; RV64I-NEXT:    srli a0, a0, 49
433; RV64I-NEXT:    srli a1, a1, 63
434; RV64I-NEXT:    slli a1, a1, 63
435; RV64I-NEXT:    srli a1, a1, 48
436; RV64I-NEXT:    or a0, a0, a1
437; RV64I-NEXT:    ret
438;
439; RV32IF-LABEL: fold_demote_h_d:
440; RV32IF:       # %bb.0:
441; RV32IF-NEXT:    fmv.x.w a0, fa0
442; RV32IF-NEXT:    lui a2, 524288
443; RV32IF-NEXT:    and a1, a1, a2
444; RV32IF-NEXT:    srli a1, a1, 16
445; RV32IF-NEXT:    slli a0, a0, 17
446; RV32IF-NEXT:    srli a0, a0, 17
447; RV32IF-NEXT:    or a0, a0, a1
448; RV32IF-NEXT:    lui a1, 1048560
449; RV32IF-NEXT:    or a0, a0, a1
450; RV32IF-NEXT:    fmv.w.x fa0, a0
451; RV32IF-NEXT:    ret
452;
453; RV32IFD-LABEL: fold_demote_h_d:
454; RV32IFD:       # %bb.0:
455; RV32IFD-NEXT:    addi sp, sp, -16
456; RV32IFD-NEXT:    fsd fa1, 8(sp)
457; RV32IFD-NEXT:    lw a0, 12(sp)
458; RV32IFD-NEXT:    fmv.x.w a1, fa0
459; RV32IFD-NEXT:    lui a2, 524288
460; RV32IFD-NEXT:    and a0, a0, a2
461; RV32IFD-NEXT:    srli a0, a0, 16
462; RV32IFD-NEXT:    slli a1, a1, 17
463; RV32IFD-NEXT:    srli a1, a1, 17
464; RV32IFD-NEXT:    or a0, a1, a0
465; RV32IFD-NEXT:    lui a1, 1048560
466; RV32IFD-NEXT:    or a0, a0, a1
467; RV32IFD-NEXT:    fmv.w.x fa0, a0
468; RV32IFD-NEXT:    addi sp, sp, 16
469; RV32IFD-NEXT:    ret
470;
471; RV64IFD-LABEL: fold_demote_h_d:
472; RV64IFD:       # %bb.0:
473; RV64IFD-NEXT:    fmv.x.d a0, fa1
474; RV64IFD-NEXT:    fmv.x.w a1, fa0
475; RV64IFD-NEXT:    slli a1, a1, 49
476; RV64IFD-NEXT:    srli a1, a1, 49
477; RV64IFD-NEXT:    srli a0, a0, 63
478; RV64IFD-NEXT:    slli a0, a0, 63
479; RV64IFD-NEXT:    srli a0, a0, 48
480; RV64IFD-NEXT:    or a0, a1, a0
481; RV64IFD-NEXT:    lui a1, 1048560
482; RV64IFD-NEXT:    or a0, a0, a1
483; RV64IFD-NEXT:    fmv.w.x fa0, a0
484; RV64IFD-NEXT:    ret
485;
486; RV32IFZFH-LABEL: fold_demote_h_d:
487; RV32IFZFH:       # %bb.0:
488; RV32IFZFH-NEXT:    srli a0, a1, 16
489; RV32IFZFH-NEXT:    fmv.h.x ft0, a0
490; RV32IFZFH-NEXT:    fsgnj.h fa0, fa0, ft0
491; RV32IFZFH-NEXT:    ret
492;
493; RV32IFDZFH-LABEL: fold_demote_h_d:
494; RV32IFDZFH:       # %bb.0:
495; RV32IFDZFH-NEXT:    fcvt.h.d ft0, fa1
496; RV32IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
497; RV32IFDZFH-NEXT:    ret
498;
499; RV64IFDZFH-LABEL: fold_demote_h_d:
500; RV64IFDZFH:       # %bb.0:
501; RV64IFDZFH-NEXT:    fcvt.h.d ft0, fa1
502; RV64IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
503; RV64IFDZFH-NEXT:    ret
504  %c = fptrunc double %b to half
505  %t = call half @llvm.copysign.f16(half %a, half %c)
506  ret half %t
507}
508