[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / RISCV / fold-addi-loadstore.ll
bloba2972908d3c7494f8ba73c09aff89f92274d780b
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=riscv64 -verify-machineinstrs < %s \
5 ; RUN:   | FileCheck -check-prefix=RV64I %s
7 ; We can often fold an ADDI into the offset of load/store instructions:
8 ;   (load (addi base, off1), off2) -> (load base, off1+off2)
9 ;   (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
10 ; This is possible when the off1+off2 continues to fit the 12-bit immediate.
11 ; Check if we do the fold under various conditions. If off1 is (the low part of)
12 ; an address the fold's safety depends on the variable's alignment.
14 @g_0 = dso_local global i64 0
15 @g_1 = dso_local global i64 0, align 1
16 @g_2 = dso_local global i64 0, align 2
17 @g_4 = dso_local global i64 0, align 4
18 @g_8 = dso_local global i64 0, align 8
19 @g_16 = dso_local global i64 0, align 16
21 define dso_local i64 @load_g_0() nounwind {
22 ; RV32I-LABEL: load_g_0:
23 ; RV32I:       # %bb.0: # %entry
24 ; RV32I-NEXT:    lui a1, %hi(g_0)
25 ; RV32I-NEXT:    lw a0, %lo(g_0)(a1)
26 ; RV32I-NEXT:    lw a1, %lo(g_0+4)(a1)
27 ; RV32I-NEXT:    ret
29 ; RV64I-LABEL: load_g_0:
30 ; RV64I:       # %bb.0: # %entry
31 ; RV64I-NEXT:    lui a0, %hi(g_0)
32 ; RV64I-NEXT:    ld a0, %lo(g_0)(a0)
33 ; RV64I-NEXT:    ret
34 entry:
35   %0 = load i64, i64* @g_0
36   ret i64 %0
39 define dso_local i64 @load_g_1() nounwind {
40 ; RV32I-LABEL: load_g_1:
41 ; RV32I:       # %bb.0: # %entry
42 ; RV32I-NEXT:    lui a1, %hi(g_1)
43 ; RV32I-NEXT:    lw a0, %lo(g_1)(a1)
44 ; RV32I-NEXT:    addi a1, a1, %lo(g_1)
45 ; RV32I-NEXT:    lw a1, 4(a1)
46 ; RV32I-NEXT:    ret
48 ; RV64I-LABEL: load_g_1:
49 ; RV64I:       # %bb.0: # %entry
50 ; RV64I-NEXT:    lui a0, %hi(g_1)
51 ; RV64I-NEXT:    ld a0, %lo(g_1)(a0)
52 ; RV64I-NEXT:    ret
53 entry:
54   %0 = load i64, i64* @g_1
55   ret i64 %0
58 define dso_local i64 @load_g_2() nounwind {
59 ; RV32I-LABEL: load_g_2:
60 ; RV32I:       # %bb.0: # %entry
61 ; RV32I-NEXT:    lui a1, %hi(g_2)
62 ; RV32I-NEXT:    lw a0, %lo(g_2)(a1)
63 ; RV32I-NEXT:    addi a1, a1, %lo(g_2)
64 ; RV32I-NEXT:    lw a1, 4(a1)
65 ; RV32I-NEXT:    ret
67 ; RV64I-LABEL: load_g_2:
68 ; RV64I:       # %bb.0: # %entry
69 ; RV64I-NEXT:    lui a0, %hi(g_2)
70 ; RV64I-NEXT:    ld a0, %lo(g_2)(a0)
71 ; RV64I-NEXT:    ret
72 entry:
73   %0 = load i64, i64* @g_2
74   ret i64 %0
77 define dso_local i64 @load_g_4() nounwind {
78 ; RV32I-LABEL: load_g_4:
79 ; RV32I:       # %bb.0: # %entry
80 ; RV32I-NEXT:    lui a1, %hi(g_4)
81 ; RV32I-NEXT:    lw a0, %lo(g_4)(a1)
82 ; RV32I-NEXT:    addi a1, a1, %lo(g_4)
83 ; RV32I-NEXT:    lw a1, 4(a1)
84 ; RV32I-NEXT:    ret
86 ; RV64I-LABEL: load_g_4:
87 ; RV64I:       # %bb.0: # %entry
88 ; RV64I-NEXT:    lui a0, %hi(g_4)
89 ; RV64I-NEXT:    ld a0, %lo(g_4)(a0)
90 ; RV64I-NEXT:    ret
91 entry:
92   %0 = load i64, i64* @g_4
93   ret i64 %0
96 define dso_local i64 @load_g_8() nounwind {
97 ; RV32I-LABEL: load_g_8:
98 ; RV32I:       # %bb.0: # %entry
99 ; RV32I-NEXT:    lui a1, %hi(g_8)
100 ; RV32I-NEXT:    lw a0, %lo(g_8)(a1)
101 ; RV32I-NEXT:    lw a1, %lo(g_8+4)(a1)
102 ; RV32I-NEXT:    ret
104 ; RV64I-LABEL: load_g_8:
105 ; RV64I:       # %bb.0: # %entry
106 ; RV64I-NEXT:    lui a0, %hi(g_8)
107 ; RV64I-NEXT:    ld a0, %lo(g_8)(a0)
108 ; RV64I-NEXT:    ret
109 entry:
110   %0 = load i64, i64* @g_8
111   ret i64 %0
114 define dso_local i64 @load_g_16() nounwind {
115 ; RV32I-LABEL: load_g_16:
116 ; RV32I:       # %bb.0: # %entry
117 ; RV32I-NEXT:    lui a1, %hi(g_16)
118 ; RV32I-NEXT:    lw a0, %lo(g_16)(a1)
119 ; RV32I-NEXT:    lw a1, %lo(g_16+4)(a1)
120 ; RV32I-NEXT:    ret
122 ; RV64I-LABEL: load_g_16:
123 ; RV64I:       # %bb.0: # %entry
124 ; RV64I-NEXT:    lui a0, %hi(g_16)
125 ; RV64I-NEXT:    ld a0, %lo(g_16)(a0)
126 ; RV64I-NEXT:    ret
127 entry:
128   %0 = load i64, i64* @g_16
129   ret i64 %0
132 define dso_local void @store_g_4() nounwind {
133 ; RV32I-LABEL: store_g_4:
134 ; RV32I:       # %bb.0: # %entry
135 ; RV32I-NEXT:    lui a0, %hi(g_4)
136 ; RV32I-NEXT:    sw zero, %lo(g_4)(a0)
137 ; RV32I-NEXT:    addi a0, a0, %lo(g_4)
138 ; RV32I-NEXT:    sw zero, 4(a0)
139 ; RV32I-NEXT:    ret
141 ; RV64I-LABEL: store_g_4:
142 ; RV64I:       # %bb.0: # %entry
143 ; RV64I-NEXT:    lui a0, %hi(g_4)
144 ; RV64I-NEXT:    sd zero, %lo(g_4)(a0)
145 ; RV64I-NEXT:    ret
146 entry:
147    store i64 0, i64* @g_4
148    ret void
151 define dso_local void @store_g_8() nounwind {
152 ; RV32I-LABEL: store_g_8:
153 ; RV32I:       # %bb.0: # %entry
154 ; RV32I-NEXT:    lui a0, %hi(g_8)
155 ; RV32I-NEXT:    sw zero, %lo(g_8+4)(a0)
156 ; RV32I-NEXT:    sw zero, %lo(g_8)(a0)
157 ; RV32I-NEXT:    ret
159 ; RV64I-LABEL: store_g_8:
160 ; RV64I:       # %bb.0: # %entry
161 ; RV64I-NEXT:    lui a0, %hi(g_8)
162 ; RV64I-NEXT:    sd zero, %lo(g_8)(a0)
163 ; RV64I-NEXT:    ret
164 entry:
165    store i64 0, i64* @g_8
166    ret void
169 ; Check for folds in accesses to the second element of an i64 array.
171 @ga_8 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 8
172 @ga_16 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 16
174 define dso_local i64 @load_ga_8() nounwind {
175 ; RV32I-LABEL: load_ga_8:
176 ; RV32I:       # %bb.0: # %entry
177 ; RV32I-NEXT:    lui a0, %hi(ga_8)
178 ; RV32I-NEXT:    addi a1, a0, %lo(ga_8)
179 ; RV32I-NEXT:    lw a0, 8(a1)
180 ; RV32I-NEXT:    lw a1, 12(a1)
181 ; RV32I-NEXT:    ret
183 ; RV64I-LABEL: load_ga_8:
184 ; RV64I:       # %bb.0: # %entry
185 ; RV64I-NEXT:    lui a0, %hi(ga_8+8)
186 ; RV64I-NEXT:    ld a0, %lo(ga_8+8)(a0)
187 ; RV64I-NEXT:    ret
188 entry:
189   %0 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @ga_8, i32 0, i32 1)
190   ret i64 %0
193 define dso_local i64 @load_ga_16() nounwind {
194 ; RV32I-LABEL: load_ga_16:
195 ; RV32I:       # %bb.0: # %entry
196 ; RV32I-NEXT:    lui a1, %hi(ga_16)
197 ; RV32I-NEXT:    lw a0, %lo(ga_16+8)(a1)
198 ; RV32I-NEXT:    lw a1, %lo(ga_16+12)(a1)
199 ; RV32I-NEXT:    ret
201 ; RV64I-LABEL: load_ga_16:
202 ; RV64I:       # %bb.0: # %entry
203 ; RV64I-NEXT:    lui a0, %hi(ga_16)
204 ; RV64I-NEXT:    ld a0, %lo(ga_16+8)(a0)
205 ; RV64I-NEXT:    ret
206 entry:
207   %0 = load i64, i64* getelementptr inbounds ([2 x i64], [2 x i64]* @ga_16, i32 0, i32 1)
208   ret i64 %0
211 ; Check for folds in accesses to thread-local variables.
213 @tl_4 = dso_local thread_local global i64 0, align 4
214 @tl_8 = dso_local thread_local global i64 0, align 8
216 define dso_local i64 @load_tl_4() nounwind {
217 ; RV32I-LABEL: load_tl_4:
218 ; RV32I:       # %bb.0: # %entry
219 ; RV32I-NEXT:    lui a0, %tprel_hi(tl_4)
220 ; RV32I-NEXT:    add a1, a0, tp, %tprel_add(tl_4)
221 ; RV32I-NEXT:    lw a0, %tprel_lo(tl_4)(a1)
222 ; RV32I-NEXT:    addi a1, a1, %tprel_lo(tl_4)
223 ; RV32I-NEXT:    lw a1, 4(a1)
224 ; RV32I-NEXT:    ret
226 ; RV64I-LABEL: load_tl_4:
227 ; RV64I:       # %bb.0: # %entry
228 ; RV64I-NEXT:    lui a0, %tprel_hi(tl_4)
229 ; RV64I-NEXT:    add a0, a0, tp, %tprel_add(tl_4)
230 ; RV64I-NEXT:    ld a0, %tprel_lo(tl_4)(a0)
231 ; RV64I-NEXT:    ret
232 entry:
233   %0 = load i64, i64* @tl_4
234   ret i64 %0
237 define dso_local i64 @load_tl_8() nounwind {
238 ; RV32I-LABEL: load_tl_8:
239 ; RV32I:       # %bb.0: # %entry
240 ; RV32I-NEXT:    lui a0, %tprel_hi(tl_8)
241 ; RV32I-NEXT:    add a1, a0, tp, %tprel_add(tl_8)
242 ; RV32I-NEXT:    lw a0, %tprel_lo(tl_8)(a1)
243 ; RV32I-NEXT:    lw a1, %tprel_lo(tl_8+4)(a1)
244 ; RV32I-NEXT:    ret
246 ; RV64I-LABEL: load_tl_8:
247 ; RV64I:       # %bb.0: # %entry
248 ; RV64I-NEXT:    lui a0, %tprel_hi(tl_8)
249 ; RV64I-NEXT:    add a0, a0, tp, %tprel_add(tl_8)
250 ; RV64I-NEXT:    ld a0, %tprel_lo(tl_8)(a0)
251 ; RV64I-NEXT:    ret
252 entry:
253   %0 = load i64, i64* @tl_8
254   ret i64 %0
257 define dso_local i64 @load_const_ok() nounwind {
258 ; RV32I-LABEL: load_const_ok:
259 ; RV32I:       # %bb.0: # %entry
260 ; RV32I-NEXT:    lw a0, 2040(zero)
261 ; RV32I-NEXT:    lw a1, 2044(zero)
262 ; RV32I-NEXT:    ret
264 ; RV64I-LABEL: load_const_ok:
265 ; RV64I:       # %bb.0: # %entry
266 ; RV64I-NEXT:    ld a0, 2040(zero)
267 ; RV64I-NEXT:    ret
268 entry:
269   %0 = load i64, i64* inttoptr (i32 2040 to i64*)
270   ret i64 %0
273 define dso_local i64 @load_cost_overflow() nounwind {
274 ; RV32I-LABEL: load_cost_overflow:
275 ; RV32I:       # %bb.0: # %entry
276 ; RV32I-NEXT:    lui a0, 1
277 ; RV32I-NEXT:    lw a1, -2048(a0)
278 ; RV32I-NEXT:    lw a0, 2044(zero)
279 ; RV32I-NEXT:    ret
281 ; RV64I-LABEL: load_cost_overflow:
282 ; RV64I:       # %bb.0: # %entry
283 ; RV64I-NEXT:    ld a0, 2044(zero)
284 ; RV64I-NEXT:    ret
285 entry:
286   %0 = load i64, i64* inttoptr (i64 2044 to i64*)
287   ret i64 %0