1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck -check-prefix=RV32I %s
4 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -code-model=medium < %s \
5 ; RUN: | FileCheck -check-prefix=RV32I-MEDIUM %s
6 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefix=RV64I %s
8 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -code-model=medium < %s \
9 ; RUN: | FileCheck -check-prefix=RV64I-MEDIUM %s
10 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -code-model=large < %s \
11 ; RUN: | FileCheck -check-prefix=RV64I-LARGE %s
13 ; We can often fold an ADDI into the offset of load/store instructions:
14 ; (load (addi base, off1), off2) -> (load base, off1+off2)
15 ; (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
16 ; This is possible when the off1+off2 continues to fit the 12-bit immediate.
17 ; Check if we do the fold under various conditions. If off1 is (the low part of)
18 ; an address the fold's safety depends on the variable's alignment.
20 @g_0 = dso_local global i64 0
21 @g_1 = dso_local global i64 0, align 1
22 @g_2 = dso_local global i64 0, align 2
23 @g_4 = dso_local global i64 0, align 4
24 @g_8 = dso_local global i64 0, align 8
25 @g_16 = dso_local global i64 0, align 16
27 define dso_local i64 @load_g_0() nounwind {
28 ; RV32I-LABEL: load_g_0:
29 ; RV32I: # %bb.0: # %entry
30 ; RV32I-NEXT: lui a1, %hi(g_0)
31 ; RV32I-NEXT: lw a0, %lo(g_0)(a1)
32 ; RV32I-NEXT: lw a1, %lo(g_0+4)(a1)
35 ; RV32I-MEDIUM-LABEL: load_g_0:
36 ; RV32I-MEDIUM: # %bb.0: # %entry
37 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi0:
38 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_0)
39 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi0)
40 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
41 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
42 ; RV32I-MEDIUM-NEXT: ret
44 ; RV64I-LABEL: load_g_0:
45 ; RV64I: # %bb.0: # %entry
46 ; RV64I-NEXT: lui a0, %hi(g_0)
47 ; RV64I-NEXT: ld a0, %lo(g_0)(a0)
50 ; RV64I-MEDIUM-LABEL: load_g_0:
51 ; RV64I-MEDIUM: # %bb.0: # %entry
52 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi0:
53 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_0)
54 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi0)(a0)
55 ; RV64I-MEDIUM-NEXT: ret
57 ; RV64I-LARGE-LABEL: load_g_0:
58 ; RV64I-LARGE: # %bb.0: # %entry
59 ; RV64I-LARGE-NEXT: .Lpcrel_hi0:
60 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI0_0)
61 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi0)(a0)
62 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
63 ; RV64I-LARGE-NEXT: ret
65 %0 = load i64, ptr @g_0
69 define dso_local i64 @load_g_1() nounwind {
70 ; RV32I-LABEL: load_g_1:
71 ; RV32I: # %bb.0: # %entry
72 ; RV32I-NEXT: lui a1, %hi(g_1)
73 ; RV32I-NEXT: lw a0, %lo(g_1)(a1)
74 ; RV32I-NEXT: addi a1, a1, %lo(g_1)
75 ; RV32I-NEXT: lw a1, 4(a1)
78 ; RV32I-MEDIUM-LABEL: load_g_1:
79 ; RV32I-MEDIUM: # %bb.0: # %entry
80 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi1:
81 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_1)
82 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi1)
83 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
84 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
85 ; RV32I-MEDIUM-NEXT: ret
87 ; RV64I-LABEL: load_g_1:
88 ; RV64I: # %bb.0: # %entry
89 ; RV64I-NEXT: lui a0, %hi(g_1)
90 ; RV64I-NEXT: ld a0, %lo(g_1)(a0)
93 ; RV64I-MEDIUM-LABEL: load_g_1:
94 ; RV64I-MEDIUM: # %bb.0: # %entry
95 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi1:
96 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_1)
97 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi1)(a0)
98 ; RV64I-MEDIUM-NEXT: ret
100 ; RV64I-LARGE-LABEL: load_g_1:
101 ; RV64I-LARGE: # %bb.0: # %entry
102 ; RV64I-LARGE-NEXT: .Lpcrel_hi1:
103 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI1_0)
104 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi1)(a0)
105 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
106 ; RV64I-LARGE-NEXT: ret
108 %0 = load i64, ptr @g_1
112 define dso_local i64 @load_g_2() nounwind {
113 ; RV32I-LABEL: load_g_2:
114 ; RV32I: # %bb.0: # %entry
115 ; RV32I-NEXT: lui a1, %hi(g_2)
116 ; RV32I-NEXT: lw a0, %lo(g_2)(a1)
117 ; RV32I-NEXT: addi a1, a1, %lo(g_2)
118 ; RV32I-NEXT: lw a1, 4(a1)
121 ; RV32I-MEDIUM-LABEL: load_g_2:
122 ; RV32I-MEDIUM: # %bb.0: # %entry
123 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi2:
124 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_2)
125 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi2)
126 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
127 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
128 ; RV32I-MEDIUM-NEXT: ret
130 ; RV64I-LABEL: load_g_2:
131 ; RV64I: # %bb.0: # %entry
132 ; RV64I-NEXT: lui a0, %hi(g_2)
133 ; RV64I-NEXT: ld a0, %lo(g_2)(a0)
136 ; RV64I-MEDIUM-LABEL: load_g_2:
137 ; RV64I-MEDIUM: # %bb.0: # %entry
138 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi2:
139 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_2)
140 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi2)(a0)
141 ; RV64I-MEDIUM-NEXT: ret
143 ; RV64I-LARGE-LABEL: load_g_2:
144 ; RV64I-LARGE: # %bb.0: # %entry
145 ; RV64I-LARGE-NEXT: .Lpcrel_hi2:
146 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI2_0)
147 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi2)(a0)
148 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
149 ; RV64I-LARGE-NEXT: ret
151 %0 = load i64, ptr @g_2
155 define dso_local i64 @load_g_4() nounwind {
156 ; RV32I-LABEL: load_g_4:
157 ; RV32I: # %bb.0: # %entry
158 ; RV32I-NEXT: lui a1, %hi(g_4)
159 ; RV32I-NEXT: lw a0, %lo(g_4)(a1)
160 ; RV32I-NEXT: addi a1, a1, %lo(g_4)
161 ; RV32I-NEXT: lw a1, 4(a1)
164 ; RV32I-MEDIUM-LABEL: load_g_4:
165 ; RV32I-MEDIUM: # %bb.0: # %entry
166 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi3:
167 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4)
168 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi3)
169 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
170 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
171 ; RV32I-MEDIUM-NEXT: ret
173 ; RV64I-LABEL: load_g_4:
174 ; RV64I: # %bb.0: # %entry
175 ; RV64I-NEXT: lui a0, %hi(g_4)
176 ; RV64I-NEXT: ld a0, %lo(g_4)(a0)
179 ; RV64I-MEDIUM-LABEL: load_g_4:
180 ; RV64I-MEDIUM: # %bb.0: # %entry
181 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi3:
182 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4)
183 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi3)(a0)
184 ; RV64I-MEDIUM-NEXT: ret
186 ; RV64I-LARGE-LABEL: load_g_4:
187 ; RV64I-LARGE: # %bb.0: # %entry
188 ; RV64I-LARGE-NEXT: .Lpcrel_hi3:
189 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI3_0)
190 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi3)(a0)
191 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
192 ; RV64I-LARGE-NEXT: ret
194 %0 = load i64, ptr @g_4
198 define dso_local i64 @load_g_8() nounwind {
199 ; RV32I-LABEL: load_g_8:
200 ; RV32I: # %bb.0: # %entry
201 ; RV32I-NEXT: lui a1, %hi(g_8)
202 ; RV32I-NEXT: lw a0, %lo(g_8)(a1)
203 ; RV32I-NEXT: lw a1, %lo(g_8+4)(a1)
206 ; RV32I-MEDIUM-LABEL: load_g_8:
207 ; RV32I-MEDIUM: # %bb.0: # %entry
208 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi4:
209 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8)
210 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi4)
211 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
212 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
213 ; RV32I-MEDIUM-NEXT: ret
215 ; RV64I-LABEL: load_g_8:
216 ; RV64I: # %bb.0: # %entry
217 ; RV64I-NEXT: lui a0, %hi(g_8)
218 ; RV64I-NEXT: ld a0, %lo(g_8)(a0)
221 ; RV64I-MEDIUM-LABEL: load_g_8:
222 ; RV64I-MEDIUM: # %bb.0: # %entry
223 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi4:
224 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8)
225 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi4)(a0)
226 ; RV64I-MEDIUM-NEXT: ret
228 ; RV64I-LARGE-LABEL: load_g_8:
229 ; RV64I-LARGE: # %bb.0: # %entry
230 ; RV64I-LARGE-NEXT: .Lpcrel_hi4:
231 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI4_0)
232 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi4)(a0)
233 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
234 ; RV64I-LARGE-NEXT: ret
236 %0 = load i64, ptr @g_8
240 define dso_local i64 @load_g_16() nounwind {
241 ; RV32I-LABEL: load_g_16:
242 ; RV32I: # %bb.0: # %entry
243 ; RV32I-NEXT: lui a1, %hi(g_16)
244 ; RV32I-NEXT: lw a0, %lo(g_16)(a1)
245 ; RV32I-NEXT: lw a1, %lo(g_16+4)(a1)
248 ; RV32I-MEDIUM-LABEL: load_g_16:
249 ; RV32I-MEDIUM: # %bb.0: # %entry
250 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi5:
251 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_16)
252 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi5)
253 ; RV32I-MEDIUM-NEXT: lw a0, 0(a1)
254 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
255 ; RV32I-MEDIUM-NEXT: ret
257 ; RV64I-LABEL: load_g_16:
258 ; RV64I: # %bb.0: # %entry
259 ; RV64I-NEXT: lui a0, %hi(g_16)
260 ; RV64I-NEXT: ld a0, %lo(g_16)(a0)
263 ; RV64I-MEDIUM-LABEL: load_g_16:
264 ; RV64I-MEDIUM: # %bb.0: # %entry
265 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi5:
266 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_16)
267 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0)
268 ; RV64I-MEDIUM-NEXT: ret
270 ; RV64I-LARGE-LABEL: load_g_16:
271 ; RV64I-LARGE: # %bb.0: # %entry
272 ; RV64I-LARGE-NEXT: .Lpcrel_hi5:
273 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI5_0)
274 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0)
275 ; RV64I-LARGE-NEXT: ld a0, 0(a0)
276 ; RV64I-LARGE-NEXT: ret
278 %0 = load i64, ptr @g_16
282 define dso_local void @store_g_4() nounwind {
283 ; RV32I-LABEL: store_g_4:
284 ; RV32I: # %bb.0: # %entry
285 ; RV32I-NEXT: lui a0, %hi(g_4)
286 ; RV32I-NEXT: sw zero, %lo(g_4)(a0)
287 ; RV32I-NEXT: addi a0, a0, %lo(g_4)
288 ; RV32I-NEXT: sw zero, 4(a0)
291 ; RV32I-MEDIUM-LABEL: store_g_4:
292 ; RV32I-MEDIUM: # %bb.0: # %entry
293 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi6:
294 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4)
295 ; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6)
296 ; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
297 ; RV32I-MEDIUM-NEXT: sw zero, 4(a0)
298 ; RV32I-MEDIUM-NEXT: ret
300 ; RV64I-LABEL: store_g_4:
301 ; RV64I: # %bb.0: # %entry
302 ; RV64I-NEXT: lui a0, %hi(g_4)
303 ; RV64I-NEXT: sd zero, %lo(g_4)(a0)
306 ; RV64I-MEDIUM-LABEL: store_g_4:
307 ; RV64I-MEDIUM: # %bb.0: # %entry
308 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi6:
309 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4)
310 ; RV64I-MEDIUM-NEXT: sd zero, %pcrel_lo(.Lpcrel_hi6)(a0)
311 ; RV64I-MEDIUM-NEXT: ret
313 ; RV64I-LARGE-LABEL: store_g_4:
314 ; RV64I-LARGE: # %bb.0: # %entry
315 ; RV64I-LARGE-NEXT: .Lpcrel_hi6:
316 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI6_0)
317 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi6)(a0)
318 ; RV64I-LARGE-NEXT: sd zero, 0(a0)
319 ; RV64I-LARGE-NEXT: ret
321 store i64 0, ptr @g_4
325 define dso_local void @store_g_8() nounwind {
326 ; RV32I-LABEL: store_g_8:
327 ; RV32I: # %bb.0: # %entry
328 ; RV32I-NEXT: lui a0, %hi(g_8)
329 ; RV32I-NEXT: sw zero, %lo(g_8+4)(a0)
330 ; RV32I-NEXT: sw zero, %lo(g_8)(a0)
333 ; RV32I-MEDIUM-LABEL: store_g_8:
334 ; RV32I-MEDIUM: # %bb.0: # %entry
335 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi7:
336 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8)
337 ; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7)
338 ; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
339 ; RV32I-MEDIUM-NEXT: sw zero, 4(a0)
340 ; RV32I-MEDIUM-NEXT: ret
342 ; RV64I-LABEL: store_g_8:
343 ; RV64I: # %bb.0: # %entry
344 ; RV64I-NEXT: lui a0, %hi(g_8)
345 ; RV64I-NEXT: sd zero, %lo(g_8)(a0)
348 ; RV64I-MEDIUM-LABEL: store_g_8:
349 ; RV64I-MEDIUM: # %bb.0: # %entry
350 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi7:
351 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8)
352 ; RV64I-MEDIUM-NEXT: sd zero, %pcrel_lo(.Lpcrel_hi7)(a0)
353 ; RV64I-MEDIUM-NEXT: ret
355 ; RV64I-LARGE-LABEL: store_g_8:
356 ; RV64I-LARGE: # %bb.0: # %entry
357 ; RV64I-LARGE-NEXT: .Lpcrel_hi7:
358 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI7_0)
359 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi7)(a0)
360 ; RV64I-LARGE-NEXT: sd zero, 0(a0)
361 ; RV64I-LARGE-NEXT: ret
363 store i64 0, ptr @g_8
367 ; Check if we can fold ADDI into the offset of store instructions,
368 ; when store instructions is the root node in DAG.
370 @g_4_i32 = global i32 0, align 4
372 define dso_local void @inc_g_i32() nounwind {
373 ; RV32I-LABEL: inc_g_i32:
374 ; RV32I: # %bb.0: # %entry
375 ; RV32I-NEXT: lui a0, %hi(g_4_i32)
376 ; RV32I-NEXT: lw a1, %lo(g_4_i32)(a0)
377 ; RV32I-NEXT: addi a1, a1, 1
378 ; RV32I-NEXT: sw a1, %lo(g_4_i32)(a0)
381 ; RV32I-MEDIUM-LABEL: inc_g_i32:
382 ; RV32I-MEDIUM: # %bb.0: # %entry
383 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi8:
384 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32)
385 ; RV32I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
386 ; RV32I-MEDIUM-NEXT: addi a1, a1, 1
387 ; RV32I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
388 ; RV32I-MEDIUM-NEXT: ret
390 ; RV64I-LABEL: inc_g_i32:
391 ; RV64I: # %bb.0: # %entry
392 ; RV64I-NEXT: lui a0, %hi(g_4_i32)
393 ; RV64I-NEXT: lw a1, %lo(g_4_i32)(a0)
394 ; RV64I-NEXT: addi a1, a1, 1
395 ; RV64I-NEXT: sw a1, %lo(g_4_i32)(a0)
398 ; RV64I-MEDIUM-LABEL: inc_g_i32:
399 ; RV64I-MEDIUM: # %bb.0: # %entry
400 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi8:
401 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32)
402 ; RV64I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
403 ; RV64I-MEDIUM-NEXT: addi a1, a1, 1
404 ; RV64I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
405 ; RV64I-MEDIUM-NEXT: ret
407 ; RV64I-LARGE-LABEL: inc_g_i32:
408 ; RV64I-LARGE: # %bb.0: # %entry
409 ; RV64I-LARGE-NEXT: .Lpcrel_hi8:
410 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI8_0)
411 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi8)(a0)
412 ; RV64I-LARGE-NEXT: lw a1, 0(a0)
413 ; RV64I-LARGE-NEXT: addi a1, a1, 1
414 ; RV64I-LARGE-NEXT: sw a1, 0(a0)
415 ; RV64I-LARGE-NEXT: ret
417 %0 = load i32, ptr @g_4_i32
419 store i32 %inc, ptr @g_4_i32
426 ; Check for folds in accesses to elements of an i32 array.
428 @ga = dso_local local_unnamed_addr global [2 x i32] zeroinitializer, align 4
430 define dso_local i32 @load_ga() local_unnamed_addr #0 {
431 ; RV32I-LABEL: load_ga:
433 ; RV32I-NEXT: lui a0, %hi(ga+4)
434 ; RV32I-NEXT: lw a0, %lo(ga+4)(a0)
437 ; RV32I-MEDIUM-LABEL: load_ga:
438 ; RV32I-MEDIUM: # %bb.0:
439 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi9:
440 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga+4)
441 ; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi9)(a0)
442 ; RV32I-MEDIUM-NEXT: ret
444 ; RV64I-LABEL: load_ga:
446 ; RV64I-NEXT: lui a0, %hi(ga+4)
447 ; RV64I-NEXT: lw a0, %lo(ga+4)(a0)
450 ; RV64I-MEDIUM-LABEL: load_ga:
451 ; RV64I-MEDIUM: # %bb.0:
452 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi9:
453 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga+4)
454 ; RV64I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi9)(a0)
455 ; RV64I-MEDIUM-NEXT: ret
457 ; RV64I-LARGE-LABEL: load_ga:
458 ; RV64I-LARGE: # %bb.0:
459 ; RV64I-LARGE-NEXT: .Lpcrel_hi9:
460 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI9_0)
461 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi9)(a0)
462 ; RV64I-LARGE-NEXT: lw a0, 4(a0)
463 ; RV64I-LARGE-NEXT: ret
464 %1 = load i32, ptr getelementptr inbounds ([2 x i32], ptr @ga, i32 0, i32 1), align 4
468 ; Check for folds in accesses to the second element of an i64 array.
470 @ga_8 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 8
471 @ga_16 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 16
473 define dso_local i64 @load_ga_8() nounwind {
474 ; RV32I-LABEL: load_ga_8:
475 ; RV32I: # %bb.0: # %entry
476 ; RV32I-NEXT: lui a1, %hi(ga_8)
477 ; RV32I-NEXT: addi a1, a1, %lo(ga_8)
478 ; RV32I-NEXT: lw a0, 8(a1)
479 ; RV32I-NEXT: lw a1, 12(a1)
482 ; RV32I-MEDIUM-LABEL: load_ga_8:
483 ; RV32I-MEDIUM: # %bb.0: # %entry
484 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi10:
485 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_8)
486 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi10)
487 ; RV32I-MEDIUM-NEXT: lw a0, 8(a1)
488 ; RV32I-MEDIUM-NEXT: lw a1, 12(a1)
489 ; RV32I-MEDIUM-NEXT: ret
491 ; RV64I-LABEL: load_ga_8:
492 ; RV64I: # %bb.0: # %entry
493 ; RV64I-NEXT: lui a0, %hi(ga_8+8)
494 ; RV64I-NEXT: ld a0, %lo(ga_8+8)(a0)
497 ; RV64I-MEDIUM-LABEL: load_ga_8:
498 ; RV64I-MEDIUM: # %bb.0: # %entry
499 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi10:
500 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_8+8)
501 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0)
502 ; RV64I-MEDIUM-NEXT: ret
504 ; RV64I-LARGE-LABEL: load_ga_8:
505 ; RV64I-LARGE: # %bb.0: # %entry
506 ; RV64I-LARGE-NEXT: .Lpcrel_hi10:
507 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI10_0)
508 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0)
509 ; RV64I-LARGE-NEXT: ld a0, 8(a0)
510 ; RV64I-LARGE-NEXT: ret
512 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_8, i32 0, i32 1)
516 define dso_local i64 @load_ga_16() nounwind {
517 ; RV32I-LABEL: load_ga_16:
518 ; RV32I: # %bb.0: # %entry
519 ; RV32I-NEXT: lui a1, %hi(ga_16)
520 ; RV32I-NEXT: lw a0, %lo(ga_16+8)(a1)
521 ; RV32I-NEXT: lw a1, %lo(ga_16+12)(a1)
524 ; RV32I-MEDIUM-LABEL: load_ga_16:
525 ; RV32I-MEDIUM: # %bb.0: # %entry
526 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi11:
527 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_16)
528 ; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi11)
529 ; RV32I-MEDIUM-NEXT: lw a0, 8(a1)
530 ; RV32I-MEDIUM-NEXT: lw a1, 12(a1)
531 ; RV32I-MEDIUM-NEXT: ret
533 ; RV64I-LABEL: load_ga_16:
534 ; RV64I: # %bb.0: # %entry
535 ; RV64I-NEXT: lui a0, %hi(ga_16)
536 ; RV64I-NEXT: ld a0, %lo(ga_16+8)(a0)
539 ; RV64I-MEDIUM-LABEL: load_ga_16:
540 ; RV64I-MEDIUM: # %bb.0: # %entry
541 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi11:
542 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_16+8)
543 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0)
544 ; RV64I-MEDIUM-NEXT: ret
546 ; RV64I-LARGE-LABEL: load_ga_16:
547 ; RV64I-LARGE: # %bb.0: # %entry
548 ; RV64I-LARGE-NEXT: .Lpcrel_hi11:
549 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI11_0)
550 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0)
551 ; RV64I-LARGE-NEXT: ld a0, 8(a0)
552 ; RV64I-LARGE-NEXT: ret
554 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_16, i32 0, i32 1)
558 ; Check for folds in accesses to block address.
559 define dso_local ptr @load_ba_1() nounwind {
560 ; RV32I-LABEL: load_ba_1:
561 ; RV32I: # %bb.0: # %entry
562 ; RV32I-NEXT: .Ltmp0: # Block address taken
563 ; RV32I-NEXT: # %bb.1: # %label
564 ; RV32I-NEXT: lui a0, %hi(.Ltmp0)
565 ; RV32I-NEXT: lw a0, %lo(.Ltmp0)(a0)
568 ; RV32I-MEDIUM-LABEL: load_ba_1:
569 ; RV32I-MEDIUM: # %bb.0: # %entry
570 ; RV32I-MEDIUM-NEXT: .Ltmp0: # Block address taken
571 ; RV32I-MEDIUM-NEXT: # %bb.1: # %label
572 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi12:
573 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp0)
574 ; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi12)(a0)
575 ; RV32I-MEDIUM-NEXT: ret
577 ; RV64I-LABEL: load_ba_1:
578 ; RV64I: # %bb.0: # %entry
579 ; RV64I-NEXT: .Ltmp0: # Block address taken
580 ; RV64I-NEXT: # %bb.1: # %label
581 ; RV64I-NEXT: lui a0, %hi(.Ltmp0)
582 ; RV64I-NEXT: ld a0, %lo(.Ltmp0)(a0)
585 ; RV64I-MEDIUM-LABEL: load_ba_1:
586 ; RV64I-MEDIUM: # %bb.0: # %entry
587 ; RV64I-MEDIUM-NEXT: .Ltmp0: # Block address taken
588 ; RV64I-MEDIUM-NEXT: # %bb.1: # %label
589 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi12:
590 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp0)
591 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi12)(a0)
592 ; RV64I-MEDIUM-NEXT: ret
594 ; RV64I-LARGE-LABEL: load_ba_1:
595 ; RV64I-LARGE: # %bb.0: # %entry
596 ; RV64I-LARGE-NEXT: .Ltmp0: # Block address taken
597 ; RV64I-LARGE-NEXT: # %bb.1: # %label
598 ; RV64I-LARGE-NEXT: .Lpcrel_hi12:
599 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.Ltmp0)
600 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi12)(a0)
601 ; RV64I-LARGE-NEXT: ret
605 %0 = load ptr, ptr blockaddress(@load_ba_1, %label)
609 define dso_local ptr @load_ba_2() nounwind {
610 ; RV32I-LABEL: load_ba_2:
611 ; RV32I: # %bb.0: # %entry
612 ; RV32I-NEXT: .Ltmp1: # Block address taken
613 ; RV32I-NEXT: # %bb.1: # %label
614 ; RV32I-NEXT: lui a0, %hi(.Ltmp1+8)
615 ; RV32I-NEXT: lw a0, %lo(.Ltmp1+8)(a0)
618 ; RV32I-MEDIUM-LABEL: load_ba_2:
619 ; RV32I-MEDIUM: # %bb.0: # %entry
620 ; RV32I-MEDIUM-NEXT: .Ltmp1: # Block address taken
621 ; RV32I-MEDIUM-NEXT: # %bb.1: # %label
622 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi13:
623 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8)
624 ; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi13)(a0)
625 ; RV32I-MEDIUM-NEXT: ret
627 ; RV64I-LABEL: load_ba_2:
628 ; RV64I: # %bb.0: # %entry
629 ; RV64I-NEXT: .Ltmp1: # Block address taken
630 ; RV64I-NEXT: # %bb.1: # %label
631 ; RV64I-NEXT: lui a0, %hi(.Ltmp1+8)
632 ; RV64I-NEXT: ld a0, %lo(.Ltmp1+8)(a0)
635 ; RV64I-MEDIUM-LABEL: load_ba_2:
636 ; RV64I-MEDIUM: # %bb.0: # %entry
637 ; RV64I-MEDIUM-NEXT: .Ltmp1: # Block address taken
638 ; RV64I-MEDIUM-NEXT: # %bb.1: # %label
639 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi13:
640 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8)
641 ; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi13)(a0)
642 ; RV64I-MEDIUM-NEXT: ret
644 ; RV64I-LARGE-LABEL: load_ba_2:
645 ; RV64I-LARGE: # %bb.0: # %entry
646 ; RV64I-LARGE-NEXT: .Ltmp1: # Block address taken
647 ; RV64I-LARGE-NEXT: # %bb.1: # %label
648 ; RV64I-LARGE-NEXT: .Lpcrel_hi13:
649 ; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8)
650 ; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi13)(a0)
651 ; RV64I-LARGE-NEXT: ret
655 %0 = load ptr, ptr getelementptr inbounds (i8, ptr blockaddress(@load_ba_2, %label), i32 8)
659 ; Check for folds in accesses to thread-local variables.
661 @tl_4 = dso_local thread_local global i64 0, align 4
662 @tl_8 = dso_local thread_local global i64 0, align 8
664 define dso_local i64 @load_tl_4() nounwind {
665 ; RV32I-LABEL: load_tl_4:
666 ; RV32I: # %bb.0: # %entry
667 ; RV32I-NEXT: lui a0, %tprel_hi(tl_4)
668 ; RV32I-NEXT: add a1, a0, tp, %tprel_add(tl_4)
669 ; RV32I-NEXT: lw a0, %tprel_lo(tl_4)(a1)
670 ; RV32I-NEXT: addi a1, a1, %tprel_lo(tl_4)
671 ; RV32I-NEXT: lw a1, 4(a1)
674 ; RV32I-MEDIUM-LABEL: load_tl_4:
675 ; RV32I-MEDIUM: # %bb.0: # %entry
676 ; RV32I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_4)
677 ; RV32I-MEDIUM-NEXT: add a1, a0, tp, %tprel_add(tl_4)
678 ; RV32I-MEDIUM-NEXT: lw a0, %tprel_lo(tl_4)(a1)
679 ; RV32I-MEDIUM-NEXT: addi a1, a1, %tprel_lo(tl_4)
680 ; RV32I-MEDIUM-NEXT: lw a1, 4(a1)
681 ; RV32I-MEDIUM-NEXT: ret
683 ; RV64I-LABEL: load_tl_4:
684 ; RV64I: # %bb.0: # %entry
685 ; RV64I-NEXT: lui a0, %tprel_hi(tl_4)
686 ; RV64I-NEXT: add a0, a0, tp, %tprel_add(tl_4)
687 ; RV64I-NEXT: ld a0, %tprel_lo(tl_4)(a0)
690 ; RV64I-MEDIUM-LABEL: load_tl_4:
691 ; RV64I-MEDIUM: # %bb.0: # %entry
692 ; RV64I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_4)
693 ; RV64I-MEDIUM-NEXT: add a0, a0, tp, %tprel_add(tl_4)
694 ; RV64I-MEDIUM-NEXT: ld a0, %tprel_lo(tl_4)(a0)
695 ; RV64I-MEDIUM-NEXT: ret
697 ; RV64I-LARGE-LABEL: load_tl_4:
698 ; RV64I-LARGE: # %bb.0: # %entry
699 ; RV64I-LARGE-NEXT: lui a0, %tprel_hi(tl_4)
700 ; RV64I-LARGE-NEXT: add a0, a0, tp, %tprel_add(tl_4)
701 ; RV64I-LARGE-NEXT: ld a0, %tprel_lo(tl_4)(a0)
702 ; RV64I-LARGE-NEXT: ret
704 %0 = load i64, ptr @tl_4
708 define dso_local i64 @load_tl_8() nounwind {
709 ; RV32I-LABEL: load_tl_8:
710 ; RV32I: # %bb.0: # %entry
711 ; RV32I-NEXT: lui a0, %tprel_hi(tl_8)
712 ; RV32I-NEXT: add a1, a0, tp, %tprel_add(tl_8)
713 ; RV32I-NEXT: lw a0, %tprel_lo(tl_8)(a1)
714 ; RV32I-NEXT: lw a1, %tprel_lo(tl_8+4)(a1)
717 ; RV32I-MEDIUM-LABEL: load_tl_8:
718 ; RV32I-MEDIUM: # %bb.0: # %entry
719 ; RV32I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_8)
720 ; RV32I-MEDIUM-NEXT: add a1, a0, tp, %tprel_add(tl_8)
721 ; RV32I-MEDIUM-NEXT: lw a0, %tprel_lo(tl_8)(a1)
722 ; RV32I-MEDIUM-NEXT: lw a1, %tprel_lo(tl_8+4)(a1)
723 ; RV32I-MEDIUM-NEXT: ret
725 ; RV64I-LABEL: load_tl_8:
726 ; RV64I: # %bb.0: # %entry
727 ; RV64I-NEXT: lui a0, %tprel_hi(tl_8)
728 ; RV64I-NEXT: add a0, a0, tp, %tprel_add(tl_8)
729 ; RV64I-NEXT: ld a0, %tprel_lo(tl_8)(a0)
732 ; RV64I-MEDIUM-LABEL: load_tl_8:
733 ; RV64I-MEDIUM: # %bb.0: # %entry
734 ; RV64I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_8)
735 ; RV64I-MEDIUM-NEXT: add a0, a0, tp, %tprel_add(tl_8)
736 ; RV64I-MEDIUM-NEXT: ld a0, %tprel_lo(tl_8)(a0)
737 ; RV64I-MEDIUM-NEXT: ret
739 ; RV64I-LARGE-LABEL: load_tl_8:
740 ; RV64I-LARGE: # %bb.0: # %entry
741 ; RV64I-LARGE-NEXT: lui a0, %tprel_hi(tl_8)
742 ; RV64I-LARGE-NEXT: add a0, a0, tp, %tprel_add(tl_8)
743 ; RV64I-LARGE-NEXT: ld a0, %tprel_lo(tl_8)(a0)
744 ; RV64I-LARGE-NEXT: ret
746 %0 = load i64, ptr @tl_8
750 define dso_local i64 @load_const_ok() nounwind {
751 ; RV32I-LABEL: load_const_ok:
752 ; RV32I: # %bb.0: # %entry
753 ; RV32I-NEXT: lw a0, 2040(zero)
754 ; RV32I-NEXT: lw a1, 2044(zero)
757 ; RV32I-MEDIUM-LABEL: load_const_ok:
758 ; RV32I-MEDIUM: # %bb.0: # %entry
759 ; RV32I-MEDIUM-NEXT: lw a0, 2040(zero)
760 ; RV32I-MEDIUM-NEXT: lw a1, 2044(zero)
761 ; RV32I-MEDIUM-NEXT: ret
763 ; RV64I-LABEL: load_const_ok:
764 ; RV64I: # %bb.0: # %entry
765 ; RV64I-NEXT: ld a0, 2040(zero)
768 ; RV64I-MEDIUM-LABEL: load_const_ok:
769 ; RV64I-MEDIUM: # %bb.0: # %entry
770 ; RV64I-MEDIUM-NEXT: ld a0, 2040(zero)
771 ; RV64I-MEDIUM-NEXT: ret
773 ; RV64I-LARGE-LABEL: load_const_ok:
774 ; RV64I-LARGE: # %bb.0: # %entry
775 ; RV64I-LARGE-NEXT: ld a0, 2040(zero)
776 ; RV64I-LARGE-NEXT: ret
778 %0 = load i64, ptr inttoptr (i32 2040 to ptr)
782 define dso_local i64 @load_cost_overflow() nounwind {
783 ; RV32I-LABEL: load_cost_overflow:
784 ; RV32I: # %bb.0: # %entry
785 ; RV32I-NEXT: lui a0, 1
786 ; RV32I-NEXT: lw a1, -2048(a0)
787 ; RV32I-NEXT: lw a0, 2044(zero)
790 ; RV32I-MEDIUM-LABEL: load_cost_overflow:
791 ; RV32I-MEDIUM: # %bb.0: # %entry
792 ; RV32I-MEDIUM-NEXT: lui a0, 1
793 ; RV32I-MEDIUM-NEXT: lw a1, -2048(a0)
794 ; RV32I-MEDIUM-NEXT: lw a0, 2044(zero)
795 ; RV32I-MEDIUM-NEXT: ret
797 ; RV64I-LABEL: load_cost_overflow:
798 ; RV64I: # %bb.0: # %entry
799 ; RV64I-NEXT: ld a0, 2044(zero)
802 ; RV64I-MEDIUM-LABEL: load_cost_overflow:
803 ; RV64I-MEDIUM: # %bb.0: # %entry
804 ; RV64I-MEDIUM-NEXT: ld a0, 2044(zero)
805 ; RV64I-MEDIUM-NEXT: ret
807 ; RV64I-LARGE-LABEL: load_cost_overflow:
808 ; RV64I-LARGE: # %bb.0: # %entry
809 ; RV64I-LARGE-NEXT: ld a0, 2044(zero)
810 ; RV64I-LARGE-NEXT: ret
812 %0 = load i64, ptr inttoptr (i64 2044 to ptr)
816 define dso_local i32 @load_const_medium() nounwind {
817 ; RV32I-LABEL: load_const_medium:
818 ; RV32I: # %bb.0: # %entry
819 ; RV32I-NEXT: lui a0, 1
820 ; RV32I-NEXT: lw a0, -16(a0)
823 ; RV32I-MEDIUM-LABEL: load_const_medium:
824 ; RV32I-MEDIUM: # %bb.0: # %entry
825 ; RV32I-MEDIUM-NEXT: lui a0, 1
826 ; RV32I-MEDIUM-NEXT: lw a0, -16(a0)
827 ; RV32I-MEDIUM-NEXT: ret
829 ; RV64I-LABEL: load_const_medium:
830 ; RV64I: # %bb.0: # %entry
831 ; RV64I-NEXT: lui a0, 1
832 ; RV64I-NEXT: lw a0, -16(a0)
835 ; RV64I-MEDIUM-LABEL: load_const_medium:
836 ; RV64I-MEDIUM: # %bb.0: # %entry
837 ; RV64I-MEDIUM-NEXT: lui a0, 1
838 ; RV64I-MEDIUM-NEXT: lw a0, -16(a0)
839 ; RV64I-MEDIUM-NEXT: ret
841 ; RV64I-LARGE-LABEL: load_const_medium:
842 ; RV64I-LARGE: # %bb.0: # %entry
843 ; RV64I-LARGE-NEXT: lui a0, 1
844 ; RV64I-LARGE-NEXT: lw a0, -16(a0)
845 ; RV64I-LARGE-NEXT: ret
847 %0 = load i32, ptr inttoptr (i64 4080 to ptr)
851 ; The constant here is 0x7ffff800, this value requires LUI+ADDIW on RV64,
852 ; LUI+ADDI would produce a different constant so we can't fold into the load
854 define dso_local i32 @load_const_large() nounwind {
855 ; RV32I-LABEL: load_const_large:
856 ; RV32I: # %bb.0: # %entry
857 ; RV32I-NEXT: lui a0, 524288
858 ; RV32I-NEXT: lw a0, -2048(a0)
861 ; RV32I-MEDIUM-LABEL: load_const_large:
862 ; RV32I-MEDIUM: # %bb.0: # %entry
863 ; RV32I-MEDIUM-NEXT: lui a0, 524288
864 ; RV32I-MEDIUM-NEXT: lw a0, -2048(a0)
865 ; RV32I-MEDIUM-NEXT: ret
867 ; RV64I-LABEL: load_const_large:
868 ; RV64I: # %bb.0: # %entry
869 ; RV64I-NEXT: lui a0, 524288
870 ; RV64I-NEXT: addiw a0, a0, -2048
871 ; RV64I-NEXT: lw a0, 0(a0)
874 ; RV64I-MEDIUM-LABEL: load_const_large:
875 ; RV64I-MEDIUM: # %bb.0: # %entry
876 ; RV64I-MEDIUM-NEXT: lui a0, 524288
877 ; RV64I-MEDIUM-NEXT: addiw a0, a0, -2048
878 ; RV64I-MEDIUM-NEXT: lw a0, 0(a0)
879 ; RV64I-MEDIUM-NEXT: ret
881 ; RV64I-LARGE-LABEL: load_const_large:
882 ; RV64I-LARGE: # %bb.0: # %entry
883 ; RV64I-LARGE-NEXT: lui a0, 524288
884 ; RV64I-LARGE-NEXT: addiw a0, a0, -2048
885 ; RV64I-LARGE-NEXT: lw a0, 0(a0)
886 ; RV64I-LARGE-NEXT: ret
888 %0 = load i32, ptr inttoptr (i64 2147481600 to ptr)
892 %struct.S = type { i64, i64 }
894 define i64 @fold_addi_from_different_bb(i64 %k, i64 %n, ptr %a) nounwind {
895 ; RV32I-LABEL: fold_addi_from_different_bb:
896 ; RV32I: # %bb.0: # %entry
897 ; RV32I-NEXT: addi sp, sp, -48
898 ; RV32I-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
899 ; RV32I-NEXT: sw s0, 40(sp) # 4-byte Folded Spill
900 ; RV32I-NEXT: sw s1, 36(sp) # 4-byte Folded Spill
901 ; RV32I-NEXT: sw s2, 32(sp) # 4-byte Folded Spill
902 ; RV32I-NEXT: sw s3, 28(sp) # 4-byte Folded Spill
903 ; RV32I-NEXT: sw s4, 24(sp) # 4-byte Folded Spill
904 ; RV32I-NEXT: sw s5, 20(sp) # 4-byte Folded Spill
905 ; RV32I-NEXT: sw s6, 16(sp) # 4-byte Folded Spill
906 ; RV32I-NEXT: sw s7, 12(sp) # 4-byte Folded Spill
907 ; RV32I-NEXT: mv s0, a4
908 ; RV32I-NEXT: mv s1, a3
909 ; RV32I-NEXT: mv s2, a2
910 ; RV32I-NEXT: beqz a3, .LBB20_3
911 ; RV32I-NEXT: # %bb.1: # %entry
912 ; RV32I-NEXT: slti a1, s1, 0
913 ; RV32I-NEXT: beqz a1, .LBB20_4
914 ; RV32I-NEXT: .LBB20_2:
915 ; RV32I-NEXT: li s3, 0
916 ; RV32I-NEXT: li s4, 0
917 ; RV32I-NEXT: j .LBB20_6
918 ; RV32I-NEXT: .LBB20_3:
919 ; RV32I-NEXT: seqz a1, s2
920 ; RV32I-NEXT: bnez a1, .LBB20_2
921 ; RV32I-NEXT: .LBB20_4: # %for.body.lr.ph
922 ; RV32I-NEXT: li s5, 0
923 ; RV32I-NEXT: li s6, 0
924 ; RV32I-NEXT: li s3, 0
925 ; RV32I-NEXT: li s4, 0
926 ; RV32I-NEXT: slli a0, a0, 4
927 ; RV32I-NEXT: add s7, s0, a0
928 ; RV32I-NEXT: .LBB20_5: # %for.body
929 ; RV32I-NEXT: # =>This Inner Loop Header: Depth=1
930 ; RV32I-NEXT: mv a0, s0
932 ; RV32I-NEXT: lw a0, 8(s7)
933 ; RV32I-NEXT: lw a1, 12(s7)
934 ; RV32I-NEXT: addi s5, s5, 1
935 ; RV32I-NEXT: seqz a2, s5
936 ; RV32I-NEXT: add s6, s6, a2
937 ; RV32I-NEXT: xor a2, s5, s2
938 ; RV32I-NEXT: add a1, a1, s4
939 ; RV32I-NEXT: xor a3, s6, s1
940 ; RV32I-NEXT: or a2, a2, a3
941 ; RV32I-NEXT: add s3, a0, s3
942 ; RV32I-NEXT: sltu s4, s3, a0
943 ; RV32I-NEXT: add s4, a1, s4
944 ; RV32I-NEXT: bnez a2, .LBB20_5
945 ; RV32I-NEXT: .LBB20_6: # %for.cond.cleanup
946 ; RV32I-NEXT: mv a0, s3
947 ; RV32I-NEXT: mv a1, s4
948 ; RV32I-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
949 ; RV32I-NEXT: lw s0, 40(sp) # 4-byte Folded Reload
950 ; RV32I-NEXT: lw s1, 36(sp) # 4-byte Folded Reload
951 ; RV32I-NEXT: lw s2, 32(sp) # 4-byte Folded Reload
952 ; RV32I-NEXT: lw s3, 28(sp) # 4-byte Folded Reload
953 ; RV32I-NEXT: lw s4, 24(sp) # 4-byte Folded Reload
954 ; RV32I-NEXT: lw s5, 20(sp) # 4-byte Folded Reload
955 ; RV32I-NEXT: lw s6, 16(sp) # 4-byte Folded Reload
956 ; RV32I-NEXT: lw s7, 12(sp) # 4-byte Folded Reload
957 ; RV32I-NEXT: addi sp, sp, 48
960 ; RV32I-MEDIUM-LABEL: fold_addi_from_different_bb:
961 ; RV32I-MEDIUM: # %bb.0: # %entry
962 ; RV32I-MEDIUM-NEXT: addi sp, sp, -48
963 ; RV32I-MEDIUM-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
964 ; RV32I-MEDIUM-NEXT: sw s0, 40(sp) # 4-byte Folded Spill
965 ; RV32I-MEDIUM-NEXT: sw s1, 36(sp) # 4-byte Folded Spill
966 ; RV32I-MEDIUM-NEXT: sw s2, 32(sp) # 4-byte Folded Spill
967 ; RV32I-MEDIUM-NEXT: sw s3, 28(sp) # 4-byte Folded Spill
968 ; RV32I-MEDIUM-NEXT: sw s4, 24(sp) # 4-byte Folded Spill
969 ; RV32I-MEDIUM-NEXT: sw s5, 20(sp) # 4-byte Folded Spill
970 ; RV32I-MEDIUM-NEXT: sw s6, 16(sp) # 4-byte Folded Spill
971 ; RV32I-MEDIUM-NEXT: sw s7, 12(sp) # 4-byte Folded Spill
972 ; RV32I-MEDIUM-NEXT: mv s0, a4
973 ; RV32I-MEDIUM-NEXT: mv s1, a3
974 ; RV32I-MEDIUM-NEXT: mv s2, a2
975 ; RV32I-MEDIUM-NEXT: beqz a3, .LBB20_3
976 ; RV32I-MEDIUM-NEXT: # %bb.1: # %entry
977 ; RV32I-MEDIUM-NEXT: slti a1, s1, 0
978 ; RV32I-MEDIUM-NEXT: beqz a1, .LBB20_4
979 ; RV32I-MEDIUM-NEXT: .LBB20_2:
980 ; RV32I-MEDIUM-NEXT: li s3, 0
981 ; RV32I-MEDIUM-NEXT: li s4, 0
982 ; RV32I-MEDIUM-NEXT: j .LBB20_6
983 ; RV32I-MEDIUM-NEXT: .LBB20_3:
984 ; RV32I-MEDIUM-NEXT: seqz a1, s2
985 ; RV32I-MEDIUM-NEXT: bnez a1, .LBB20_2
986 ; RV32I-MEDIUM-NEXT: .LBB20_4: # %for.body.lr.ph
987 ; RV32I-MEDIUM-NEXT: li s5, 0
988 ; RV32I-MEDIUM-NEXT: li s6, 0
989 ; RV32I-MEDIUM-NEXT: li s3, 0
990 ; RV32I-MEDIUM-NEXT: li s4, 0
991 ; RV32I-MEDIUM-NEXT: slli a0, a0, 4
992 ; RV32I-MEDIUM-NEXT: add s7, s0, a0
993 ; RV32I-MEDIUM-NEXT: .LBB20_5: # %for.body
994 ; RV32I-MEDIUM-NEXT: # =>This Inner Loop Header: Depth=1
995 ; RV32I-MEDIUM-NEXT: mv a0, s0
996 ; RV32I-MEDIUM-NEXT: call f
997 ; RV32I-MEDIUM-NEXT: lw a0, 8(s7)
998 ; RV32I-MEDIUM-NEXT: lw a1, 12(s7)
999 ; RV32I-MEDIUM-NEXT: addi s5, s5, 1
1000 ; RV32I-MEDIUM-NEXT: seqz a2, s5
1001 ; RV32I-MEDIUM-NEXT: add s6, s6, a2
1002 ; RV32I-MEDIUM-NEXT: xor a2, s5, s2
1003 ; RV32I-MEDIUM-NEXT: add a1, a1, s4
1004 ; RV32I-MEDIUM-NEXT: xor a3, s6, s1
1005 ; RV32I-MEDIUM-NEXT: or a2, a2, a3
1006 ; RV32I-MEDIUM-NEXT: add s3, a0, s3
1007 ; RV32I-MEDIUM-NEXT: sltu s4, s3, a0
1008 ; RV32I-MEDIUM-NEXT: add s4, a1, s4
1009 ; RV32I-MEDIUM-NEXT: bnez a2, .LBB20_5
1010 ; RV32I-MEDIUM-NEXT: .LBB20_6: # %for.cond.cleanup
1011 ; RV32I-MEDIUM-NEXT: mv a0, s3
1012 ; RV32I-MEDIUM-NEXT: mv a1, s4
1013 ; RV32I-MEDIUM-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
1014 ; RV32I-MEDIUM-NEXT: lw s0, 40(sp) # 4-byte Folded Reload
1015 ; RV32I-MEDIUM-NEXT: lw s1, 36(sp) # 4-byte Folded Reload
1016 ; RV32I-MEDIUM-NEXT: lw s2, 32(sp) # 4-byte Folded Reload
1017 ; RV32I-MEDIUM-NEXT: lw s3, 28(sp) # 4-byte Folded Reload
1018 ; RV32I-MEDIUM-NEXT: lw s4, 24(sp) # 4-byte Folded Reload
1019 ; RV32I-MEDIUM-NEXT: lw s5, 20(sp) # 4-byte Folded Reload
1020 ; RV32I-MEDIUM-NEXT: lw s6, 16(sp) # 4-byte Folded Reload
1021 ; RV32I-MEDIUM-NEXT: lw s7, 12(sp) # 4-byte Folded Reload
1022 ; RV32I-MEDIUM-NEXT: addi sp, sp, 48
1023 ; RV32I-MEDIUM-NEXT: ret
1025 ; RV64I-LABEL: fold_addi_from_different_bb:
1026 ; RV64I: # %bb.0: # %entry
1027 ; RV64I-NEXT: addi sp, sp, -48
1028 ; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
1029 ; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
1030 ; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
1031 ; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
1032 ; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
1033 ; RV64I-NEXT: blez a1, .LBB20_3
1034 ; RV64I-NEXT: # %bb.1: # %for.body.lr.ph
1035 ; RV64I-NEXT: mv s0, a2
1036 ; RV64I-NEXT: mv s1, a1
1037 ; RV64I-NEXT: li s2, 0
1038 ; RV64I-NEXT: slli a0, a0, 4
1039 ; RV64I-NEXT: add s3, a2, a0
1040 ; RV64I-NEXT: .LBB20_2: # %for.body
1041 ; RV64I-NEXT: # =>This Inner Loop Header: Depth=1
1042 ; RV64I-NEXT: mv a0, s0
1043 ; RV64I-NEXT: call f
1044 ; RV64I-NEXT: ld a0, 8(s3)
1045 ; RV64I-NEXT: addi s1, s1, -1
1046 ; RV64I-NEXT: add s2, a0, s2
1047 ; RV64I-NEXT: bnez s1, .LBB20_2
1048 ; RV64I-NEXT: j .LBB20_4
1049 ; RV64I-NEXT: .LBB20_3:
1050 ; RV64I-NEXT: li s2, 0
1051 ; RV64I-NEXT: .LBB20_4: # %for.cond.cleanup
1052 ; RV64I-NEXT: mv a0, s2
1053 ; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
1054 ; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
1055 ; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
1056 ; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
1057 ; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
1058 ; RV64I-NEXT: addi sp, sp, 48
1061 ; RV64I-MEDIUM-LABEL: fold_addi_from_different_bb:
1062 ; RV64I-MEDIUM: # %bb.0: # %entry
1063 ; RV64I-MEDIUM-NEXT: addi sp, sp, -48
1064 ; RV64I-MEDIUM-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
1065 ; RV64I-MEDIUM-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
1066 ; RV64I-MEDIUM-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
1067 ; RV64I-MEDIUM-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
1068 ; RV64I-MEDIUM-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
1069 ; RV64I-MEDIUM-NEXT: blez a1, .LBB20_3
1070 ; RV64I-MEDIUM-NEXT: # %bb.1: # %for.body.lr.ph
1071 ; RV64I-MEDIUM-NEXT: mv s0, a2
1072 ; RV64I-MEDIUM-NEXT: mv s1, a1
1073 ; RV64I-MEDIUM-NEXT: li s2, 0
1074 ; RV64I-MEDIUM-NEXT: slli a0, a0, 4
1075 ; RV64I-MEDIUM-NEXT: add s3, a2, a0
1076 ; RV64I-MEDIUM-NEXT: .LBB20_2: # %for.body
1077 ; RV64I-MEDIUM-NEXT: # =>This Inner Loop Header: Depth=1
1078 ; RV64I-MEDIUM-NEXT: mv a0, s0
1079 ; RV64I-MEDIUM-NEXT: call f
1080 ; RV64I-MEDIUM-NEXT: ld a0, 8(s3)
1081 ; RV64I-MEDIUM-NEXT: addi s1, s1, -1
1082 ; RV64I-MEDIUM-NEXT: add s2, a0, s2
1083 ; RV64I-MEDIUM-NEXT: bnez s1, .LBB20_2
1084 ; RV64I-MEDIUM-NEXT: j .LBB20_4
1085 ; RV64I-MEDIUM-NEXT: .LBB20_3:
1086 ; RV64I-MEDIUM-NEXT: li s2, 0
1087 ; RV64I-MEDIUM-NEXT: .LBB20_4: # %for.cond.cleanup
1088 ; RV64I-MEDIUM-NEXT: mv a0, s2
1089 ; RV64I-MEDIUM-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
1090 ; RV64I-MEDIUM-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
1091 ; RV64I-MEDIUM-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
1092 ; RV64I-MEDIUM-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
1093 ; RV64I-MEDIUM-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
1094 ; RV64I-MEDIUM-NEXT: addi sp, sp, 48
1095 ; RV64I-MEDIUM-NEXT: ret
1097 ; RV64I-LARGE-LABEL: fold_addi_from_different_bb:
1098 ; RV64I-LARGE: # %bb.0: # %entry
1099 ; RV64I-LARGE-NEXT: addi sp, sp, -48
1100 ; RV64I-LARGE-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
1101 ; RV64I-LARGE-NEXT: sd s0, 32(sp) # 8-byte Folded Spill
1102 ; RV64I-LARGE-NEXT: sd s1, 24(sp) # 8-byte Folded Spill
1103 ; RV64I-LARGE-NEXT: sd s2, 16(sp) # 8-byte Folded Spill
1104 ; RV64I-LARGE-NEXT: sd s3, 8(sp) # 8-byte Folded Spill
1105 ; RV64I-LARGE-NEXT: sd s4, 0(sp) # 8-byte Folded Spill
1106 ; RV64I-LARGE-NEXT: blez a1, .LBB20_3
1107 ; RV64I-LARGE-NEXT: # %bb.1: # %for.body.lr.ph
1108 ; RV64I-LARGE-NEXT: mv s0, a2
1109 ; RV64I-LARGE-NEXT: mv s1, a1
1110 ; RV64I-LARGE-NEXT: li s2, 0
1111 ; RV64I-LARGE-NEXT: .Lpcrel_hi14:
1112 ; RV64I-LARGE-NEXT: auipc a1, %pcrel_hi(.LCPI20_0)
1113 ; RV64I-LARGE-NEXT: ld s3, %pcrel_lo(.Lpcrel_hi14)(a1)
1114 ; RV64I-LARGE-NEXT: slli a0, a0, 4
1115 ; RV64I-LARGE-NEXT: add s4, a2, a0
1116 ; RV64I-LARGE-NEXT: .LBB20_2: # %for.body
1117 ; RV64I-LARGE-NEXT: # =>This Inner Loop Header: Depth=1
1118 ; RV64I-LARGE-NEXT: mv a0, s0
1119 ; RV64I-LARGE-NEXT: jalr s3
1120 ; RV64I-LARGE-NEXT: ld a0, 8(s4)
1121 ; RV64I-LARGE-NEXT: addi s1, s1, -1
1122 ; RV64I-LARGE-NEXT: add s2, a0, s2
1123 ; RV64I-LARGE-NEXT: bnez s1, .LBB20_2
1124 ; RV64I-LARGE-NEXT: j .LBB20_4
1125 ; RV64I-LARGE-NEXT: .LBB20_3:
1126 ; RV64I-LARGE-NEXT: li s2, 0
1127 ; RV64I-LARGE-NEXT: .LBB20_4: # %for.cond.cleanup
1128 ; RV64I-LARGE-NEXT: mv a0, s2
1129 ; RV64I-LARGE-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
1130 ; RV64I-LARGE-NEXT: ld s0, 32(sp) # 8-byte Folded Reload
1131 ; RV64I-LARGE-NEXT: ld s1, 24(sp) # 8-byte Folded Reload
1132 ; RV64I-LARGE-NEXT: ld s2, 16(sp) # 8-byte Folded Reload
1133 ; RV64I-LARGE-NEXT: ld s3, 8(sp) # 8-byte Folded Reload
1134 ; RV64I-LARGE-NEXT: ld s4, 0(sp) # 8-byte Folded Reload
1135 ; RV64I-LARGE-NEXT: addi sp, sp, 48
1136 ; RV64I-LARGE-NEXT: ret
1138 %cmp4 = icmp sgt i64 %n, 0
1139 br i1 %cmp4, label %for.body.lr.ph, label %for.cond.cleanup
1141 for.body.lr.ph: ; preds = %entry
1142 ; TODO: when this GEP is expanded, the resulting `addi` should be folded
1143 ; into the load in the loop body.
1144 %y = getelementptr inbounds %struct.S, ptr %a, i64 %k, i32 1
1147 for.cond.cleanup: ; preds = %for.body, %entry
1148 %s.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
1151 for.body: ; preds = %for.body.lr.ph, %for.body
1152 %i.06 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
1153 %s.05 = phi i64 [ 0, %for.body.lr.ph ], [ %add, %for.body ]
1154 call void @f(ptr %a)
1155 %0 = load i64, ptr %y, align 8
1156 %add = add nsw i64 %0, %s.05
1157 %inc = add nuw nsw i64 %i.06, 1
1158 %exitcond.not = icmp eq i64 %inc, %n
1159 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1162 declare void @f(ptr)
1164 @g = external dso_local global [100 x [100 x i8]]
1166 ; This test used to crash due to calling getVRegDef on X0.
1167 define i32 @crash() {
1168 ; RV32I-LABEL: crash:
1169 ; RV32I: # %bb.0: # %entry
1170 ; RV32I-NEXT: lui a0, %hi(g+401)
1171 ; RV32I-NEXT: lbu a0, %lo(g+401)(a0)
1172 ; RV32I-NEXT: seqz a0, a0
1173 ; RV32I-NEXT: sw a0, 0(zero)
1174 ; RV32I-NEXT: li a0, 0
1177 ; RV32I-MEDIUM-LABEL: crash:
1178 ; RV32I-MEDIUM: # %bb.0: # %entry
1179 ; RV32I-MEDIUM-NEXT: .Lpcrel_hi14:
1180 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g+401)
1181 ; RV32I-MEDIUM-NEXT: lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0)
1182 ; RV32I-MEDIUM-NEXT: seqz a0, a0
1183 ; RV32I-MEDIUM-NEXT: sw a0, 0(zero)
1184 ; RV32I-MEDIUM-NEXT: li a0, 0
1185 ; RV32I-MEDIUM-NEXT: ret
1187 ; RV64I-LABEL: crash:
1188 ; RV64I: # %bb.0: # %entry
1189 ; RV64I-NEXT: lui a0, %hi(g+401)
1190 ; RV64I-NEXT: lbu a0, %lo(g+401)(a0)
1191 ; RV64I-NEXT: seqz a0, a0
1192 ; RV64I-NEXT: sw a0, 0(zero)
1193 ; RV64I-NEXT: li a0, 0
1196 ; RV64I-MEDIUM-LABEL: crash:
1197 ; RV64I-MEDIUM: # %bb.0: # %entry
1198 ; RV64I-MEDIUM-NEXT: .Lpcrel_hi14:
1199 ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g+401)
1200 ; RV64I-MEDIUM-NEXT: lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0)
1201 ; RV64I-MEDIUM-NEXT: seqz a0, a0
1202 ; RV64I-MEDIUM-NEXT: sw a0, 0(zero)
1203 ; RV64I-MEDIUM-NEXT: li a0, 0
1204 ; RV64I-MEDIUM-NEXT: ret
1206 ; RV64I-LARGE-LABEL: crash:
1207 ; RV64I-LARGE: # %bb.0: # %entry
1208 ; RV64I-LARGE-NEXT: li a0, 1
1209 ; RV64I-LARGE-NEXT: .Lpcrel_hi15:
1210 ; RV64I-LARGE-NEXT: auipc a1, %pcrel_hi(.LCPI21_0)
1211 ; RV64I-LARGE-NEXT: ld a1, %pcrel_lo(.Lpcrel_hi15)(a1)
1212 ; RV64I-LARGE-NEXT: add a0, a1, a0
1213 ; RV64I-LARGE-NEXT: lbu a0, 400(a0)
1214 ; RV64I-LARGE-NEXT: seqz a0, a0
1215 ; RV64I-LARGE-NEXT: sw a0, 0(zero)
1216 ; RV64I-LARGE-NEXT: li a0, 0
1217 ; RV64I-LARGE-NEXT: ret
1219 %idxprom7.peel = sext i32 1 to i64
1220 br label %for.inc.peel
1222 for.inc.peel: ; preds = %entry
1223 %arrayidx8.3.peel = getelementptr [100 x [100 x i8]], ptr @g, i64 0, i64 4, i64 %idxprom7.peel
1224 %0 = load i8, ptr %arrayidx8.3.peel, align 1
1225 %tobool.not.3.peel = icmp eq i8 %0, 0
1226 %spec.select = select i1 %tobool.not.3.peel, i32 1, i32 0
1227 store i32 %spec.select, ptr null, align 4