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