xref: /llvm-project/llvm/test/CodeGen/RISCV/copysign-casts.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
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
36
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.
39
40declare double @llvm.copysign.f64(double, double)
41declare float @llvm.copysign.f32(float, float)
42declare half @llvm.copysign.f16(half, half)
43
44define double @fold_promote_d_s(double %a, float %b) nounwind {
45; RV32I-LABEL: fold_promote_d_s:
46; RV32I:       # %bb.0:
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
52; RV32I-NEXT:    ret
53;
54; RV64I-LABEL: fold_promote_d_s:
55; RV64I:       # %bb.0:
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
62; RV64I-NEXT:    ret
63;
64; RV32IF-LABEL: fold_promote_d_s:
65; RV32IF:       # %bb.0:
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
72; RV32IF-NEXT:    ret
73;
74; RV32IFD-LABEL: fold_promote_d_s:
75; RV32IFD:       # %bb.0:
76; RV32IFD-NEXT:    fcvt.d.s fa5, fa1
77; RV32IFD-NEXT:    fsgnj.d fa0, fa0, fa5
78; RV32IFD-NEXT:    ret
79;
80; RV64IFD-LABEL: fold_promote_d_s:
81; RV64IFD:       # %bb.0:
82; RV64IFD-NEXT:    fcvt.d.s fa5, fa1
83; RV64IFD-NEXT:    fsgnj.d fa0, fa0, fa5
84; RV64IFD-NEXT:    ret
85;
86; RV32IFZFH-LABEL: fold_promote_d_s:
87; RV32IFZFH:       # %bb.0:
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
94; RV32IFZFH-NEXT:    ret
95;
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
101;
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
107;
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
117;
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
123;
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
129;
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
135;
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)
143  ret double %t
144}
145
146define double @fold_promote_d_h(double %a, half %b) nounwind {
147; RV32I-LABEL: fold_promote_d_h:
148; RV32I:       # %bb.0:
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
155; RV32I-NEXT:    ret
156;
157; RV64I-LABEL: fold_promote_d_h:
158; RV64I:       # %bb.0:
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
165; RV64I-NEXT:    ret
166;
167; RV32IF-LABEL: fold_promote_d_h:
168; RV32IF:       # %bb.0:
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
176; RV32IF-NEXT:    ret
177;
178; RV32IFD-LABEL: fold_promote_d_h:
179; RV32IFD:       # %bb.0:
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
191; RV32IFD-NEXT:    ret
192;
193; RV64IFD-LABEL: fold_promote_d_h:
194; RV64IFD:       # %bb.0:
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
206; RV64IFD-NEXT:    ret
207;
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
218;
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
224;
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
230;
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
241;
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
247;
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
253;
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
271;
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)
288  ret double %t
289}
290
291define float @fold_promote_f_h(float %a, half %b) nounwind {
292; RV32I-LABEL: fold_promote_f_h:
293; RV32I:       # %bb.0:
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
300; RV32I-NEXT:    ret
301;
302; RV64I-LABEL: fold_promote_f_h:
303; RV64I:       # %bb.0:
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
310; RV64I-NEXT:    ret
311;
312; RV32IF-LABEL: fold_promote_f_h:
313; RV32IF:       # %bb.0:
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
324; RV32IF-NEXT:    ret
325;
326; RV32IFD-LABEL: fold_promote_f_h:
327; RV32IFD:       # %bb.0:
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
338; RV32IFD-NEXT:    ret
339;
340; RV64IFD-LABEL: fold_promote_f_h:
341; RV64IFD:       # %bb.0:
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
352; RV64IFD-NEXT:    ret
353;
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
359;
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
365;
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
371;
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
377;
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
383;
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
389;
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
403;
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)
419  ret float %t
420}
421
422define float @fold_demote_s_d(float %a, double %b) nounwind {
423; RV32I-LABEL: fold_demote_s_d:
424; RV32I:       # %bb.0:
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
430; RV32I-NEXT:    ret
431;
432; RV64I-LABEL: fold_demote_s_d:
433; RV64I:       # %bb.0:
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
440; RV64I-NEXT:    ret
441;
442; RV32IF-LABEL: fold_demote_s_d:
443; RV32IF:       # %bb.0:
444; RV32IF-NEXT:    fmv.w.x fa5, a1
445; RV32IF-NEXT:    fsgnj.s fa0, fa0, fa5
446; RV32IF-NEXT:    ret
447;
448; RV32IFD-LABEL: fold_demote_s_d:
449; RV32IFD:       # %bb.0:
450; RV32IFD-NEXT:    fcvt.s.d fa5, fa1
451; RV32IFD-NEXT:    fsgnj.s fa0, fa0, fa5
452; RV32IFD-NEXT:    ret
453;
454; RV64IFD-LABEL: fold_demote_s_d:
455; RV64IFD:       # %bb.0:
456; RV64IFD-NEXT:    fcvt.s.d fa5, fa1
457; RV64IFD-NEXT:    fsgnj.s fa0, fa0, fa5
458; RV64IFD-NEXT:    ret
459;
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
465;
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
471;
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
477;
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
483;
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
489;
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
495;
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
503;
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)
511  ret float %t
512}
513
514define half @fold_demote_h_s(half %a, float %b) nounwind {
515; RV32I-LABEL: fold_demote_h_s:
516; RV32I:       # %bb.0:
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
523; RV32I-NEXT:    ret
524;
525; RV64I-LABEL: fold_demote_h_s:
526; RV64I:       # %bb.0:
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
532; RV64I-NEXT:    ret
533;
534; RV32IF-LABEL: fold_demote_h_s:
535; RV32IF:       # %bb.0:
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
547; RV32IF-NEXT:    ret
548;
549; RV32IFD-LABEL: fold_demote_h_s:
550; RV32IFD:       # %bb.0:
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
562; RV32IFD-NEXT:    ret
563;
564; RV64IFD-LABEL: fold_demote_h_s:
565; RV64IFD:       # %bb.0:
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
577; RV64IFD-NEXT:    ret
578;
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
584;
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
590;
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
596;
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
608;
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
620;
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
632;
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
647;
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)
664  ret half %t
665}
666
667define half @fold_demote_h_d(half %a, double %b) nounwind {
668; RV32I-LABEL: fold_demote_h_d:
669; RV32I:       # %bb.0:
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
676; RV32I-NEXT:    ret
677;
678; RV64I-LABEL: fold_demote_h_d:
679; RV64I:       # %bb.0:
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
686; RV64I-NEXT:    ret
687;
688; RV32IF-LABEL: fold_demote_h_d:
689; RV32IF:       # %bb.0:
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
700; RV32IF-NEXT:    ret
701;
702; RV32IFD-LABEL: fold_demote_h_d:
703; RV32IFD:       # %bb.0:
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
718; RV32IFD-NEXT:    ret
719;
720; RV64IFD-LABEL: fold_demote_h_d:
721; RV64IFD:       # %bb.0:
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
733; RV64IFD-NEXT:    ret
734;
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
741;
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
747;
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
753;
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
764;
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
779;
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
791;
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
805;
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)
821  ret half %t
822}
823