[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / CodeGen / RISCV / rv64-legal-i32 / mem64.ll
blob76ab0e7d5810e7092e3c0a449323ab838ec753c3
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
3 ; RUN:   -riscv-experimental-rv64-legal-i32 | FileCheck -check-prefix=RV64I %s
5 ; Check indexed and unindexed, sext, zext and anyext loads
7 define dso_local i64 @lb(ptr %a) nounwind {
8 ; RV64I-LABEL: lb:
9 ; RV64I:       # %bb.0:
10 ; RV64I-NEXT:    lb a1, 1(a0)
11 ; RV64I-NEXT:    lbu zero, 0(a0)
12 ; RV64I-NEXT:    mv a0, a1
13 ; RV64I-NEXT:    ret
14   %1 = getelementptr i8, ptr %a, i32 1
15   %2 = load i8, ptr %1
16   %3 = sext i8 %2 to i64
17   ; the unused load will produce an anyext for selection
18   %4 = load volatile i8, ptr %a
19   ret i64 %3
22 define dso_local i64 @lh(ptr %a) nounwind {
23 ; RV64I-LABEL: lh:
24 ; RV64I:       # %bb.0:
25 ; RV64I-NEXT:    lh a1, 4(a0)
26 ; RV64I-NEXT:    lh zero, 0(a0)
27 ; RV64I-NEXT:    mv a0, a1
28 ; RV64I-NEXT:    ret
29   %1 = getelementptr i16, ptr %a, i32 2
30   %2 = load i16, ptr %1
31   %3 = sext i16 %2 to i64
32   ; the unused load will produce an anyext for selection
33   %4 = load volatile i16, ptr %a
34   ret i64 %3
37 define dso_local i64 @lw(ptr %a) nounwind {
38 ; RV64I-LABEL: lw:
39 ; RV64I:       # %bb.0:
40 ; RV64I-NEXT:    lw a1, 12(a0)
41 ; RV64I-NEXT:    lw zero, 0(a0)
42 ; RV64I-NEXT:    mv a0, a1
43 ; RV64I-NEXT:    ret
44   %1 = getelementptr i32, ptr %a, i32 3
45   %2 = load i32, ptr %1
46   %3 = sext i32 %2 to i64
47   ; the unused load will produce an anyext for selection
48   %4 = load volatile i32, ptr %a
49   ret i64 %3
52 define dso_local i64 @lbu(ptr %a) nounwind {
53 ; RV64I-LABEL: lbu:
54 ; RV64I:       # %bb.0:
55 ; RV64I-NEXT:    lbu a1, 4(a0)
56 ; RV64I-NEXT:    lbu a0, 0(a0)
57 ; RV64I-NEXT:    add a0, a1, a0
58 ; RV64I-NEXT:    ret
59   %1 = getelementptr i8, ptr %a, i32 4
60   %2 = load i8, ptr %1
61   %3 = zext i8 %2 to i64
62   %4 = load volatile i8, ptr %a
63   %5 = zext i8 %4 to i64
64   %6 = add i64 %3, %5
65   ret i64 %6
68 define dso_local i64 @lhu(ptr %a) nounwind {
69 ; RV64I-LABEL: lhu:
70 ; RV64I:       # %bb.0:
71 ; RV64I-NEXT:    lhu a1, 10(a0)
72 ; RV64I-NEXT:    lhu a0, 0(a0)
73 ; RV64I-NEXT:    add a0, a1, a0
74 ; RV64I-NEXT:    ret
75   %1 = getelementptr i16, ptr %a, i32 5
76   %2 = load i16, ptr %1
77   %3 = zext i16 %2 to i64
78   %4 = load volatile i16, ptr %a
79   %5 = zext i16 %4 to i64
80   %6 = add i64 %3, %5
81   ret i64 %6
84 define dso_local i64 @lwu(ptr %a) nounwind {
85 ; RV64I-LABEL: lwu:
86 ; RV64I:       # %bb.0:
87 ; RV64I-NEXT:    lwu a1, 24(a0)
88 ; RV64I-NEXT:    lwu a0, 0(a0)
89 ; RV64I-NEXT:    add a0, a1, a0
90 ; RV64I-NEXT:    ret
91   %1 = getelementptr i32, ptr %a, i32 6
92   %2 = load i32, ptr %1
93   %3 = zext i32 %2 to i64
94   %4 = load volatile i32, ptr %a
95   %5 = zext i32 %4 to i64
96   %6 = add i64 %3, %5
97   ret i64 %6
100 ; 64-bit loads and stores
102 define dso_local i64 @ld(ptr %a) nounwind {
103 ; RV64I-LABEL: ld:
104 ; RV64I:       # %bb.0:
105 ; RV64I-NEXT:    ld a1, 80(a0)
106 ; RV64I-NEXT:    ld zero, 0(a0)
107 ; RV64I-NEXT:    mv a0, a1
108 ; RV64I-NEXT:    ret
109   %1 = getelementptr i64, ptr %a, i32 10
110   %2 = load i64, ptr %1
111   %3 = load volatile i64, ptr %a
112   ret i64 %2
115 define dso_local void @sd(ptr %a, i64 %b) nounwind {
116 ; RV64I-LABEL: sd:
117 ; RV64I:       # %bb.0:
118 ; RV64I-NEXT:    sd a1, 0(a0)
119 ; RV64I-NEXT:    sd a1, 88(a0)
120 ; RV64I-NEXT:    ret
121   store i64 %b, ptr %a
122   %1 = getelementptr i64, ptr %a, i32 11
123   store i64 %b, ptr %1
124   ret void
127 ; Check load and store to an i1 location
128 define dso_local i64 @load_sext_zext_anyext_i1(ptr %a) nounwind {
129 ; RV64I-LABEL: load_sext_zext_anyext_i1:
130 ; RV64I:       # %bb.0:
131 ; RV64I-NEXT:    lbu a1, 1(a0)
132 ; RV64I-NEXT:    lbu a2, 2(a0)
133 ; RV64I-NEXT:    lbu zero, 0(a0)
134 ; RV64I-NEXT:    sub a0, a2, a1
135 ; RV64I-NEXT:    ret
136   ; sextload i1
137   %1 = getelementptr i1, ptr %a, i32 1
138   %2 = load i1, ptr %1
139   %3 = sext i1 %2 to i64
140   ; zextload i1
141   %4 = getelementptr i1, ptr %a, i32 2
142   %5 = load i1, ptr %4
143   %6 = zext i1 %5 to i64
144   %7 = add i64 %3, %6
145   ; extload i1 (anyext). Produced as the load is unused.
146   %8 = load volatile i1, ptr %a
147   ret i64 %7
150 define dso_local i16 @load_sext_zext_anyext_i1_i16(ptr %a) nounwind {
151 ; RV64I-LABEL: load_sext_zext_anyext_i1_i16:
152 ; RV64I:       # %bb.0:
153 ; RV64I-NEXT:    lbu a1, 1(a0)
154 ; RV64I-NEXT:    lbu a2, 2(a0)
155 ; RV64I-NEXT:    lbu zero, 0(a0)
156 ; RV64I-NEXT:    subw a0, a2, a1
157 ; RV64I-NEXT:    ret
158   ; sextload i1
159   %1 = getelementptr i1, ptr %a, i32 1
160   %2 = load i1, ptr %1
161   %3 = sext i1 %2 to i16
162   ; zextload i1
163   %4 = getelementptr i1, ptr %a, i32 2
164   %5 = load i1, ptr %4
165   %6 = zext i1 %5 to i16
166   %7 = add i16 %3, %6
167   ; extload i1 (anyext). Produced as the load is unused.
168   %8 = load volatile i1, ptr %a
169   ret i16 %7
172 ; Check load and store to a global
173 @G = dso_local global i64 0
175 define dso_local i64 @ld_sd_global(i64 %a) nounwind {
176 ; RV64I-LABEL: ld_sd_global:
177 ; RV64I:       # %bb.0:
178 ; RV64I-NEXT:    lui a2, %hi(G)
179 ; RV64I-NEXT:    ld a1, %lo(G)(a2)
180 ; RV64I-NEXT:    addi a3, a2, %lo(G)
181 ; RV64I-NEXT:    sd a0, %lo(G)(a2)
182 ; RV64I-NEXT:    ld zero, 72(a3)
183 ; RV64I-NEXT:    sd a0, 72(a3)
184 ; RV64I-NEXT:    mv a0, a1
185 ; RV64I-NEXT:    ret
186   %1 = load volatile i64, ptr @G
187   store i64 %a, ptr @G
188   %2 = getelementptr i64, ptr @G, i64 9
189   %3 = load volatile i64, ptr %2
190   store i64 %a, ptr %2
191   ret i64 %1
194 define i64 @lw_near_local(ptr %a)  {
195 ; RV64I-LABEL: lw_near_local:
196 ; RV64I:       # %bb.0:
197 ; RV64I-NEXT:    addi a0, a0, 2047
198 ; RV64I-NEXT:    ld a0, 9(a0)
199 ; RV64I-NEXT:    ret
200   %1 = getelementptr inbounds i64, ptr %a, i64 257
201   %2 = load volatile i64, ptr %1
202   ret i64 %2
205 define void @st_near_local(ptr %a, i64 %b)  {
206 ; RV64I-LABEL: st_near_local:
207 ; RV64I:       # %bb.0:
208 ; RV64I-NEXT:    addi a0, a0, 2047
209 ; RV64I-NEXT:    sd a1, 9(a0)
210 ; RV64I-NEXT:    ret
211   %1 = getelementptr inbounds i64, ptr %a, i64 257
212   store i64 %b, ptr %1
213   ret void
216 define i64 @lw_sw_near_local(ptr %a, i64 %b)  {
217 ; RV64I-LABEL: lw_sw_near_local:
218 ; RV64I:       # %bb.0:
219 ; RV64I-NEXT:    addi a2, a0, 2047
220 ; RV64I-NEXT:    ld a0, 9(a2)
221 ; RV64I-NEXT:    sd a1, 9(a2)
222 ; RV64I-NEXT:    ret
223   %1 = getelementptr inbounds i64, ptr %a, i64 257
224   %2 = load volatile i64, ptr %1
225   store i64 %b, ptr %1
226   ret i64 %2
229 define i64 @lw_far_local(ptr %a)  {
230 ; RV64I-LABEL: lw_far_local:
231 ; RV64I:       # %bb.0:
232 ; RV64I-NEXT:    lui a1, 8
233 ; RV64I-NEXT:    add a0, a0, a1
234 ; RV64I-NEXT:    ld a0, -8(a0)
235 ; RV64I-NEXT:    ret
236   %1 = getelementptr inbounds i64, ptr %a, i64 4095
237   %2 = load volatile i64, ptr %1
238   ret i64 %2
241 define void @st_far_local(ptr %a, i64 %b)  {
242 ; RV64I-LABEL: st_far_local:
243 ; RV64I:       # %bb.0:
244 ; RV64I-NEXT:    lui a2, 8
245 ; RV64I-NEXT:    add a0, a0, a2
246 ; RV64I-NEXT:    sd a1, -8(a0)
247 ; RV64I-NEXT:    ret
248   %1 = getelementptr inbounds i64, ptr %a, i64 4095
249   store i64 %b, ptr %1
250   ret void
253 define i64 @lw_sw_far_local(ptr %a, i64 %b)  {
254 ; RV64I-LABEL: lw_sw_far_local:
255 ; RV64I:       # %bb.0:
256 ; RV64I-NEXT:    lui a2, 8
257 ; RV64I-NEXT:    add a2, a0, a2
258 ; RV64I-NEXT:    ld a0, -8(a2)
259 ; RV64I-NEXT:    sd a1, -8(a2)
260 ; RV64I-NEXT:    ret
261   %1 = getelementptr inbounds i64, ptr %a, i64 4095
262   %2 = load volatile i64, ptr %1
263   store i64 %b, ptr %1
264   ret i64 %2
267 ; Make sure we don't fold the addiw into the load offset. The sign extend of the
268 ; addiw is required.
269 define i64 @lw_really_far_local(ptr %a)  {
270 ; RV64I-LABEL: lw_really_far_local:
271 ; RV64I:       # %bb.0:
272 ; RV64I-NEXT:    lui a1, 524288
273 ; RV64I-NEXT:    addiw a1, a1, -2048
274 ; RV64I-NEXT:    add a0, a0, a1
275 ; RV64I-NEXT:    ld a0, 0(a0)
276 ; RV64I-NEXT:    ret
277   %1 = getelementptr inbounds i64, ptr %a, i64 268435200
278   %2 = load volatile i64, ptr %1
279   ret i64 %2
282 ; Make sure we don't fold the addiw into the store offset. The sign extend of
283 ; the addiw is required.
284 define void @st_really_far_local(ptr %a, i64 %b)  {
285 ; RV64I-LABEL: st_really_far_local:
286 ; RV64I:       # %bb.0:
287 ; RV64I-NEXT:    lui a2, 524288
288 ; RV64I-NEXT:    addiw a2, a2, -2048
289 ; RV64I-NEXT:    add a0, a0, a2
290 ; RV64I-NEXT:    sd a1, 0(a0)
291 ; RV64I-NEXT:    ret
292   %1 = getelementptr inbounds i64, ptr %a, i64 268435200
293   store i64 %b, ptr %1
294   ret void
297 ; Make sure we don't fold the addiw into the load/store offset. The sign extend
298 ; of the addiw is required.
299 define i64 @lw_sw_really_far_local(ptr %a, i64 %b)  {
300 ; RV64I-LABEL: lw_sw_really_far_local:
301 ; RV64I:       # %bb.0:
302 ; RV64I-NEXT:    lui a2, 524288
303 ; RV64I-NEXT:    addiw a2, a2, -2048
304 ; RV64I-NEXT:    add a2, a0, a2
305 ; RV64I-NEXT:    ld a0, 0(a2)
306 ; RV64I-NEXT:    sd a1, 0(a2)
307 ; RV64I-NEXT:    ret
308   %1 = getelementptr inbounds i64, ptr %a, i64 268435200
309   %2 = load volatile i64, ptr %1
310   store i64 %b, ptr %1
311   ret i64 %2
314 %struct.quux = type { i32, [0 x i8] }
316 ; Make sure we don't remove the addi and fold the C from
317 ; (add (addi FrameIndex, C), X) into the store address.
318 ; FrameIndex cannot be the operand of an ADD. We must keep the ADDI.
319 define void @addi_fold_crash(i64 %arg) nounwind {
320 ; RV64I-LABEL: addi_fold_crash:
321 ; RV64I:       # %bb.0: # %bb
322 ; RV64I-NEXT:    addi sp, sp, -16
323 ; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
324 ; RV64I-NEXT:    addi a1, sp, 4
325 ; RV64I-NEXT:    add a0, a1, a0
326 ; RV64I-NEXT:    sb zero, 0(a0)
327 ; RV64I-NEXT:    mv a0, a1
328 ; RV64I-NEXT:    call snork@plt
329 ; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
330 ; RV64I-NEXT:    addi sp, sp, 16
331 ; RV64I-NEXT:    ret
333   %tmp = alloca %struct.quux, align 8
334   %tmp1 = getelementptr inbounds %struct.quux, ptr %tmp, i64 0, i32 1
335   %tmp2 = getelementptr inbounds %struct.quux, ptr %tmp, i64 0, i32 1, i64 %arg
336   store i8 0, ptr %tmp2, align 1
337   call void @snork(ptr %tmp1)
338   ret void
341 declare void @snork(ptr)