xref: /llvm-project/llvm/test/CodeGen/RISCV/float-mem.ll (revision eabaee0c59110d0e11b33a69db54ccda526b35fd)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
3; RUN:   -target-abi=ilp32f | FileCheck -check-prefixes=CHECKIF,RV32IF %s
4; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
5; RUN:   -target-abi=lp64f | FileCheck -check-prefixes=CHECKIF,RV64IF %s
6; RUN: llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs < %s \
7; RUN:   -target-abi=ilp32 | FileCheck -check-prefixes=CHECKIZFINX,RV32IZFINX %s
8; RUN: llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs < %s \
9; RUN:   -target-abi=lp64 | FileCheck -check-prefixes=CHECKIZFINX,RV64IZFINX %s
10
11define dso_local float @flw(ptr %a) nounwind {
12; CHECKIF-LABEL: flw:
13; CHECKIF:       # %bb.0:
14; CHECKIF-NEXT:    flw fa5, 0(a0)
15; CHECKIF-NEXT:    flw fa4, 12(a0)
16; CHECKIF-NEXT:    fadd.s fa0, fa5, fa4
17; CHECKIF-NEXT:    ret
18;
19; CHECKIZFINX-LABEL: flw:
20; CHECKIZFINX:       # %bb.0:
21; CHECKIZFINX-NEXT:    lw a1, 0(a0)
22; CHECKIZFINX-NEXT:    lw a0, 12(a0)
23; CHECKIZFINX-NEXT:    fadd.s a0, a1, a0
24; CHECKIZFINX-NEXT:    ret
25  %1 = load float, ptr %a
26  %2 = getelementptr float, ptr %a, i32 3
27  %3 = load float, ptr %2
28; Use both loaded values in an FP op to ensure an flw is used, even for the
29; soft float ABI
30  %4 = fadd float %1, %3
31  ret float %4
32}
33
34define dso_local void @fsw(ptr %a, float %b, float %c) nounwind {
35; Use %b and %c in an FP op to ensure floating point registers are used, even
36; for the soft float ABI
37; CHECKIF-LABEL: fsw:
38; CHECKIF:       # %bb.0:
39; CHECKIF-NEXT:    fadd.s fa5, fa0, fa1
40; CHECKIF-NEXT:    fsw fa5, 0(a0)
41; CHECKIF-NEXT:    fsw fa5, 32(a0)
42; CHECKIF-NEXT:    ret
43;
44; CHECKIZFINX-LABEL: fsw:
45; CHECKIZFINX:       # %bb.0:
46; CHECKIZFINX-NEXT:    fadd.s a1, a1, a2
47; CHECKIZFINX-NEXT:    sw a1, 0(a0)
48; CHECKIZFINX-NEXT:    sw a1, 32(a0)
49; CHECKIZFINX-NEXT:    ret
50  %1 = fadd float %b, %c
51  store float %1, ptr %a
52  %2 = getelementptr float, ptr %a, i32 8
53  store float %1, ptr %2
54  ret void
55}
56
57; Check load and store to a global
58@G = dso_local global float 0.0
59
60define dso_local float @flw_fsw_global(float %a, float %b) nounwind {
61; Use %a and %b in an FP op to ensure floating point registers are used, even
62; for the soft float ABI
63; CHECKIF-LABEL: flw_fsw_global:
64; CHECKIF:       # %bb.0:
65; CHECKIF-NEXT:    fadd.s fa0, fa0, fa1
66; CHECKIF-NEXT:    lui a0, %hi(G)
67; CHECKIF-NEXT:    flw fa5, %lo(G)(a0)
68; CHECKIF-NEXT:    addi a1, a0, %lo(G)
69; CHECKIF-NEXT:    fsw fa0, %lo(G)(a0)
70; CHECKIF-NEXT:    flw fa5, 36(a1)
71; CHECKIF-NEXT:    fsw fa0, 36(a1)
72; CHECKIF-NEXT:    ret
73;
74; CHECKIZFINX-LABEL: flw_fsw_global:
75; CHECKIZFINX:       # %bb.0:
76; CHECKIZFINX-NEXT:    fadd.s a0, a0, a1
77; CHECKIZFINX-NEXT:    lui a1, %hi(G)
78; CHECKIZFINX-NEXT:    lw zero, %lo(G)(a1)
79; CHECKIZFINX-NEXT:    addi a2, a1, %lo(G)
80; CHECKIZFINX-NEXT:    sw a0, %lo(G)(a1)
81; CHECKIZFINX-NEXT:    lw zero, 36(a2)
82; CHECKIZFINX-NEXT:    sw a0, 36(a2)
83; CHECKIZFINX-NEXT:    ret
84  %1 = fadd float %a, %b
85  %2 = load volatile float, ptr @G
86  store float %1, ptr @G
87  %3 = getelementptr float, ptr @G, i32 9
88  %4 = load volatile float, ptr %3
89  store float %1, ptr %3
90  ret float %1
91}
92
93; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
94define dso_local float @flw_fsw_constant(float %a) nounwind {
95; RV32IF-LABEL: flw_fsw_constant:
96; RV32IF:       # %bb.0:
97; RV32IF-NEXT:    lui a0, 912092
98; RV32IF-NEXT:    flw fa5, -273(a0)
99; RV32IF-NEXT:    fadd.s fa0, fa0, fa5
100; RV32IF-NEXT:    fsw fa0, -273(a0)
101; RV32IF-NEXT:    ret
102;
103; RV64IF-LABEL: flw_fsw_constant:
104; RV64IF:       # %bb.0:
105; RV64IF-NEXT:    lui a0, 228023
106; RV64IF-NEXT:    slli a0, a0, 2
107; RV64IF-NEXT:    flw fa5, -273(a0)
108; RV64IF-NEXT:    fadd.s fa0, fa0, fa5
109; RV64IF-NEXT:    fsw fa0, -273(a0)
110; RV64IF-NEXT:    ret
111;
112; RV32IZFINX-LABEL: flw_fsw_constant:
113; RV32IZFINX:       # %bb.0:
114; RV32IZFINX-NEXT:    lui a1, 912092
115; RV32IZFINX-NEXT:    lw a2, -273(a1)
116; RV32IZFINX-NEXT:    fadd.s a0, a0, a2
117; RV32IZFINX-NEXT:    sw a0, -273(a1)
118; RV32IZFINX-NEXT:    ret
119;
120; RV64IZFINX-LABEL: flw_fsw_constant:
121; RV64IZFINX:       # %bb.0:
122; RV64IZFINX-NEXT:    lui a1, 228023
123; RV64IZFINX-NEXT:    slli a1, a1, 2
124; RV64IZFINX-NEXT:    lw a2, -273(a1)
125; RV64IZFINX-NEXT:    fadd.s a0, a0, a2
126; RV64IZFINX-NEXT:    sw a0, -273(a1)
127; RV64IZFINX-NEXT:    ret
128  %1 = inttoptr i32 3735928559 to ptr
129  %2 = load volatile float, ptr %1
130  %3 = fadd float %a, %2
131  store float %3, ptr %1
132  ret float %3
133}
134
135declare void @notdead(ptr)
136
137define dso_local float @flw_stack(float %a) nounwind {
138; RV32IF-LABEL: flw_stack:
139; RV32IF:       # %bb.0:
140; RV32IF-NEXT:    addi sp, sp, -16
141; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
142; RV32IF-NEXT:    fsw fs0, 8(sp) # 4-byte Folded Spill
143; RV32IF-NEXT:    fmv.s fs0, fa0
144; RV32IF-NEXT:    addi a0, sp, 4
145; RV32IF-NEXT:    call notdead
146; RV32IF-NEXT:    flw fa5, 4(sp)
147; RV32IF-NEXT:    fadd.s fa0, fa5, fs0
148; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
149; RV32IF-NEXT:    flw fs0, 8(sp) # 4-byte Folded Reload
150; RV32IF-NEXT:    addi sp, sp, 16
151; RV32IF-NEXT:    ret
152;
153; RV64IF-LABEL: flw_stack:
154; RV64IF:       # %bb.0:
155; RV64IF-NEXT:    addi sp, sp, -16
156; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
157; RV64IF-NEXT:    fsw fs0, 4(sp) # 4-byte Folded Spill
158; RV64IF-NEXT:    fmv.s fs0, fa0
159; RV64IF-NEXT:    mv a0, sp
160; RV64IF-NEXT:    call notdead
161; RV64IF-NEXT:    flw fa5, 0(sp)
162; RV64IF-NEXT:    fadd.s fa0, fa5, fs0
163; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
164; RV64IF-NEXT:    flw fs0, 4(sp) # 4-byte Folded Reload
165; RV64IF-NEXT:    addi sp, sp, 16
166; RV64IF-NEXT:    ret
167;
168; RV32IZFINX-LABEL: flw_stack:
169; RV32IZFINX:       # %bb.0:
170; RV32IZFINX-NEXT:    addi sp, sp, -16
171; RV32IZFINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
172; RV32IZFINX-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
173; RV32IZFINX-NEXT:    mv s0, a0
174; RV32IZFINX-NEXT:    addi a0, sp, 4
175; RV32IZFINX-NEXT:    call notdead
176; RV32IZFINX-NEXT:    lw a0, 4(sp)
177; RV32IZFINX-NEXT:    fadd.s a0, a0, s0
178; RV32IZFINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
179; RV32IZFINX-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
180; RV32IZFINX-NEXT:    addi sp, sp, 16
181; RV32IZFINX-NEXT:    ret
182;
183; RV64IZFINX-LABEL: flw_stack:
184; RV64IZFINX:       # %bb.0:
185; RV64IZFINX-NEXT:    addi sp, sp, -32
186; RV64IZFINX-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
187; RV64IZFINX-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
188; RV64IZFINX-NEXT:    mv s0, a0
189; RV64IZFINX-NEXT:    addi a0, sp, 12
190; RV64IZFINX-NEXT:    call notdead
191; RV64IZFINX-NEXT:    lw a0, 12(sp)
192; RV64IZFINX-NEXT:    fadd.s a0, a0, s0
193; RV64IZFINX-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
194; RV64IZFINX-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
195; RV64IZFINX-NEXT:    addi sp, sp, 32
196; RV64IZFINX-NEXT:    ret
197  %1 = alloca float, align 4
198  call void @notdead(ptr %1)
199  %2 = load float, ptr %1
200  %3 = fadd float %2, %a ; force load in to FPR32
201  ret float %3
202}
203
204define dso_local void @fsw_stack(float %a, float %b) nounwind {
205; RV32IF-LABEL: fsw_stack:
206; RV32IF:       # %bb.0:
207; RV32IF-NEXT:    addi sp, sp, -16
208; RV32IF-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
209; RV32IF-NEXT:    fadd.s fa5, fa0, fa1
210; RV32IF-NEXT:    fsw fa5, 8(sp)
211; RV32IF-NEXT:    addi a0, sp, 8
212; RV32IF-NEXT:    call notdead
213; RV32IF-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
214; RV32IF-NEXT:    addi sp, sp, 16
215; RV32IF-NEXT:    ret
216;
217; RV64IF-LABEL: fsw_stack:
218; RV64IF:       # %bb.0:
219; RV64IF-NEXT:    addi sp, sp, -16
220; RV64IF-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
221; RV64IF-NEXT:    fadd.s fa5, fa0, fa1
222; RV64IF-NEXT:    fsw fa5, 4(sp)
223; RV64IF-NEXT:    addi a0, sp, 4
224; RV64IF-NEXT:    call notdead
225; RV64IF-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
226; RV64IF-NEXT:    addi sp, sp, 16
227; RV64IF-NEXT:    ret
228;
229; RV32IZFINX-LABEL: fsw_stack:
230; RV32IZFINX:       # %bb.0:
231; RV32IZFINX-NEXT:    addi sp, sp, -16
232; RV32IZFINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
233; RV32IZFINX-NEXT:    fadd.s a0, a0, a1
234; RV32IZFINX-NEXT:    sw a0, 8(sp)
235; RV32IZFINX-NEXT:    addi a0, sp, 8
236; RV32IZFINX-NEXT:    call notdead
237; RV32IZFINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
238; RV32IZFINX-NEXT:    addi sp, sp, 16
239; RV32IZFINX-NEXT:    ret
240;
241; RV64IZFINX-LABEL: fsw_stack:
242; RV64IZFINX:       # %bb.0:
243; RV64IZFINX-NEXT:    addi sp, sp, -16
244; RV64IZFINX-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
245; RV64IZFINX-NEXT:    fadd.s a0, a0, a1
246; RV64IZFINX-NEXT:    sw a0, 4(sp)
247; RV64IZFINX-NEXT:    addi a0, sp, 4
248; RV64IZFINX-NEXT:    call notdead
249; RV64IZFINX-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
250; RV64IZFINX-NEXT:    addi sp, sp, 16
251; RV64IZFINX-NEXT:    ret
252  %1 = fadd float %a, %b ; force store from FPR32
253  %2 = alloca float, align 4
254  store float %1, ptr %2
255  call void @notdead(ptr %2)
256  ret void
257}
258