xref: /llvm-project/llvm/test/CodeGen/RISCV/half-mem.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \
3; RUN:   -target-abi ilp32f < %s | FileCheck -check-prefixes=CHECKIZFH,RV32IZFH %s
4; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \
5; RUN:   -target-abi lp64f < %s | FileCheck -check-prefixes=CHECKIZFH,RV64IZFH %s
6; RUN: llc -mtriple=riscv32 -mattr=+zhinx -verify-machineinstrs \
7; RUN:   -target-abi ilp32 < %s | FileCheck -check-prefixes=CHECKIZHINX,RV32IZHINX %s
8; RUN: llc -mtriple=riscv64 -mattr=+zhinx -verify-machineinstrs \
9; RUN:   -target-abi lp64 < %s | FileCheck -check-prefixes=CHECKIZHINX,RV64IZHINX %s
10; RUN: llc -mtriple=riscv32 -mattr=+zfhmin -verify-machineinstrs \
11; RUN:   -target-abi ilp32f < %s | FileCheck -check-prefixes=CHECKIZFHMIN,RV32IZFHMIN %s
12; RUN: llc -mtriple=riscv64 -mattr=+zfhmin -verify-machineinstrs \
13; RUN:   -target-abi lp64f < %s | FileCheck -check-prefixes=CHECKIZFHMIN,RV64IZFHMIN %s
14; RUN: llc -mtriple=riscv32 -mattr=+zhinxmin -verify-machineinstrs \
15; RUN:   -target-abi ilp32 < %s | FileCheck -check-prefixes=CHECKIZHINXMIN,RV32IZHINXMIN %s
16; RUN: llc -mtriple=riscv64 -mattr=+zhinxmin -verify-machineinstrs \
17; RUN:   -target-abi lp64 < %s | FileCheck -check-prefixes=CHECKIZHINXMIN,RV64IZHINXMIN %s
18
19define half @flh(ptr %a) nounwind {
20; CHECKIZFH-LABEL: flh:
21; CHECKIZFH:       # %bb.0:
22; CHECKIZFH-NEXT:    flh fa5, 0(a0)
23; CHECKIZFH-NEXT:    flh fa4, 6(a0)
24; CHECKIZFH-NEXT:    fadd.h fa0, fa5, fa4
25; CHECKIZFH-NEXT:    ret
26;
27; CHECKIZHINX-LABEL: flh:
28; CHECKIZHINX:       # %bb.0:
29; CHECKIZHINX-NEXT:    lh a1, 0(a0)
30; CHECKIZHINX-NEXT:    lh a0, 6(a0)
31; CHECKIZHINX-NEXT:    fadd.h a0, a1, a0
32; CHECKIZHINX-NEXT:    ret
33;
34; CHECKIZFHMIN-LABEL: flh:
35; CHECKIZFHMIN:       # %bb.0:
36; CHECKIZFHMIN-NEXT:    flh fa5, 6(a0)
37; CHECKIZFHMIN-NEXT:    flh fa4, 0(a0)
38; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa5
39; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa4
40; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
41; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
42; CHECKIZFHMIN-NEXT:    ret
43;
44; CHECKIZHINXMIN-LABEL: flh:
45; CHECKIZHINXMIN:       # %bb.0:
46; CHECKIZHINXMIN-NEXT:    lh a1, 6(a0)
47; CHECKIZHINXMIN-NEXT:    lh a0, 0(a0)
48; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
49; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
50; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, a1
51; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
52; CHECKIZHINXMIN-NEXT:    ret
53  %1 = load half, ptr %a
54  %2 = getelementptr half, ptr %a, i32 3
55  %3 = load half, ptr %2
56; Use both loaded values in an FP op to ensure an flh is used, even for the
57; soft half ABI
58  %4 = fadd half %1, %3
59  ret half %4
60}
61
62define dso_local void @fsh(ptr %a, half %b, half %c) nounwind {
63; Use %b and %c in an FP op to ensure half precision floating point registers
64; are used, even for the soft half ABI
65; CHECKIZFH-LABEL: fsh:
66; CHECKIZFH:       # %bb.0:
67; CHECKIZFH-NEXT:    fadd.h fa5, fa0, fa1
68; CHECKIZFH-NEXT:    fsh fa5, 0(a0)
69; CHECKIZFH-NEXT:    fsh fa5, 16(a0)
70; CHECKIZFH-NEXT:    ret
71;
72; CHECKIZHINX-LABEL: fsh:
73; CHECKIZHINX:       # %bb.0:
74; CHECKIZHINX-NEXT:    fadd.h a1, a1, a2
75; CHECKIZHINX-NEXT:    sh a1, 0(a0)
76; CHECKIZHINX-NEXT:    sh a1, 16(a0)
77; CHECKIZHINX-NEXT:    ret
78;
79; CHECKIZFHMIN-LABEL: fsh:
80; CHECKIZFHMIN:       # %bb.0:
81; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
82; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
83; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
84; CHECKIZFHMIN-NEXT:    fcvt.h.s fa5, fa5
85; CHECKIZFHMIN-NEXT:    fsh fa5, 0(a0)
86; CHECKIZFHMIN-NEXT:    fsh fa5, 16(a0)
87; CHECKIZFHMIN-NEXT:    ret
88;
89; CHECKIZHINXMIN-LABEL: fsh:
90; CHECKIZHINXMIN:       # %bb.0:
91; CHECKIZHINXMIN-NEXT:    fcvt.s.h a2, a2
92; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
93; CHECKIZHINXMIN-NEXT:    fadd.s a1, a1, a2
94; CHECKIZHINXMIN-NEXT:    fcvt.h.s a1, a1
95; CHECKIZHINXMIN-NEXT:    sh a1, 0(a0)
96; CHECKIZHINXMIN-NEXT:    sh a1, 16(a0)
97; CHECKIZHINXMIN-NEXT:    ret
98  %1 = fadd half %b, %c
99  store half %1, ptr %a
100  %2 = getelementptr half, ptr %a, i32 8
101  store half %1, ptr %2
102  ret void
103}
104
105; Check load and store to a global
106@G = dso_local global half 0.0
107
108define half @flh_fsh_global(half %a, half %b) nounwind {
109; Use %a and %b in an FP op to ensure half precision floating point registers
110; are used, even for the soft half ABI
111; CHECKIZFH-LABEL: flh_fsh_global:
112; CHECKIZFH:       # %bb.0:
113; CHECKIZFH-NEXT:    fadd.h fa0, fa0, fa1
114; CHECKIZFH-NEXT:    lui a0, %hi(G)
115; CHECKIZFH-NEXT:    flh fa5, %lo(G)(a0)
116; CHECKIZFH-NEXT:    addi a1, a0, %lo(G)
117; CHECKIZFH-NEXT:    fsh fa0, %lo(G)(a0)
118; CHECKIZFH-NEXT:    flh fa5, 18(a1)
119; CHECKIZFH-NEXT:    fsh fa0, 18(a1)
120; CHECKIZFH-NEXT:    ret
121;
122; CHECKIZHINX-LABEL: flh_fsh_global:
123; CHECKIZHINX:       # %bb.0:
124; CHECKIZHINX-NEXT:    fadd.h a0, a0, a1
125; CHECKIZHINX-NEXT:    lui a1, %hi(G)
126; CHECKIZHINX-NEXT:    lh zero, %lo(G)(a1)
127; CHECKIZHINX-NEXT:    addi a2, a1, %lo(G)
128; CHECKIZHINX-NEXT:    sh a0, %lo(G)(a1)
129; CHECKIZHINX-NEXT:    lh zero, 18(a2)
130; CHECKIZHINX-NEXT:    sh a0, 18(a2)
131; CHECKIZHINX-NEXT:    ret
132;
133; CHECKIZFHMIN-LABEL: flh_fsh_global:
134; CHECKIZFHMIN:       # %bb.0:
135; CHECKIZFHMIN-NEXT:    fcvt.s.h fa5, fa1
136; CHECKIZFHMIN-NEXT:    fcvt.s.h fa4, fa0
137; CHECKIZFHMIN-NEXT:    lui a0, %hi(G)
138; CHECKIZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
139; CHECKIZFHMIN-NEXT:    flh fa4, %lo(G)(a0)
140; CHECKIZFHMIN-NEXT:    fcvt.h.s fa0, fa5
141; CHECKIZFHMIN-NEXT:    addi a1, a0, %lo(G)
142; CHECKIZFHMIN-NEXT:    fsh fa0, %lo(G)(a0)
143; CHECKIZFHMIN-NEXT:    flh fa5, 18(a1)
144; CHECKIZFHMIN-NEXT:    fsh fa0, 18(a1)
145; CHECKIZFHMIN-NEXT:    ret
146;
147; CHECKIZHINXMIN-LABEL: flh_fsh_global:
148; CHECKIZHINXMIN:       # %bb.0:
149; CHECKIZHINXMIN-NEXT:    fcvt.s.h a1, a1
150; CHECKIZHINXMIN-NEXT:    fcvt.s.h a0, a0
151; CHECKIZHINXMIN-NEXT:    lui a2, %hi(G)
152; CHECKIZHINXMIN-NEXT:    fadd.s a0, a0, a1
153; CHECKIZHINXMIN-NEXT:    lh zero, %lo(G)(a2)
154; CHECKIZHINXMIN-NEXT:    fcvt.h.s a0, a0
155; CHECKIZHINXMIN-NEXT:    addi a1, a2, %lo(G)
156; CHECKIZHINXMIN-NEXT:    sh a0, %lo(G)(a2)
157; CHECKIZHINXMIN-NEXT:    lh zero, 18(a1)
158; CHECKIZHINXMIN-NEXT:    sh a0, 18(a1)
159; CHECKIZHINXMIN-NEXT:    ret
160  %1 = fadd half %a, %b
161  %2 = load volatile half, ptr @G
162  store half %1, ptr @G
163  %3 = getelementptr half, ptr @G, i32 9
164  %4 = load volatile half, ptr %3
165  store half %1, ptr %3
166  ret half %1
167}
168
169; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
170define half @flh_fsh_constant(half %a) nounwind {
171; RV32IZFH-LABEL: flh_fsh_constant:
172; RV32IZFH:       # %bb.0:
173; RV32IZFH-NEXT:    lui a0, 912092
174; RV32IZFH-NEXT:    flh fa5, -273(a0)
175; RV32IZFH-NEXT:    fadd.h fa0, fa0, fa5
176; RV32IZFH-NEXT:    fsh fa0, -273(a0)
177; RV32IZFH-NEXT:    ret
178;
179; RV64IZFH-LABEL: flh_fsh_constant:
180; RV64IZFH:       # %bb.0:
181; RV64IZFH-NEXT:    lui a0, 228023
182; RV64IZFH-NEXT:    slli a0, a0, 2
183; RV64IZFH-NEXT:    flh fa5, -273(a0)
184; RV64IZFH-NEXT:    fadd.h fa0, fa0, fa5
185; RV64IZFH-NEXT:    fsh fa0, -273(a0)
186; RV64IZFH-NEXT:    ret
187;
188; RV32IZHINX-LABEL: flh_fsh_constant:
189; RV32IZHINX:       # %bb.0:
190; RV32IZHINX-NEXT:    lui a1, 912092
191; RV32IZHINX-NEXT:    lh a2, -273(a1)
192; RV32IZHINX-NEXT:    fadd.h a0, a0, a2
193; RV32IZHINX-NEXT:    sh a0, -273(a1)
194; RV32IZHINX-NEXT:    ret
195;
196; RV64IZHINX-LABEL: flh_fsh_constant:
197; RV64IZHINX:       # %bb.0:
198; RV64IZHINX-NEXT:    lui a1, 228023
199; RV64IZHINX-NEXT:    slli a1, a1, 2
200; RV64IZHINX-NEXT:    lh a2, -273(a1)
201; RV64IZHINX-NEXT:    fadd.h a0, a0, a2
202; RV64IZHINX-NEXT:    sh a0, -273(a1)
203; RV64IZHINX-NEXT:    ret
204;
205; RV32IZFHMIN-LABEL: flh_fsh_constant:
206; RV32IZFHMIN:       # %bb.0:
207; RV32IZFHMIN-NEXT:    lui a0, 912092
208; RV32IZFHMIN-NEXT:    flh fa5, -273(a0)
209; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
210; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
211; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
212; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
213; RV32IZFHMIN-NEXT:    fsh fa0, -273(a0)
214; RV32IZFHMIN-NEXT:    ret
215;
216; RV64IZFHMIN-LABEL: flh_fsh_constant:
217; RV64IZFHMIN:       # %bb.0:
218; RV64IZFHMIN-NEXT:    lui a0, 228023
219; RV64IZFHMIN-NEXT:    slli a0, a0, 2
220; RV64IZFHMIN-NEXT:    flh fa5, -273(a0)
221; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
222; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
223; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
224; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
225; RV64IZFHMIN-NEXT:    fsh fa0, -273(a0)
226; RV64IZFHMIN-NEXT:    ret
227;
228; RV32IZHINXMIN-LABEL: flh_fsh_constant:
229; RV32IZHINXMIN:       # %bb.0:
230; RV32IZHINXMIN-NEXT:    lui a1, 912092
231; RV32IZHINXMIN-NEXT:    lh a2, -273(a1)
232; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
233; RV32IZHINXMIN-NEXT:    fcvt.s.h a2, a2
234; RV32IZHINXMIN-NEXT:    fadd.s a0, a0, a2
235; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
236; RV32IZHINXMIN-NEXT:    sh a0, -273(a1)
237; RV32IZHINXMIN-NEXT:    ret
238;
239; RV64IZHINXMIN-LABEL: flh_fsh_constant:
240; RV64IZHINXMIN:       # %bb.0:
241; RV64IZHINXMIN-NEXT:    lui a1, 228023
242; RV64IZHINXMIN-NEXT:    slli a1, a1, 2
243; RV64IZHINXMIN-NEXT:    lh a2, -273(a1)
244; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
245; RV64IZHINXMIN-NEXT:    fcvt.s.h a2, a2
246; RV64IZHINXMIN-NEXT:    fadd.s a0, a0, a2
247; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
248; RV64IZHINXMIN-NEXT:    sh a0, -273(a1)
249; RV64IZHINXMIN-NEXT:    ret
250  %1 = inttoptr i32 3735928559 to ptr
251  %2 = load volatile half, ptr %1
252  %3 = fadd half %a, %2
253  store half %3, ptr %1
254  ret half %3
255}
256
257declare void @notdead(ptr)
258
259define half @flh_stack(half %a) nounwind {
260; RV32IZFH-LABEL: flh_stack:
261; RV32IZFH:       # %bb.0:
262; RV32IZFH-NEXT:    addi sp, sp, -16
263; RV32IZFH-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
264; RV32IZFH-NEXT:    fsw fs0, 8(sp) # 4-byte Folded Spill
265; RV32IZFH-NEXT:    fmv.h fs0, fa0
266; RV32IZFH-NEXT:    addi a0, sp, 4
267; RV32IZFH-NEXT:    call notdead
268; RV32IZFH-NEXT:    flh fa5, 4(sp)
269; RV32IZFH-NEXT:    fadd.h fa0, fa5, fs0
270; RV32IZFH-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
271; RV32IZFH-NEXT:    flw fs0, 8(sp) # 4-byte Folded Reload
272; RV32IZFH-NEXT:    addi sp, sp, 16
273; RV32IZFH-NEXT:    ret
274;
275; RV64IZFH-LABEL: flh_stack:
276; RV64IZFH:       # %bb.0:
277; RV64IZFH-NEXT:    addi sp, sp, -16
278; RV64IZFH-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
279; RV64IZFH-NEXT:    fsw fs0, 4(sp) # 4-byte Folded Spill
280; RV64IZFH-NEXT:    fmv.h fs0, fa0
281; RV64IZFH-NEXT:    mv a0, sp
282; RV64IZFH-NEXT:    call notdead
283; RV64IZFH-NEXT:    flh fa5, 0(sp)
284; RV64IZFH-NEXT:    fadd.h fa0, fa5, fs0
285; RV64IZFH-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
286; RV64IZFH-NEXT:    flw fs0, 4(sp) # 4-byte Folded Reload
287; RV64IZFH-NEXT:    addi sp, sp, 16
288; RV64IZFH-NEXT:    ret
289;
290; RV32IZHINX-LABEL: flh_stack:
291; RV32IZHINX:       # %bb.0:
292; RV32IZHINX-NEXT:    addi sp, sp, -16
293; RV32IZHINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
294; RV32IZHINX-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
295; RV32IZHINX-NEXT:    mv s0, a0
296; RV32IZHINX-NEXT:    addi a0, sp, 4
297; RV32IZHINX-NEXT:    call notdead
298; RV32IZHINX-NEXT:    lh a0, 4(sp)
299; RV32IZHINX-NEXT:    fadd.h a0, a0, s0
300; RV32IZHINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
301; RV32IZHINX-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
302; RV32IZHINX-NEXT:    addi sp, sp, 16
303; RV32IZHINX-NEXT:    ret
304;
305; RV64IZHINX-LABEL: flh_stack:
306; RV64IZHINX:       # %bb.0:
307; RV64IZHINX-NEXT:    addi sp, sp, -32
308; RV64IZHINX-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
309; RV64IZHINX-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
310; RV64IZHINX-NEXT:    mv s0, a0
311; RV64IZHINX-NEXT:    addi a0, sp, 12
312; RV64IZHINX-NEXT:    call notdead
313; RV64IZHINX-NEXT:    lh a0, 12(sp)
314; RV64IZHINX-NEXT:    fadd.h a0, a0, s0
315; RV64IZHINX-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
316; RV64IZHINX-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
317; RV64IZHINX-NEXT:    addi sp, sp, 32
318; RV64IZHINX-NEXT:    ret
319;
320; RV32IZFHMIN-LABEL: flh_stack:
321; RV32IZFHMIN:       # %bb.0:
322; RV32IZFHMIN-NEXT:    addi sp, sp, -16
323; RV32IZFHMIN-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
324; RV32IZFHMIN-NEXT:    fsw fs0, 8(sp) # 4-byte Folded Spill
325; RV32IZFHMIN-NEXT:    fmv.s fs0, fa0
326; RV32IZFHMIN-NEXT:    addi a0, sp, 4
327; RV32IZFHMIN-NEXT:    call notdead
328; RV32IZFHMIN-NEXT:    flh fa5, 4(sp)
329; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fs0
330; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
331; RV32IZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
332; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
333; RV32IZFHMIN-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
334; RV32IZFHMIN-NEXT:    flw fs0, 8(sp) # 4-byte Folded Reload
335; RV32IZFHMIN-NEXT:    addi sp, sp, 16
336; RV32IZFHMIN-NEXT:    ret
337;
338; RV64IZFHMIN-LABEL: flh_stack:
339; RV64IZFHMIN:       # %bb.0:
340; RV64IZFHMIN-NEXT:    addi sp, sp, -16
341; RV64IZFHMIN-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
342; RV64IZFHMIN-NEXT:    fsw fs0, 4(sp) # 4-byte Folded Spill
343; RV64IZFHMIN-NEXT:    fmv.s fs0, fa0
344; RV64IZFHMIN-NEXT:    mv a0, sp
345; RV64IZFHMIN-NEXT:    call notdead
346; RV64IZFHMIN-NEXT:    flh fa5, 0(sp)
347; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fs0
348; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
349; RV64IZFHMIN-NEXT:    fadd.s fa5, fa5, fa4
350; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
351; RV64IZFHMIN-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
352; RV64IZFHMIN-NEXT:    flw fs0, 4(sp) # 4-byte Folded Reload
353; RV64IZFHMIN-NEXT:    addi sp, sp, 16
354; RV64IZFHMIN-NEXT:    ret
355;
356; RV32IZHINXMIN-LABEL: flh_stack:
357; RV32IZHINXMIN:       # %bb.0:
358; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
359; RV32IZHINXMIN-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
360; RV32IZHINXMIN-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
361; RV32IZHINXMIN-NEXT:    mv s0, a0
362; RV32IZHINXMIN-NEXT:    addi a0, sp, 4
363; RV32IZHINXMIN-NEXT:    call notdead
364; RV32IZHINXMIN-NEXT:    lh a0, 4(sp)
365; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, s0
366; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
367; RV32IZHINXMIN-NEXT:    fadd.s a0, a0, a1
368; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
369; RV32IZHINXMIN-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
370; RV32IZHINXMIN-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
371; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
372; RV32IZHINXMIN-NEXT:    ret
373;
374; RV64IZHINXMIN-LABEL: flh_stack:
375; RV64IZHINXMIN:       # %bb.0:
376; RV64IZHINXMIN-NEXT:    addi sp, sp, -32
377; RV64IZHINXMIN-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
378; RV64IZHINXMIN-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
379; RV64IZHINXMIN-NEXT:    mv s0, a0
380; RV64IZHINXMIN-NEXT:    addi a0, sp, 12
381; RV64IZHINXMIN-NEXT:    call notdead
382; RV64IZHINXMIN-NEXT:    lh a0, 12(sp)
383; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, s0
384; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
385; RV64IZHINXMIN-NEXT:    fadd.s a0, a0, a1
386; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
387; RV64IZHINXMIN-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
388; RV64IZHINXMIN-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
389; RV64IZHINXMIN-NEXT:    addi sp, sp, 32
390; RV64IZHINXMIN-NEXT:    ret
391  %1 = alloca half, align 4
392  call void @notdead(ptr %1)
393  %2 = load half, ptr %1
394  %3 = fadd half %2, %a ; force load in to FPR16
395  ret half %3
396}
397
398define dso_local void @fsh_stack(half %a, half %b) nounwind {
399; RV32IZFH-LABEL: fsh_stack:
400; RV32IZFH:       # %bb.0:
401; RV32IZFH-NEXT:    addi sp, sp, -16
402; RV32IZFH-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
403; RV32IZFH-NEXT:    fadd.h fa5, fa0, fa1
404; RV32IZFH-NEXT:    fsh fa5, 8(sp)
405; RV32IZFH-NEXT:    addi a0, sp, 8
406; RV32IZFH-NEXT:    call notdead
407; RV32IZFH-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
408; RV32IZFH-NEXT:    addi sp, sp, 16
409; RV32IZFH-NEXT:    ret
410;
411; RV64IZFH-LABEL: fsh_stack:
412; RV64IZFH:       # %bb.0:
413; RV64IZFH-NEXT:    addi sp, sp, -16
414; RV64IZFH-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
415; RV64IZFH-NEXT:    fadd.h fa5, fa0, fa1
416; RV64IZFH-NEXT:    fsh fa5, 4(sp)
417; RV64IZFH-NEXT:    addi a0, sp, 4
418; RV64IZFH-NEXT:    call notdead
419; RV64IZFH-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
420; RV64IZFH-NEXT:    addi sp, sp, 16
421; RV64IZFH-NEXT:    ret
422;
423; RV32IZHINX-LABEL: fsh_stack:
424; RV32IZHINX:       # %bb.0:
425; RV32IZHINX-NEXT:    addi sp, sp, -16
426; RV32IZHINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
427; RV32IZHINX-NEXT:    fadd.h a0, a0, a1
428; RV32IZHINX-NEXT:    sh a0, 8(sp)
429; RV32IZHINX-NEXT:    addi a0, sp, 8
430; RV32IZHINX-NEXT:    call notdead
431; RV32IZHINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
432; RV32IZHINX-NEXT:    addi sp, sp, 16
433; RV32IZHINX-NEXT:    ret
434;
435; RV64IZHINX-LABEL: fsh_stack:
436; RV64IZHINX:       # %bb.0:
437; RV64IZHINX-NEXT:    addi sp, sp, -16
438; RV64IZHINX-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
439; RV64IZHINX-NEXT:    fadd.h a0, a0, a1
440; RV64IZHINX-NEXT:    sh a0, 4(sp)
441; RV64IZHINX-NEXT:    addi a0, sp, 4
442; RV64IZHINX-NEXT:    call notdead
443; RV64IZHINX-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
444; RV64IZHINX-NEXT:    addi sp, sp, 16
445; RV64IZHINX-NEXT:    ret
446;
447; RV32IZFHMIN-LABEL: fsh_stack:
448; RV32IZFHMIN:       # %bb.0:
449; RV32IZFHMIN-NEXT:    addi sp, sp, -16
450; RV32IZFHMIN-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
451; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
452; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
453; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
454; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
455; RV32IZFHMIN-NEXT:    fsh fa5, 8(sp)
456; RV32IZFHMIN-NEXT:    addi a0, sp, 8
457; RV32IZFHMIN-NEXT:    call notdead
458; RV32IZFHMIN-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
459; RV32IZFHMIN-NEXT:    addi sp, sp, 16
460; RV32IZFHMIN-NEXT:    ret
461;
462; RV64IZFHMIN-LABEL: fsh_stack:
463; RV64IZFHMIN:       # %bb.0:
464; RV64IZFHMIN-NEXT:    addi sp, sp, -16
465; RV64IZFHMIN-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
466; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
467; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
468; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
469; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
470; RV64IZFHMIN-NEXT:    fsh fa5, 4(sp)
471; RV64IZFHMIN-NEXT:    addi a0, sp, 4
472; RV64IZFHMIN-NEXT:    call notdead
473; RV64IZFHMIN-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
474; RV64IZFHMIN-NEXT:    addi sp, sp, 16
475; RV64IZFHMIN-NEXT:    ret
476;
477; RV32IZHINXMIN-LABEL: fsh_stack:
478; RV32IZHINXMIN:       # %bb.0:
479; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
480; RV32IZHINXMIN-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
481; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
482; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
483; RV32IZHINXMIN-NEXT:    fadd.s a0, a0, a1
484; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
485; RV32IZHINXMIN-NEXT:    sh a0, 8(sp)
486; RV32IZHINXMIN-NEXT:    addi a0, sp, 8
487; RV32IZHINXMIN-NEXT:    call notdead
488; RV32IZHINXMIN-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
489; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
490; RV32IZHINXMIN-NEXT:    ret
491;
492; RV64IZHINXMIN-LABEL: fsh_stack:
493; RV64IZHINXMIN:       # %bb.0:
494; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
495; RV64IZHINXMIN-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
496; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
497; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
498; RV64IZHINXMIN-NEXT:    fadd.s a0, a0, a1
499; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
500; RV64IZHINXMIN-NEXT:    sh a0, 4(sp)
501; RV64IZHINXMIN-NEXT:    addi a0, sp, 4
502; RV64IZHINXMIN-NEXT:    call notdead
503; RV64IZHINXMIN-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
504; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
505; RV64IZHINXMIN-NEXT:    ret
506  %1 = fadd half %a, %b ; force store from FPR16
507  %2 = alloca half, align 4
508  store half %1, ptr %2
509  call void @notdead(ptr %2)
510  ret void
511}
512