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:    li a2, 1
345; RV64I-NEXT:    slli a2, a2, 31
346; RV64I-NEXT:    and a1, a1, a2
347; RV64I-NEXT:    srli a1, a1, 16
348; RV64I-NEXT:    slli a0, a0, 49
349; RV64I-NEXT:    srli a0, a0, 49
350; RV64I-NEXT:    or a0, a0, a1
351; RV64I-NEXT:    ret
352;
353; RV32IF-LABEL: fold_demote_h_s:
354; RV32IF:       # %bb.0:
355; RV32IF-NEXT:    fmv.x.w a0, fa0
356; RV32IF-NEXT:    fmv.x.w a1, fa1
357; RV32IF-NEXT:    lui a2, 524288
358; RV32IF-NEXT:    and a1, a1, a2
359; RV32IF-NEXT:    srli a1, a1, 16
360; RV32IF-NEXT:    slli a0, a0, 17
361; RV32IF-NEXT:    srli a0, a0, 17
362; RV32IF-NEXT:    or a0, a0, a1
363; RV32IF-NEXT:    lui a1, 1048560
364; RV32IF-NEXT:    or a0, a0, a1
365; RV32IF-NEXT:    fmv.w.x fa0, a0
366; RV32IF-NEXT:    ret
367;
368; RV32IFD-LABEL: fold_demote_h_s:
369; RV32IFD:       # %bb.0:
370; RV32IFD-NEXT:    fmv.x.w a0, fa0
371; RV32IFD-NEXT:    fmv.x.w a1, fa1
372; RV32IFD-NEXT:    lui a2, 524288
373; RV32IFD-NEXT:    and a1, a1, a2
374; RV32IFD-NEXT:    srli a1, a1, 16
375; RV32IFD-NEXT:    slli a0, a0, 17
376; RV32IFD-NEXT:    srli a0, a0, 17
377; RV32IFD-NEXT:    or a0, a0, a1
378; RV32IFD-NEXT:    lui a1, 1048560
379; RV32IFD-NEXT:    or a0, a0, a1
380; RV32IFD-NEXT:    fmv.w.x fa0, a0
381; RV32IFD-NEXT:    ret
382;
383; RV64IFD-LABEL: fold_demote_h_s:
384; RV64IFD:       # %bb.0:
385; RV64IFD-NEXT:    fmv.x.w a0, fa0
386; RV64IFD-NEXT:    fmv.x.w a1, fa1
387; RV64IFD-NEXT:    lui a2, 524288
388; RV64IFD-NEXT:    and a1, a1, a2
389; RV64IFD-NEXT:    srli a1, a1, 16
390; RV64IFD-NEXT:    slli a0, a0, 49
391; RV64IFD-NEXT:    srli a0, a0, 49
392; RV64IFD-NEXT:    or a0, a0, a1
393; RV64IFD-NEXT:    lui a1, 1048560
394; RV64IFD-NEXT:    or a0, a0, a1
395; RV64IFD-NEXT:    fmv.w.x fa0, a0
396; RV64IFD-NEXT:    ret
397;
398; RV32IFZFH-LABEL: fold_demote_h_s:
399; RV32IFZFH:       # %bb.0:
400; RV32IFZFH-NEXT:    fcvt.h.s ft0, fa1
401; RV32IFZFH-NEXT:    fsgnj.h fa0, fa0, ft0
402; RV32IFZFH-NEXT:    ret
403;
404; RV32IFDZFH-LABEL: fold_demote_h_s:
405; RV32IFDZFH:       # %bb.0:
406; RV32IFDZFH-NEXT:    fcvt.h.s ft0, fa1
407; RV32IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
408; RV32IFDZFH-NEXT:    ret
409;
410; RV64IFDZFH-LABEL: fold_demote_h_s:
411; RV64IFDZFH:       # %bb.0:
412; RV64IFDZFH-NEXT:    fcvt.h.s ft0, fa1
413; RV64IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
414; RV64IFDZFH-NEXT:    ret
415  %c = fptrunc float %b to half
416  %t = call half @llvm.copysign.f16(half %a, half %c)
417  ret half %t
418}
419
420define half @fold_demote_h_d(half %a, double %b) nounwind {
421; RV32I-LABEL: fold_demote_h_d:
422; RV32I:       # %bb.0:
423; RV32I-NEXT:    lui a1, 524288
424; RV32I-NEXT:    and a1, a2, a1
425; RV32I-NEXT:    srli a1, a1, 16
426; RV32I-NEXT:    slli a0, a0, 17
427; RV32I-NEXT:    srli a0, a0, 17
428; RV32I-NEXT:    or a0, a0, a1
429; RV32I-NEXT:    ret
430;
431; RV64I-LABEL: fold_demote_h_d:
432; RV64I:       # %bb.0:
433; RV64I-NEXT:    slli a0, a0, 49
434; RV64I-NEXT:    srli a0, a0, 49
435; RV64I-NEXT:    srli a1, a1, 63
436; RV64I-NEXT:    slli a1, a1, 63
437; RV64I-NEXT:    srli a1, a1, 48
438; RV64I-NEXT:    or a0, a0, a1
439; RV64I-NEXT:    ret
440;
441; RV32IF-LABEL: fold_demote_h_d:
442; RV32IF:       # %bb.0:
443; RV32IF-NEXT:    fmv.x.w a0, fa0
444; RV32IF-NEXT:    lui a2, 524288
445; RV32IF-NEXT:    and a1, a1, a2
446; RV32IF-NEXT:    srli a1, a1, 16
447; RV32IF-NEXT:    slli a0, a0, 17
448; RV32IF-NEXT:    srli a0, a0, 17
449; RV32IF-NEXT:    or a0, a0, a1
450; RV32IF-NEXT:    lui a1, 1048560
451; RV32IF-NEXT:    or a0, a0, a1
452; RV32IF-NEXT:    fmv.w.x fa0, a0
453; RV32IF-NEXT:    ret
454;
455; RV32IFD-LABEL: fold_demote_h_d:
456; RV32IFD:       # %bb.0:
457; RV32IFD-NEXT:    addi sp, sp, -16
458; RV32IFD-NEXT:    fsd fa1, 8(sp)
459; RV32IFD-NEXT:    lw a0, 12(sp)
460; RV32IFD-NEXT:    fmv.x.w a1, fa0
461; RV32IFD-NEXT:    lui a2, 524288
462; RV32IFD-NEXT:    and a0, a0, a2
463; RV32IFD-NEXT:    srli a0, a0, 16
464; RV32IFD-NEXT:    slli a1, a1, 17
465; RV32IFD-NEXT:    srli a1, a1, 17
466; RV32IFD-NEXT:    or a0, a1, a0
467; RV32IFD-NEXT:    lui a1, 1048560
468; RV32IFD-NEXT:    or a0, a0, a1
469; RV32IFD-NEXT:    fmv.w.x fa0, a0
470; RV32IFD-NEXT:    addi sp, sp, 16
471; RV32IFD-NEXT:    ret
472;
473; RV64IFD-LABEL: fold_demote_h_d:
474; RV64IFD:       # %bb.0:
475; RV64IFD-NEXT:    fmv.x.d a0, fa1
476; RV64IFD-NEXT:    fmv.x.w a1, fa0
477; RV64IFD-NEXT:    slli a1, a1, 49
478; RV64IFD-NEXT:    srli a1, a1, 49
479; RV64IFD-NEXT:    srli a0, a0, 63
480; RV64IFD-NEXT:    slli a0, a0, 63
481; RV64IFD-NEXT:    srli a0, a0, 48
482; RV64IFD-NEXT:    or a0, a1, a0
483; RV64IFD-NEXT:    lui a1, 1048560
484; RV64IFD-NEXT:    or a0, a0, a1
485; RV64IFD-NEXT:    fmv.w.x fa0, a0
486; RV64IFD-NEXT:    ret
487;
488; RV32IFZFH-LABEL: fold_demote_h_d:
489; RV32IFZFH:       # %bb.0:
490; RV32IFZFH-NEXT:    srli a0, a1, 16
491; RV32IFZFH-NEXT:    fmv.h.x ft0, a0
492; RV32IFZFH-NEXT:    fsgnj.h fa0, fa0, ft0
493; RV32IFZFH-NEXT:    ret
494;
495; RV32IFDZFH-LABEL: fold_demote_h_d:
496; RV32IFDZFH:       # %bb.0:
497; RV32IFDZFH-NEXT:    fcvt.h.d ft0, fa1
498; RV32IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
499; RV32IFDZFH-NEXT:    ret
500;
501; RV64IFDZFH-LABEL: fold_demote_h_d:
502; RV64IFDZFH:       # %bb.0:
503; RV64IFDZFH-NEXT:    fcvt.h.d ft0, fa1
504; RV64IFDZFH-NEXT:    fsgnj.h fa0, fa0, ft0
505; RV64IFDZFH-NEXT:    ret
506  %c = fptrunc double %b to half
507  %t = call half @llvm.copysign.f16(half %a, half %c)
508  ret half %t
509}
510