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)
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)
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
55 %0 = load i64, ptr @g_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)
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)
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
90 %0 = load i64, ptr @g_1
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)
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)
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
125 %0 = load i64, ptr @g_2
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)
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)
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
160 %0 = load i64, ptr @g_4
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)
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)
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
194 %0 = load i64, ptr @g_8
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)
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)
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
228 %0 = load i64, ptr @g_16
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)
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)
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
263 store i64 0, ptr @g_4
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)
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)
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
297 store i64 0, ptr @g_8
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)
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)
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
341 %0 = load i32, ptr @g_4_i32
343 store i32 %inc, ptr @g_4_i32
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:
357 ; RV32I-NEXT: lui a0, %hi(ga+4)
358 ; RV32I-NEXT: lw a0, %lo(ga+4)(a0)
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:
370 ; RV64I-NEXT: lui a0, %hi(ga+4)
371 ; RV64I-NEXT: lw a0, %lo(ga+4)(a0)
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
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)
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)
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
420 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_8, i32 0, i32 1)
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)
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)
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
454 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_16, i32 0, i32 1)
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)
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)
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
496 %0 = load ptr, ptr blockaddress(@load_ba_1, %label)
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)
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)
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
537 %0 = load ptr, ptr getelementptr inbounds (i8, ptr blockaddress(@load_ba_2, %label), i32 8)
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)
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)
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
579 %0 = load i64, ptr @tl_4
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)
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)
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
614 %0 = load i64, ptr @tl_8
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)
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)
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
641 %0 = load i64, ptr inttoptr (i32 2040 to ptr)
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)
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)
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
670 %0 = load i64, ptr inttoptr (i64 2044 to ptr)
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)
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)
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
699 %0 = load i32, ptr inttoptr (i64 4080 to ptr)
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
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)
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)
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
733 %0 = load i32, ptr inttoptr (i64 2147481600 to ptr)
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
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
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
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
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
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
951 for.cond.cleanup: ; preds = %for.body, %entry
952 %s.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
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 ]
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
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
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
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
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