Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / CodeGen / RISCV / fold-addi-loadstore.ll
blob91e73992bdfa3b9dde2d937176d2b1df50c85517
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN:   -riscv-enable-sink-fold | FileCheck -check-prefix=RV32I %s
4 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -code-model=medium < %s \
5 ; RUN:   -riscv-enable-sink-fold | FileCheck -check-prefix=RV32I-MEDIUM %s
6 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
7 ; RUN:   -riscv-enable-sink-fold | FileCheck -check-prefix=RV64I %s
8 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -code-model=medium < %s \
9 ; RUN:   -riscv-enable-sink-fold | FileCheck -check-prefix=RV64I-MEDIUM %s
11 ; We can often fold an ADDI into the offset of load/store instructions:
12 ;   (load (addi base, off1), off2) -> (load base, off1+off2)
13 ;   (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
14 ; This is possible when the off1+off2 continues to fit the 12-bit immediate.
15 ; Check if we do the fold under various conditions. If off1 is (the low part of)
16 ; an address the fold's safety depends on the variable's alignment.
18 @g_0 = dso_local global i64 0
19 @g_1 = dso_local global i64 0, align 1
20 @g_2 = dso_local global i64 0, align 2
21 @g_4 = dso_local global i64 0, align 4
22 @g_8 = dso_local global i64 0, align 8
23 @g_16 = dso_local global i64 0, align 16
25 define dso_local i64 @load_g_0() nounwind {
26 ; RV32I-LABEL: load_g_0:
27 ; RV32I:       # %bb.0: # %entry
28 ; RV32I-NEXT:    lui a1, %hi(g_0)
29 ; RV32I-NEXT:    lw a0, %lo(g_0)(a1)
30 ; RV32I-NEXT:    lw a1, %lo(g_0+4)(a1)
31 ; RV32I-NEXT:    ret
33 ; RV32I-MEDIUM-LABEL: load_g_0:
34 ; RV32I-MEDIUM:       # %bb.0: # %entry
35 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi0:
36 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_0)
37 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi0)
38 ; RV32I-MEDIUM-NEXT:    lw a0, 0(a1)
39 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
40 ; RV32I-MEDIUM-NEXT:    ret
42 ; RV64I-LABEL: load_g_0:
43 ; RV64I:       # %bb.0: # %entry
44 ; RV64I-NEXT:    lui a0, %hi(g_0)
45 ; RV64I-NEXT:    ld a0, %lo(g_0)(a0)
46 ; RV64I-NEXT:    ret
48 ; RV64I-MEDIUM-LABEL: load_g_0:
49 ; RV64I-MEDIUM:       # %bb.0: # %entry
50 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi0:
51 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_0)
52 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi0)(a0)
53 ; RV64I-MEDIUM-NEXT:    ret
54 entry:
55   %0 = load i64, ptr @g_0
56   ret i64 %0
59 define dso_local i64 @load_g_1() nounwind {
60 ; RV32I-LABEL: load_g_1:
61 ; RV32I:       # %bb.0: # %entry
62 ; RV32I-NEXT:    lui a1, %hi(g_1)
63 ; RV32I-NEXT:    lw a0, %lo(g_1)(a1)
64 ; RV32I-NEXT:    addi a1, a1, %lo(g_1)
65 ; RV32I-NEXT:    lw a1, 4(a1)
66 ; RV32I-NEXT:    ret
68 ; RV32I-MEDIUM-LABEL: load_g_1:
69 ; RV32I-MEDIUM:       # %bb.0: # %entry
70 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi1:
71 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_1)
72 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi1)
73 ; RV32I-MEDIUM-NEXT:    lw a0, 0(a1)
74 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
75 ; RV32I-MEDIUM-NEXT:    ret
77 ; RV64I-LABEL: load_g_1:
78 ; RV64I:       # %bb.0: # %entry
79 ; RV64I-NEXT:    lui a0, %hi(g_1)
80 ; RV64I-NEXT:    ld a0, %lo(g_1)(a0)
81 ; RV64I-NEXT:    ret
83 ; RV64I-MEDIUM-LABEL: load_g_1:
84 ; RV64I-MEDIUM:       # %bb.0: # %entry
85 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi1:
86 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_1)
87 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi1)(a0)
88 ; RV64I-MEDIUM-NEXT:    ret
89 entry:
90   %0 = load i64, ptr @g_1
91   ret i64 %0
94 define dso_local i64 @load_g_2() nounwind {
95 ; RV32I-LABEL: load_g_2:
96 ; RV32I:       # %bb.0: # %entry
97 ; RV32I-NEXT:    lui a1, %hi(g_2)
98 ; RV32I-NEXT:    lw a0, %lo(g_2)(a1)
99 ; RV32I-NEXT:    addi a1, a1, %lo(g_2)
100 ; RV32I-NEXT:    lw a1, 4(a1)
101 ; RV32I-NEXT:    ret
103 ; RV32I-MEDIUM-LABEL: load_g_2:
104 ; RV32I-MEDIUM:       # %bb.0: # %entry
105 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi2:
106 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_2)
107 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi2)
108 ; RV32I-MEDIUM-NEXT:    lw a0, 0(a1)
109 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
110 ; RV32I-MEDIUM-NEXT:    ret
112 ; RV64I-LABEL: load_g_2:
113 ; RV64I:       # %bb.0: # %entry
114 ; RV64I-NEXT:    lui a0, %hi(g_2)
115 ; RV64I-NEXT:    ld a0, %lo(g_2)(a0)
116 ; RV64I-NEXT:    ret
118 ; RV64I-MEDIUM-LABEL: load_g_2:
119 ; RV64I-MEDIUM:       # %bb.0: # %entry
120 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi2:
121 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_2)
122 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi2)(a0)
123 ; RV64I-MEDIUM-NEXT:    ret
124 entry:
125   %0 = load i64, ptr @g_2
126   ret i64 %0
129 define dso_local i64 @load_g_4() nounwind {
130 ; RV32I-LABEL: load_g_4:
131 ; RV32I:       # %bb.0: # %entry
132 ; RV32I-NEXT:    lui a1, %hi(g_4)
133 ; RV32I-NEXT:    lw a0, %lo(g_4)(a1)
134 ; RV32I-NEXT:    addi a1, a1, %lo(g_4)
135 ; RV32I-NEXT:    lw a1, 4(a1)
136 ; RV32I-NEXT:    ret
138 ; RV32I-MEDIUM-LABEL: load_g_4:
139 ; RV32I-MEDIUM:       # %bb.0: # %entry
140 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi3:
141 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4)
142 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi3)
143 ; RV32I-MEDIUM-NEXT:    lw a0, 0(a1)
144 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
145 ; RV32I-MEDIUM-NEXT:    ret
147 ; RV64I-LABEL: load_g_4:
148 ; RV64I:       # %bb.0: # %entry
149 ; RV64I-NEXT:    lui a0, %hi(g_4)
150 ; RV64I-NEXT:    ld a0, %lo(g_4)(a0)
151 ; RV64I-NEXT:    ret
153 ; RV64I-MEDIUM-LABEL: load_g_4:
154 ; RV64I-MEDIUM:       # %bb.0: # %entry
155 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi3:
156 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4)
157 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi3)(a0)
158 ; RV64I-MEDIUM-NEXT:    ret
159 entry:
160   %0 = load i64, ptr @g_4
161   ret i64 %0
164 define dso_local i64 @load_g_8() nounwind {
165 ; RV32I-LABEL: load_g_8:
166 ; RV32I:       # %bb.0: # %entry
167 ; RV32I-NEXT:    lui a1, %hi(g_8)
168 ; RV32I-NEXT:    lw a0, %lo(g_8)(a1)
169 ; RV32I-NEXT:    lw a1, %lo(g_8+4)(a1)
170 ; RV32I-NEXT:    ret
172 ; RV32I-MEDIUM-LABEL: load_g_8:
173 ; RV32I-MEDIUM:       # %bb.0: # %entry
174 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi4:
175 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_8)
176 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi4)
177 ; RV32I-MEDIUM-NEXT:    lw a0, 0(a1)
178 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
179 ; RV32I-MEDIUM-NEXT:    ret
181 ; RV64I-LABEL: load_g_8:
182 ; RV64I:       # %bb.0: # %entry
183 ; RV64I-NEXT:    lui a0, %hi(g_8)
184 ; RV64I-NEXT:    ld a0, %lo(g_8)(a0)
185 ; RV64I-NEXT:    ret
187 ; RV64I-MEDIUM-LABEL: load_g_8:
188 ; RV64I-MEDIUM:       # %bb.0: # %entry
189 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi4:
190 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_8)
191 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi4)(a0)
192 ; RV64I-MEDIUM-NEXT:    ret
193 entry:
194   %0 = load i64, ptr @g_8
195   ret i64 %0
198 define dso_local i64 @load_g_16() nounwind {
199 ; RV32I-LABEL: load_g_16:
200 ; RV32I:       # %bb.0: # %entry
201 ; RV32I-NEXT:    lui a1, %hi(g_16)
202 ; RV32I-NEXT:    lw a0, %lo(g_16)(a1)
203 ; RV32I-NEXT:    lw a1, %lo(g_16+4)(a1)
204 ; RV32I-NEXT:    ret
206 ; RV32I-MEDIUM-LABEL: load_g_16:
207 ; RV32I-MEDIUM:       # %bb.0: # %entry
208 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi5:
209 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_16)
210 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi5)
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_16:
216 ; RV64I:       # %bb.0: # %entry
217 ; RV64I-NEXT:    lui a0, %hi(g_16)
218 ; RV64I-NEXT:    ld a0, %lo(g_16)(a0)
219 ; RV64I-NEXT:    ret
221 ; RV64I-MEDIUM-LABEL: load_g_16:
222 ; RV64I-MEDIUM:       # %bb.0: # %entry
223 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi5:
224 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_16)
225 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi5)(a0)
226 ; RV64I-MEDIUM-NEXT:    ret
227 entry:
228   %0 = load i64, ptr @g_16
229   ret i64 %0
232 define dso_local void @store_g_4() nounwind {
233 ; RV32I-LABEL: store_g_4:
234 ; RV32I:       # %bb.0: # %entry
235 ; RV32I-NEXT:    lui a0, %hi(g_4)
236 ; RV32I-NEXT:    sw zero, %lo(g_4)(a0)
237 ; RV32I-NEXT:    addi a0, a0, %lo(g_4)
238 ; RV32I-NEXT:    sw zero, 4(a0)
239 ; RV32I-NEXT:    ret
241 ; RV32I-MEDIUM-LABEL: store_g_4:
242 ; RV32I-MEDIUM:       # %bb.0: # %entry
243 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi6:
244 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4)
245 ; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.Lpcrel_hi6)
246 ; RV32I-MEDIUM-NEXT:    sw zero, 4(a0)
247 ; RV32I-MEDIUM-NEXT:    sw zero, 0(a0)
248 ; RV32I-MEDIUM-NEXT:    ret
250 ; RV64I-LABEL: store_g_4:
251 ; RV64I:       # %bb.0: # %entry
252 ; RV64I-NEXT:    lui a0, %hi(g_4)
253 ; RV64I-NEXT:    sd zero, %lo(g_4)(a0)
254 ; RV64I-NEXT:    ret
256 ; RV64I-MEDIUM-LABEL: store_g_4:
257 ; RV64I-MEDIUM:       # %bb.0: # %entry
258 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi6:
259 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4)
260 ; RV64I-MEDIUM-NEXT:    sd zero, %pcrel_lo(.Lpcrel_hi6)(a0)
261 ; RV64I-MEDIUM-NEXT:    ret
262 entry:
263    store i64 0, ptr @g_4
264    ret void
267 define dso_local void @store_g_8() nounwind {
268 ; RV32I-LABEL: store_g_8:
269 ; RV32I:       # %bb.0: # %entry
270 ; RV32I-NEXT:    lui a0, %hi(g_8)
271 ; RV32I-NEXT:    sw zero, %lo(g_8+4)(a0)
272 ; RV32I-NEXT:    sw zero, %lo(g_8)(a0)
273 ; RV32I-NEXT:    ret
275 ; RV32I-MEDIUM-LABEL: store_g_8:
276 ; RV32I-MEDIUM:       # %bb.0: # %entry
277 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi7:
278 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_8)
279 ; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.Lpcrel_hi7)
280 ; RV32I-MEDIUM-NEXT:    sw zero, 4(a0)
281 ; RV32I-MEDIUM-NEXT:    sw zero, 0(a0)
282 ; RV32I-MEDIUM-NEXT:    ret
284 ; RV64I-LABEL: store_g_8:
285 ; RV64I:       # %bb.0: # %entry
286 ; RV64I-NEXT:    lui a0, %hi(g_8)
287 ; RV64I-NEXT:    sd zero, %lo(g_8)(a0)
288 ; RV64I-NEXT:    ret
290 ; RV64I-MEDIUM-LABEL: store_g_8:
291 ; RV64I-MEDIUM:       # %bb.0: # %entry
292 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi7:
293 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_8)
294 ; RV64I-MEDIUM-NEXT:    sd zero, %pcrel_lo(.Lpcrel_hi7)(a0)
295 ; RV64I-MEDIUM-NEXT:    ret
296 entry:
297    store i64 0, ptr @g_8
298    ret void
301 ; Check if we can fold ADDI into the offset of store instructions,
302 ; when store instructions is the root node in DAG.
304 @g_4_i32 = global i32 0, align 4
306 define dso_local void @inc_g_i32() nounwind {
307 ; RV32I-LABEL: inc_g_i32:
308 ; RV32I:       # %bb.0: # %entry
309 ; RV32I-NEXT:    lui a0, %hi(g_4_i32)
310 ; RV32I-NEXT:    lw a1, %lo(g_4_i32)(a0)
311 ; RV32I-NEXT:    addi a1, a1, 1
312 ; RV32I-NEXT:    sw a1, %lo(g_4_i32)(a0)
313 ; RV32I-NEXT:    ret
315 ; RV32I-MEDIUM-LABEL: inc_g_i32:
316 ; RV32I-MEDIUM:       # %bb.0: # %entry
317 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi8:
318 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4_i32)
319 ; RV32I-MEDIUM-NEXT:    lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
320 ; RV32I-MEDIUM-NEXT:    addi a1, a1, 1
321 ; RV32I-MEDIUM-NEXT:    sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
322 ; RV32I-MEDIUM-NEXT:    ret
324 ; RV64I-LABEL: inc_g_i32:
325 ; RV64I:       # %bb.0: # %entry
326 ; RV64I-NEXT:    lui a0, %hi(g_4_i32)
327 ; RV64I-NEXT:    lw a1, %lo(g_4_i32)(a0)
328 ; RV64I-NEXT:    addi a1, a1, 1
329 ; RV64I-NEXT:    sw a1, %lo(g_4_i32)(a0)
330 ; RV64I-NEXT:    ret
332 ; RV64I-MEDIUM-LABEL: inc_g_i32:
333 ; RV64I-MEDIUM:       # %bb.0: # %entry
334 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi8:
335 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g_4_i32)
336 ; RV64I-MEDIUM-NEXT:    lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
337 ; RV64I-MEDIUM-NEXT:    addi a1, a1, 1
338 ; RV64I-MEDIUM-NEXT:    sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
339 ; RV64I-MEDIUM-NEXT:    ret
340 entry:
341   %0 = load i32, ptr @g_4_i32
342   %inc = add i32 %0, 1
343   store i32 %inc, ptr @g_4_i32
344   br label %if.end
346 if.end:
347   ret void
350 ; Check for folds in accesses to elements of an i32 array.
352 @ga = dso_local local_unnamed_addr global [2 x i32] zeroinitializer, align 4
354 define dso_local i32 @load_ga() local_unnamed_addr #0 {
355 ; RV32I-LABEL: load_ga:
356 ; RV32I:       # %bb.0:
357 ; RV32I-NEXT:    lui a0, %hi(ga+4)
358 ; RV32I-NEXT:    lw a0, %lo(ga+4)(a0)
359 ; RV32I-NEXT:    ret
361 ; RV32I-MEDIUM-LABEL: load_ga:
362 ; RV32I-MEDIUM:       # %bb.0:
363 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi9:
364 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga+4)
365 ; RV32I-MEDIUM-NEXT:    lw a0, %pcrel_lo(.Lpcrel_hi9)(a0)
366 ; RV32I-MEDIUM-NEXT:    ret
368 ; RV64I-LABEL: load_ga:
369 ; RV64I:       # %bb.0:
370 ; RV64I-NEXT:    lui a0, %hi(ga+4)
371 ; RV64I-NEXT:    lw a0, %lo(ga+4)(a0)
372 ; RV64I-NEXT:    ret
374 ; RV64I-MEDIUM-LABEL: load_ga:
375 ; RV64I-MEDIUM:       # %bb.0:
376 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi9:
377 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga+4)
378 ; RV64I-MEDIUM-NEXT:    lw a0, %pcrel_lo(.Lpcrel_hi9)(a0)
379 ; RV64I-MEDIUM-NEXT:    ret
380   %1 = load i32, ptr getelementptr inbounds ([2 x i32], ptr @ga, i32 0, i32 1), align 4
381   ret i32 %1
384 ; Check for folds in accesses to the second element of an i64 array.
386 @ga_8 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 8
387 @ga_16 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 16
389 define dso_local i64 @load_ga_8() nounwind {
390 ; RV32I-LABEL: load_ga_8:
391 ; RV32I:       # %bb.0: # %entry
392 ; RV32I-NEXT:    lui a0, %hi(ga_8)
393 ; RV32I-NEXT:    addi a1, a0, %lo(ga_8)
394 ; RV32I-NEXT:    lw a0, 8(a1)
395 ; RV32I-NEXT:    lw a1, 12(a1)
396 ; RV32I-NEXT:    ret
398 ; RV32I-MEDIUM-LABEL: load_ga_8:
399 ; RV32I-MEDIUM:       # %bb.0: # %entry
400 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi10:
401 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga_8)
402 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi10)
403 ; RV32I-MEDIUM-NEXT:    lw a0, 8(a1)
404 ; RV32I-MEDIUM-NEXT:    lw a1, 12(a1)
405 ; RV32I-MEDIUM-NEXT:    ret
407 ; RV64I-LABEL: load_ga_8:
408 ; RV64I:       # %bb.0: # %entry
409 ; RV64I-NEXT:    lui a0, %hi(ga_8+8)
410 ; RV64I-NEXT:    ld a0, %lo(ga_8+8)(a0)
411 ; RV64I-NEXT:    ret
413 ; RV64I-MEDIUM-LABEL: load_ga_8:
414 ; RV64I-MEDIUM:       # %bb.0: # %entry
415 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi10:
416 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga_8+8)
417 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi10)(a0)
418 ; RV64I-MEDIUM-NEXT:    ret
419 entry:
420   %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_8, i32 0, i32 1)
421   ret i64 %0
424 define dso_local i64 @load_ga_16() nounwind {
425 ; RV32I-LABEL: load_ga_16:
426 ; RV32I:       # %bb.0: # %entry
427 ; RV32I-NEXT:    lui a1, %hi(ga_16)
428 ; RV32I-NEXT:    lw a0, %lo(ga_16+8)(a1)
429 ; RV32I-NEXT:    lw a1, %lo(ga_16+12)(a1)
430 ; RV32I-NEXT:    ret
432 ; RV32I-MEDIUM-LABEL: load_ga_16:
433 ; RV32I-MEDIUM:       # %bb.0: # %entry
434 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi11:
435 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga_16)
436 ; RV32I-MEDIUM-NEXT:    addi a1, a0, %pcrel_lo(.Lpcrel_hi11)
437 ; RV32I-MEDIUM-NEXT:    lw a0, 8(a1)
438 ; RV32I-MEDIUM-NEXT:    lw a1, 12(a1)
439 ; RV32I-MEDIUM-NEXT:    ret
441 ; RV64I-LABEL: load_ga_16:
442 ; RV64I:       # %bb.0: # %entry
443 ; RV64I-NEXT:    lui a0, %hi(ga_16)
444 ; RV64I-NEXT:    ld a0, %lo(ga_16+8)(a0)
445 ; RV64I-NEXT:    ret
447 ; RV64I-MEDIUM-LABEL: load_ga_16:
448 ; RV64I-MEDIUM:       # %bb.0: # %entry
449 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi11:
450 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(ga_16+8)
451 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi11)(a0)
452 ; RV64I-MEDIUM-NEXT:    ret
453 entry:
454   %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_16, i32 0, i32 1)
455   ret i64 %0
458 ; Check for folds in accesses to block address.
459 define dso_local ptr @load_ba_1() nounwind {
460 ; RV32I-LABEL: load_ba_1:
461 ; RV32I:       # %bb.0: # %entry
462 ; RV32I-NEXT:  .Ltmp0: # Block address taken
463 ; RV32I-NEXT:  # %bb.1: # %label
464 ; RV32I-NEXT:    lui a0, %hi(.Ltmp0)
465 ; RV32I-NEXT:    lw a0, %lo(.Ltmp0)(a0)
466 ; RV32I-NEXT:    ret
468 ; RV32I-MEDIUM-LABEL: load_ba_1:
469 ; RV32I-MEDIUM:       # %bb.0: # %entry
470 ; RV32I-MEDIUM-NEXT:  .Ltmp0: # Block address taken
471 ; RV32I-MEDIUM-NEXT:  # %bb.1: # %label
472 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi12:
473 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(.Ltmp0)
474 ; RV32I-MEDIUM-NEXT:    lw a0, %pcrel_lo(.Lpcrel_hi12)(a0)
475 ; RV32I-MEDIUM-NEXT:    ret
477 ; RV64I-LABEL: load_ba_1:
478 ; RV64I:       # %bb.0: # %entry
479 ; RV64I-NEXT:  .Ltmp0: # Block address taken
480 ; RV64I-NEXT:  # %bb.1: # %label
481 ; RV64I-NEXT:    lui a0, %hi(.Ltmp0)
482 ; RV64I-NEXT:    ld a0, %lo(.Ltmp0)(a0)
483 ; RV64I-NEXT:    ret
485 ; RV64I-MEDIUM-LABEL: load_ba_1:
486 ; RV64I-MEDIUM:       # %bb.0: # %entry
487 ; RV64I-MEDIUM-NEXT:  .Ltmp0: # Block address taken
488 ; RV64I-MEDIUM-NEXT:  # %bb.1: # %label
489 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi12:
490 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(.Ltmp0)
491 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi12)(a0)
492 ; RV64I-MEDIUM-NEXT:    ret
493 entry:
494   br label %label
495 label:
496   %0 = load ptr, ptr blockaddress(@load_ba_1, %label)
497   ret ptr %0
500 define dso_local ptr @load_ba_2() nounwind {
501 ; RV32I-LABEL: load_ba_2:
502 ; RV32I:       # %bb.0: # %entry
503 ; RV32I-NEXT:  .Ltmp1: # Block address taken
504 ; RV32I-NEXT:  # %bb.1: # %label
505 ; RV32I-NEXT:    lui a0, %hi(.Ltmp1+8)
506 ; RV32I-NEXT:    lw a0, %lo(.Ltmp1+8)(a0)
507 ; RV32I-NEXT:    ret
509 ; RV32I-MEDIUM-LABEL: load_ba_2:
510 ; RV32I-MEDIUM:       # %bb.0: # %entry
511 ; RV32I-MEDIUM-NEXT:  .Ltmp1: # Block address taken
512 ; RV32I-MEDIUM-NEXT:  # %bb.1: # %label
513 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi13:
514 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(.Ltmp1+8)
515 ; RV32I-MEDIUM-NEXT:    lw a0, %pcrel_lo(.Lpcrel_hi13)(a0)
516 ; RV32I-MEDIUM-NEXT:    ret
518 ; RV64I-LABEL: load_ba_2:
519 ; RV64I:       # %bb.0: # %entry
520 ; RV64I-NEXT:  .Ltmp1: # Block address taken
521 ; RV64I-NEXT:  # %bb.1: # %label
522 ; RV64I-NEXT:    lui a0, %hi(.Ltmp1+8)
523 ; RV64I-NEXT:    ld a0, %lo(.Ltmp1+8)(a0)
524 ; RV64I-NEXT:    ret
526 ; RV64I-MEDIUM-LABEL: load_ba_2:
527 ; RV64I-MEDIUM:       # %bb.0: # %entry
528 ; RV64I-MEDIUM-NEXT:  .Ltmp1: # Block address taken
529 ; RV64I-MEDIUM-NEXT:  # %bb.1: # %label
530 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi13:
531 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(.Ltmp1+8)
532 ; RV64I-MEDIUM-NEXT:    ld a0, %pcrel_lo(.Lpcrel_hi13)(a0)
533 ; RV64I-MEDIUM-NEXT:    ret
534 entry:
535   br label %label
536 label:
537   %0 = load ptr, ptr getelementptr inbounds (i8, ptr blockaddress(@load_ba_2, %label), i32 8)
538   ret ptr %0
541 ; Check for folds in accesses to thread-local variables.
543 @tl_4 = dso_local thread_local global i64 0, align 4
544 @tl_8 = dso_local thread_local global i64 0, align 8
546 define dso_local i64 @load_tl_4() nounwind {
547 ; RV32I-LABEL: load_tl_4:
548 ; RV32I:       # %bb.0: # %entry
549 ; RV32I-NEXT:    lui a0, %tprel_hi(tl_4)
550 ; RV32I-NEXT:    add a1, a0, tp, %tprel_add(tl_4)
551 ; RV32I-NEXT:    lw a0, %tprel_lo(tl_4)(a1)
552 ; RV32I-NEXT:    addi a1, a1, %tprel_lo(tl_4)
553 ; RV32I-NEXT:    lw a1, 4(a1)
554 ; RV32I-NEXT:    ret
556 ; RV32I-MEDIUM-LABEL: load_tl_4:
557 ; RV32I-MEDIUM:       # %bb.0: # %entry
558 ; RV32I-MEDIUM-NEXT:    lui a0, %tprel_hi(tl_4)
559 ; RV32I-MEDIUM-NEXT:    add a1, a0, tp, %tprel_add(tl_4)
560 ; RV32I-MEDIUM-NEXT:    lw a0, %tprel_lo(tl_4)(a1)
561 ; RV32I-MEDIUM-NEXT:    addi a1, a1, %tprel_lo(tl_4)
562 ; RV32I-MEDIUM-NEXT:    lw a1, 4(a1)
563 ; RV32I-MEDIUM-NEXT:    ret
565 ; RV64I-LABEL: load_tl_4:
566 ; RV64I:       # %bb.0: # %entry
567 ; RV64I-NEXT:    lui a0, %tprel_hi(tl_4)
568 ; RV64I-NEXT:    add a0, a0, tp, %tprel_add(tl_4)
569 ; RV64I-NEXT:    ld a0, %tprel_lo(tl_4)(a0)
570 ; RV64I-NEXT:    ret
572 ; RV64I-MEDIUM-LABEL: load_tl_4:
573 ; RV64I-MEDIUM:       # %bb.0: # %entry
574 ; RV64I-MEDIUM-NEXT:    lui a0, %tprel_hi(tl_4)
575 ; RV64I-MEDIUM-NEXT:    add a0, a0, tp, %tprel_add(tl_4)
576 ; RV64I-MEDIUM-NEXT:    ld a0, %tprel_lo(tl_4)(a0)
577 ; RV64I-MEDIUM-NEXT:    ret
578 entry:
579   %0 = load i64, ptr @tl_4
580   ret i64 %0
583 define dso_local i64 @load_tl_8() nounwind {
584 ; RV32I-LABEL: load_tl_8:
585 ; RV32I:       # %bb.0: # %entry
586 ; RV32I-NEXT:    lui a0, %tprel_hi(tl_8)
587 ; RV32I-NEXT:    add a1, a0, tp, %tprel_add(tl_8)
588 ; RV32I-NEXT:    lw a0, %tprel_lo(tl_8)(a1)
589 ; RV32I-NEXT:    lw a1, %tprel_lo(tl_8+4)(a1)
590 ; RV32I-NEXT:    ret
592 ; RV32I-MEDIUM-LABEL: load_tl_8:
593 ; RV32I-MEDIUM:       # %bb.0: # %entry
594 ; RV32I-MEDIUM-NEXT:    lui a0, %tprel_hi(tl_8)
595 ; RV32I-MEDIUM-NEXT:    add a1, a0, tp, %tprel_add(tl_8)
596 ; RV32I-MEDIUM-NEXT:    lw a0, %tprel_lo(tl_8)(a1)
597 ; RV32I-MEDIUM-NEXT:    lw a1, %tprel_lo(tl_8+4)(a1)
598 ; RV32I-MEDIUM-NEXT:    ret
600 ; RV64I-LABEL: load_tl_8:
601 ; RV64I:       # %bb.0: # %entry
602 ; RV64I-NEXT:    lui a0, %tprel_hi(tl_8)
603 ; RV64I-NEXT:    add a0, a0, tp, %tprel_add(tl_8)
604 ; RV64I-NEXT:    ld a0, %tprel_lo(tl_8)(a0)
605 ; RV64I-NEXT:    ret
607 ; RV64I-MEDIUM-LABEL: load_tl_8:
608 ; RV64I-MEDIUM:       # %bb.0: # %entry
609 ; RV64I-MEDIUM-NEXT:    lui a0, %tprel_hi(tl_8)
610 ; RV64I-MEDIUM-NEXT:    add a0, a0, tp, %tprel_add(tl_8)
611 ; RV64I-MEDIUM-NEXT:    ld a0, %tprel_lo(tl_8)(a0)
612 ; RV64I-MEDIUM-NEXT:    ret
613 entry:
614   %0 = load i64, ptr @tl_8
615   ret i64 %0
618 define dso_local i64 @load_const_ok() nounwind {
619 ; RV32I-LABEL: load_const_ok:
620 ; RV32I:       # %bb.0: # %entry
621 ; RV32I-NEXT:    lw a0, 2040(zero)
622 ; RV32I-NEXT:    lw a1, 2044(zero)
623 ; RV32I-NEXT:    ret
625 ; RV32I-MEDIUM-LABEL: load_const_ok:
626 ; RV32I-MEDIUM:       # %bb.0: # %entry
627 ; RV32I-MEDIUM-NEXT:    lw a0, 2040(zero)
628 ; RV32I-MEDIUM-NEXT:    lw a1, 2044(zero)
629 ; RV32I-MEDIUM-NEXT:    ret
631 ; RV64I-LABEL: load_const_ok:
632 ; RV64I:       # %bb.0: # %entry
633 ; RV64I-NEXT:    ld a0, 2040(zero)
634 ; RV64I-NEXT:    ret
636 ; RV64I-MEDIUM-LABEL: load_const_ok:
637 ; RV64I-MEDIUM:       # %bb.0: # %entry
638 ; RV64I-MEDIUM-NEXT:    ld a0, 2040(zero)
639 ; RV64I-MEDIUM-NEXT:    ret
640 entry:
641   %0 = load i64, ptr inttoptr (i32 2040 to ptr)
642   ret i64 %0
645 define dso_local i64 @load_cost_overflow() nounwind {
646 ; RV32I-LABEL: load_cost_overflow:
647 ; RV32I:       # %bb.0: # %entry
648 ; RV32I-NEXT:    lui a0, 1
649 ; RV32I-NEXT:    lw a1, -2048(a0)
650 ; RV32I-NEXT:    lw a0, 2044(zero)
651 ; RV32I-NEXT:    ret
653 ; RV32I-MEDIUM-LABEL: load_cost_overflow:
654 ; RV32I-MEDIUM:       # %bb.0: # %entry
655 ; RV32I-MEDIUM-NEXT:    lui a0, 1
656 ; RV32I-MEDIUM-NEXT:    lw a1, -2048(a0)
657 ; RV32I-MEDIUM-NEXT:    lw a0, 2044(zero)
658 ; RV32I-MEDIUM-NEXT:    ret
660 ; RV64I-LABEL: load_cost_overflow:
661 ; RV64I:       # %bb.0: # %entry
662 ; RV64I-NEXT:    ld a0, 2044(zero)
663 ; RV64I-NEXT:    ret
665 ; RV64I-MEDIUM-LABEL: load_cost_overflow:
666 ; RV64I-MEDIUM:       # %bb.0: # %entry
667 ; RV64I-MEDIUM-NEXT:    ld a0, 2044(zero)
668 ; RV64I-MEDIUM-NEXT:    ret
669 entry:
670   %0 = load i64, ptr inttoptr (i64 2044 to ptr)
671   ret i64 %0
674 define dso_local i32 @load_const_medium() nounwind {
675 ; RV32I-LABEL: load_const_medium:
676 ; RV32I:       # %bb.0: # %entry
677 ; RV32I-NEXT:    lui a0, 1
678 ; RV32I-NEXT:    lw a0, -16(a0)
679 ; RV32I-NEXT:    ret
681 ; RV32I-MEDIUM-LABEL: load_const_medium:
682 ; RV32I-MEDIUM:       # %bb.0: # %entry
683 ; RV32I-MEDIUM-NEXT:    lui a0, 1
684 ; RV32I-MEDIUM-NEXT:    lw a0, -16(a0)
685 ; RV32I-MEDIUM-NEXT:    ret
687 ; RV64I-LABEL: load_const_medium:
688 ; RV64I:       # %bb.0: # %entry
689 ; RV64I-NEXT:    lui a0, 1
690 ; RV64I-NEXT:    lw a0, -16(a0)
691 ; RV64I-NEXT:    ret
693 ; RV64I-MEDIUM-LABEL: load_const_medium:
694 ; RV64I-MEDIUM:       # %bb.0: # %entry
695 ; RV64I-MEDIUM-NEXT:    lui a0, 1
696 ; RV64I-MEDIUM-NEXT:    lw a0, -16(a0)
697 ; RV64I-MEDIUM-NEXT:    ret
698 entry:
699   %0 = load i32, ptr inttoptr (i64 4080 to ptr)
700   ret i32 %0
703 ; The constant here is 0x7ffff800, this value requires LUI+ADDIW on RV64,
704 ; LUI+ADDI would produce a different constant so we can't fold into the load
705 ; offset.
706 define dso_local i32 @load_const_large() nounwind {
707 ; RV32I-LABEL: load_const_large:
708 ; RV32I:       # %bb.0: # %entry
709 ; RV32I-NEXT:    lui a0, 524288
710 ; RV32I-NEXT:    lw a0, -2048(a0)
711 ; RV32I-NEXT:    ret
713 ; RV32I-MEDIUM-LABEL: load_const_large:
714 ; RV32I-MEDIUM:       # %bb.0: # %entry
715 ; RV32I-MEDIUM-NEXT:    lui a0, 524288
716 ; RV32I-MEDIUM-NEXT:    lw a0, -2048(a0)
717 ; RV32I-MEDIUM-NEXT:    ret
719 ; RV64I-LABEL: load_const_large:
720 ; RV64I:       # %bb.0: # %entry
721 ; RV64I-NEXT:    lui a0, 524288
722 ; RV64I-NEXT:    addiw a0, a0, -2048
723 ; RV64I-NEXT:    lw a0, 0(a0)
724 ; RV64I-NEXT:    ret
726 ; RV64I-MEDIUM-LABEL: load_const_large:
727 ; RV64I-MEDIUM:       # %bb.0: # %entry
728 ; RV64I-MEDIUM-NEXT:    lui a0, 524288
729 ; RV64I-MEDIUM-NEXT:    addiw a0, a0, -2048
730 ; RV64I-MEDIUM-NEXT:    lw a0, 0(a0)
731 ; RV64I-MEDIUM-NEXT:    ret
732 entry:
733   %0 = load i32, ptr inttoptr (i64 2147481600 to ptr)
734   ret i32 %0
737 %struct.S = type { i64, i64 }
739 define i64 @fold_addi_from_different_bb(i64 %k, i64 %n, ptr %a) nounwind {
740 ; RV32I-LABEL: fold_addi_from_different_bb:
741 ; RV32I:       # %bb.0: # %entry
742 ; RV32I-NEXT:    addi sp, sp, -48
743 ; RV32I-NEXT:    sw ra, 44(sp) # 4-byte Folded Spill
744 ; RV32I-NEXT:    sw s0, 40(sp) # 4-byte Folded Spill
745 ; RV32I-NEXT:    sw s1, 36(sp) # 4-byte Folded Spill
746 ; RV32I-NEXT:    sw s2, 32(sp) # 4-byte Folded Spill
747 ; RV32I-NEXT:    sw s3, 28(sp) # 4-byte Folded Spill
748 ; RV32I-NEXT:    sw s4, 24(sp) # 4-byte Folded Spill
749 ; RV32I-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
750 ; RV32I-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
751 ; RV32I-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
752 ; RV32I-NEXT:    mv s0, a4
753 ; RV32I-NEXT:    mv s1, a3
754 ; RV32I-NEXT:    mv s2, a2
755 ; RV32I-NEXT:    beqz a3, .LBB20_3
756 ; RV32I-NEXT:  # %bb.1: # %entry
757 ; RV32I-NEXT:    slti a1, s1, 0
758 ; RV32I-NEXT:    beqz a1, .LBB20_4
759 ; RV32I-NEXT:  .LBB20_2:
760 ; RV32I-NEXT:    li s3, 0
761 ; RV32I-NEXT:    li s4, 0
762 ; RV32I-NEXT:    j .LBB20_6
763 ; RV32I-NEXT:  .LBB20_3:
764 ; RV32I-NEXT:    seqz a1, s2
765 ; RV32I-NEXT:    bnez a1, .LBB20_2
766 ; RV32I-NEXT:  .LBB20_4: # %for.body.lr.ph
767 ; RV32I-NEXT:    li s5, 0
768 ; RV32I-NEXT:    li s6, 0
769 ; RV32I-NEXT:    li s3, 0
770 ; RV32I-NEXT:    li s4, 0
771 ; RV32I-NEXT:    slli a0, a0, 4
772 ; RV32I-NEXT:    add s7, s0, a0
773 ; RV32I-NEXT:  .LBB20_5: # %for.body
774 ; RV32I-NEXT:    # =>This Inner Loop Header: Depth=1
775 ; RV32I-NEXT:    mv a0, s0
776 ; RV32I-NEXT:    call f
777 ; RV32I-NEXT:    lw a0, 12(s7)
778 ; RV32I-NEXT:    lw a1, 8(s7)
779 ; RV32I-NEXT:    add a0, a0, s4
780 ; RV32I-NEXT:    add s3, a1, s3
781 ; RV32I-NEXT:    sltu s4, s3, a1
782 ; RV32I-NEXT:    addi s5, s5, 1
783 ; RV32I-NEXT:    seqz a1, s5
784 ; RV32I-NEXT:    add s6, s6, a1
785 ; RV32I-NEXT:    xor a1, s5, s2
786 ; RV32I-NEXT:    xor a2, s6, s1
787 ; RV32I-NEXT:    or a1, a1, a2
788 ; RV32I-NEXT:    add s4, a0, s4
789 ; RV32I-NEXT:    bnez a1, .LBB20_5
790 ; RV32I-NEXT:  .LBB20_6: # %for.cond.cleanup
791 ; RV32I-NEXT:    mv a0, s3
792 ; RV32I-NEXT:    mv a1, s4
793 ; RV32I-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
794 ; RV32I-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
795 ; RV32I-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
796 ; RV32I-NEXT:    lw s2, 32(sp) # 4-byte Folded Reload
797 ; RV32I-NEXT:    lw s3, 28(sp) # 4-byte Folded Reload
798 ; RV32I-NEXT:    lw s4, 24(sp) # 4-byte Folded Reload
799 ; RV32I-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
800 ; RV32I-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
801 ; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
802 ; RV32I-NEXT:    addi sp, sp, 48
803 ; RV32I-NEXT:    ret
805 ; RV32I-MEDIUM-LABEL: fold_addi_from_different_bb:
806 ; RV32I-MEDIUM:       # %bb.0: # %entry
807 ; RV32I-MEDIUM-NEXT:    addi sp, sp, -48
808 ; RV32I-MEDIUM-NEXT:    sw ra, 44(sp) # 4-byte Folded Spill
809 ; RV32I-MEDIUM-NEXT:    sw s0, 40(sp) # 4-byte Folded Spill
810 ; RV32I-MEDIUM-NEXT:    sw s1, 36(sp) # 4-byte Folded Spill
811 ; RV32I-MEDIUM-NEXT:    sw s2, 32(sp) # 4-byte Folded Spill
812 ; RV32I-MEDIUM-NEXT:    sw s3, 28(sp) # 4-byte Folded Spill
813 ; RV32I-MEDIUM-NEXT:    sw s4, 24(sp) # 4-byte Folded Spill
814 ; RV32I-MEDIUM-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
815 ; RV32I-MEDIUM-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
816 ; RV32I-MEDIUM-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
817 ; RV32I-MEDIUM-NEXT:    mv s0, a4
818 ; RV32I-MEDIUM-NEXT:    mv s1, a3
819 ; RV32I-MEDIUM-NEXT:    mv s2, a2
820 ; RV32I-MEDIUM-NEXT:    beqz a3, .LBB20_3
821 ; RV32I-MEDIUM-NEXT:  # %bb.1: # %entry
822 ; RV32I-MEDIUM-NEXT:    slti a1, s1, 0
823 ; RV32I-MEDIUM-NEXT:    beqz a1, .LBB20_4
824 ; RV32I-MEDIUM-NEXT:  .LBB20_2:
825 ; RV32I-MEDIUM-NEXT:    li s3, 0
826 ; RV32I-MEDIUM-NEXT:    li s4, 0
827 ; RV32I-MEDIUM-NEXT:    j .LBB20_6
828 ; RV32I-MEDIUM-NEXT:  .LBB20_3:
829 ; RV32I-MEDIUM-NEXT:    seqz a1, s2
830 ; RV32I-MEDIUM-NEXT:    bnez a1, .LBB20_2
831 ; RV32I-MEDIUM-NEXT:  .LBB20_4: # %for.body.lr.ph
832 ; RV32I-MEDIUM-NEXT:    li s5, 0
833 ; RV32I-MEDIUM-NEXT:    li s6, 0
834 ; RV32I-MEDIUM-NEXT:    li s3, 0
835 ; RV32I-MEDIUM-NEXT:    li s4, 0
836 ; RV32I-MEDIUM-NEXT:    slli a0, a0, 4
837 ; RV32I-MEDIUM-NEXT:    add s7, s0, a0
838 ; RV32I-MEDIUM-NEXT:  .LBB20_5: # %for.body
839 ; RV32I-MEDIUM-NEXT:    # =>This Inner Loop Header: Depth=1
840 ; RV32I-MEDIUM-NEXT:    mv a0, s0
841 ; RV32I-MEDIUM-NEXT:    call f
842 ; RV32I-MEDIUM-NEXT:    lw a0, 12(s7)
843 ; RV32I-MEDIUM-NEXT:    lw a1, 8(s7)
844 ; RV32I-MEDIUM-NEXT:    add a0, a0, s4
845 ; RV32I-MEDIUM-NEXT:    add s3, a1, s3
846 ; RV32I-MEDIUM-NEXT:    sltu s4, s3, a1
847 ; RV32I-MEDIUM-NEXT:    addi s5, s5, 1
848 ; RV32I-MEDIUM-NEXT:    seqz a1, s5
849 ; RV32I-MEDIUM-NEXT:    add s6, s6, a1
850 ; RV32I-MEDIUM-NEXT:    xor a1, s5, s2
851 ; RV32I-MEDIUM-NEXT:    xor a2, s6, s1
852 ; RV32I-MEDIUM-NEXT:    or a1, a1, a2
853 ; RV32I-MEDIUM-NEXT:    add s4, a0, s4
854 ; RV32I-MEDIUM-NEXT:    bnez a1, .LBB20_5
855 ; RV32I-MEDIUM-NEXT:  .LBB20_6: # %for.cond.cleanup
856 ; RV32I-MEDIUM-NEXT:    mv a0, s3
857 ; RV32I-MEDIUM-NEXT:    mv a1, s4
858 ; RV32I-MEDIUM-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
859 ; RV32I-MEDIUM-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
860 ; RV32I-MEDIUM-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
861 ; RV32I-MEDIUM-NEXT:    lw s2, 32(sp) # 4-byte Folded Reload
862 ; RV32I-MEDIUM-NEXT:    lw s3, 28(sp) # 4-byte Folded Reload
863 ; RV32I-MEDIUM-NEXT:    lw s4, 24(sp) # 4-byte Folded Reload
864 ; RV32I-MEDIUM-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
865 ; RV32I-MEDIUM-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
866 ; RV32I-MEDIUM-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
867 ; RV32I-MEDIUM-NEXT:    addi sp, sp, 48
868 ; RV32I-MEDIUM-NEXT:    ret
870 ; RV64I-LABEL: fold_addi_from_different_bb:
871 ; RV64I:       # %bb.0: # %entry
872 ; RV64I-NEXT:    addi sp, sp, -48
873 ; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
874 ; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
875 ; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
876 ; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
877 ; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
878 ; RV64I-NEXT:    blez a1, .LBB20_3
879 ; RV64I-NEXT:  # %bb.1: # %for.body.lr.ph
880 ; RV64I-NEXT:    mv s0, a2
881 ; RV64I-NEXT:    mv s1, a1
882 ; RV64I-NEXT:    li s2, 0
883 ; RV64I-NEXT:    slli a0, a0, 4
884 ; RV64I-NEXT:    add s3, a2, a0
885 ; RV64I-NEXT:  .LBB20_2: # %for.body
886 ; RV64I-NEXT:    # =>This Inner Loop Header: Depth=1
887 ; RV64I-NEXT:    mv a0, s0
888 ; RV64I-NEXT:    call f
889 ; RV64I-NEXT:    ld a0, 8(s3)
890 ; RV64I-NEXT:    addi s1, s1, -1
891 ; RV64I-NEXT:    add s2, a0, s2
892 ; RV64I-NEXT:    bnez s1, .LBB20_2
893 ; RV64I-NEXT:    j .LBB20_4
894 ; RV64I-NEXT:  .LBB20_3:
895 ; RV64I-NEXT:    li s2, 0
896 ; RV64I-NEXT:  .LBB20_4: # %for.cond.cleanup
897 ; RV64I-NEXT:    mv a0, s2
898 ; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
899 ; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
900 ; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
901 ; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
902 ; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
903 ; RV64I-NEXT:    addi sp, sp, 48
904 ; RV64I-NEXT:    ret
906 ; RV64I-MEDIUM-LABEL: fold_addi_from_different_bb:
907 ; RV64I-MEDIUM:       # %bb.0: # %entry
908 ; RV64I-MEDIUM-NEXT:    addi sp, sp, -48
909 ; RV64I-MEDIUM-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
910 ; RV64I-MEDIUM-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
911 ; RV64I-MEDIUM-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
912 ; RV64I-MEDIUM-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
913 ; RV64I-MEDIUM-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
914 ; RV64I-MEDIUM-NEXT:    blez a1, .LBB20_3
915 ; RV64I-MEDIUM-NEXT:  # %bb.1: # %for.body.lr.ph
916 ; RV64I-MEDIUM-NEXT:    mv s0, a2
917 ; RV64I-MEDIUM-NEXT:    mv s1, a1
918 ; RV64I-MEDIUM-NEXT:    li s2, 0
919 ; RV64I-MEDIUM-NEXT:    slli a0, a0, 4
920 ; RV64I-MEDIUM-NEXT:    add s3, a2, a0
921 ; RV64I-MEDIUM-NEXT:  .LBB20_2: # %for.body
922 ; RV64I-MEDIUM-NEXT:    # =>This Inner Loop Header: Depth=1
923 ; RV64I-MEDIUM-NEXT:    mv a0, s0
924 ; RV64I-MEDIUM-NEXT:    call f
925 ; RV64I-MEDIUM-NEXT:    ld a0, 8(s3)
926 ; RV64I-MEDIUM-NEXT:    addi s1, s1, -1
927 ; RV64I-MEDIUM-NEXT:    add s2, a0, s2
928 ; RV64I-MEDIUM-NEXT:    bnez s1, .LBB20_2
929 ; RV64I-MEDIUM-NEXT:    j .LBB20_4
930 ; RV64I-MEDIUM-NEXT:  .LBB20_3:
931 ; RV64I-MEDIUM-NEXT:    li s2, 0
932 ; RV64I-MEDIUM-NEXT:  .LBB20_4: # %for.cond.cleanup
933 ; RV64I-MEDIUM-NEXT:    mv a0, s2
934 ; RV64I-MEDIUM-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
935 ; RV64I-MEDIUM-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
936 ; RV64I-MEDIUM-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
937 ; RV64I-MEDIUM-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
938 ; RV64I-MEDIUM-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
939 ; RV64I-MEDIUM-NEXT:    addi sp, sp, 48
940 ; RV64I-MEDIUM-NEXT:    ret
941 entry:
942   %cmp4 = icmp sgt i64 %n, 0
943   br i1 %cmp4, label %for.body.lr.ph, label %for.cond.cleanup
945 for.body.lr.ph:                                   ; preds = %entry
946   ; TODO: when this GEP is expanded, the resulting `addi` should be folded
947   ; into the load in the loop body.
948   %y = getelementptr inbounds %struct.S, ptr %a, i64 %k, i32 1
949   br label %for.body
951 for.cond.cleanup:                                 ; preds = %for.body, %entry
952   %s.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
953   ret i64 %s.0.lcssa
955 for.body:                                         ; preds = %for.body.lr.ph, %for.body
956   %i.06 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
957   %s.05 = phi i64 [ 0, %for.body.lr.ph ], [ %add, %for.body ]
958   call void @f(ptr %a)
959   %0 = load i64, ptr %y, align 8
960   %add = add nsw i64 %0, %s.05
961   %inc = add nuw nsw i64 %i.06, 1
962   %exitcond.not = icmp eq i64 %inc, %n
963   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
966 declare void @f(ptr)
968 @g = external dso_local global [100 x [100 x i8]]
970 ; This test used to crash due to calling getVRegDef on X0.
971 define i32 @crash() {
972 ; RV32I-LABEL: crash:
973 ; RV32I:       # %bb.0: # %entry
974 ; RV32I-NEXT:    lui a0, %hi(g+401)
975 ; RV32I-NEXT:    lbu a0, %lo(g+401)(a0)
976 ; RV32I-NEXT:    seqz a0, a0
977 ; RV32I-NEXT:    sw a0, 0(zero)
978 ; RV32I-NEXT:    li a0, 0
979 ; RV32I-NEXT:    ret
981 ; RV32I-MEDIUM-LABEL: crash:
982 ; RV32I-MEDIUM:       # %bb.0: # %entry
983 ; RV32I-MEDIUM-NEXT:  .Lpcrel_hi14:
984 ; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g+401)
985 ; RV32I-MEDIUM-NEXT:    lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0)
986 ; RV32I-MEDIUM-NEXT:    seqz a0, a0
987 ; RV32I-MEDIUM-NEXT:    sw a0, 0(zero)
988 ; RV32I-MEDIUM-NEXT:    li a0, 0
989 ; RV32I-MEDIUM-NEXT:    ret
991 ; RV64I-LABEL: crash:
992 ; RV64I:       # %bb.0: # %entry
993 ; RV64I-NEXT:    lui a0, %hi(g+401)
994 ; RV64I-NEXT:    lbu a0, %lo(g+401)(a0)
995 ; RV64I-NEXT:    seqz a0, a0
996 ; RV64I-NEXT:    sw a0, 0(zero)
997 ; RV64I-NEXT:    li a0, 0
998 ; RV64I-NEXT:    ret
1000 ; RV64I-MEDIUM-LABEL: crash:
1001 ; RV64I-MEDIUM:       # %bb.0: # %entry
1002 ; RV64I-MEDIUM-NEXT:  .Lpcrel_hi14:
1003 ; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(g+401)
1004 ; RV64I-MEDIUM-NEXT:    lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0)
1005 ; RV64I-MEDIUM-NEXT:    seqz a0, a0
1006 ; RV64I-MEDIUM-NEXT:    sw a0, 0(zero)
1007 ; RV64I-MEDIUM-NEXT:    li a0, 0
1008 ; RV64I-MEDIUM-NEXT:    ret
1009 entry:
1010   %idxprom7.peel = sext i32 1 to i64
1011   br label %for.inc.peel
1013 for.inc.peel:                                     ; preds = %entry
1014   %arrayidx8.3.peel = getelementptr [100 x [100 x i8]], ptr @g, i64 0, i64 4, i64 %idxprom7.peel
1015   %0 = load i8, ptr %arrayidx8.3.peel, align 1
1016   %tobool.not.3.peel = icmp eq i8 %0, 0
1017   %spec.select = select i1 %tobool.not.3.peel, i32 1, i32 0
1018   store i32 %spec.select, ptr null, align 4
1019   ret i32 0