1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
2
3; Test folding constant offsets and symbols into load and store addresses under
4; a variety of circumstances.
5
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
9@g = external global [0 x i32], align 4
10
11; CHECK-LABEL: load_test0:
12; CHECK-NEXT: .functype load_test0 () -> (i32){{$}}
13; CHECK-NEXT: i32.const $push0=, 0{{$}}
14; CHECK-NEXT: i32.load  $push1=, g+40($pop0){{$}}
15; CHECK-NEXT: return    $pop1{{$}}
16define i32 @load_test0() {
17  %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
18  ret i32 %t
19}
20
21; CHECK-LABEL: load_test0_noinbounds:
22; CHECK-NEXT: .functype load_test0_noinbounds () -> (i32){{$}}
23; CHECK-NEXT: i32.const $push0=, 0{{$}}
24; CHECK-NEXT: i32.load  $push1=, g+40($pop0){{$}}
25; CHECK-NEXT: return    $pop1{{$}}
26define i32 @load_test0_noinbounds() {
27  %t = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
28  ret i32 %t
29}
30
31; TODO: load_test1 - load_test8 are disabled because folding GA+reg is disabled
32; (there are cases where the value in the reg can be negative).
33; Likewise for stores.
34
35; CHECK-LABEL: load_test1:
36; CHECK-NEXT: .functype load_test1 (i32) -> (i32){{$}}
37; CHECK-NEXT: i32.const $push0=, 2{{$}}
38; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
39; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
40; CHECK-NEX T: return    $pop2{{$}}
41define i32 @load_test1(i32 %n) {
42  %add = add nsw i32 %n, 10
43  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
44  %t = load i32, i32* %arrayidx, align 4
45  ret i32 %t
46}
47
48; CHECK-LABEL: load_test2:
49; CHECK-NEXT: .functype load_test2 (i32) -> (i32){{$}}
50; CHECK-NEXT: i32.const $push0=, 2{{$}}
51; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
52; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
53; CHECK-NEX T: return    $pop2{{$}}
54define i32 @load_test2(i32 %n) {
55  %add = add nsw i32 10, %n
56  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
57  %t = load i32, i32* %arrayidx, align 4
58  ret i32 %t
59}
60
61; CHECK-LABEL: load_test3:
62; CHECK-NEXT: .functype load_test3 (i32) -> (i32){{$}}
63; CHECK-NEXT: i32.const $push0=, 2{{$}}
64; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
65; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
66; CHECK-NEX T: return    $pop2{{$}}
67define i32 @load_test3(i32 %n) {
68  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
69  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
70  %t = load i32, i32* %add.ptr1, align 4
71  ret i32 %t
72}
73
74; CHECK-LABEL: load_test4:
75; CHECK-NEXT: .functype load_test4 (i32) -> (i32){{$}}
76; CHECK-NEXT: i32.const $push0=, 2{{$}}
77; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
78; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
79; CHECK-NEX T: return    $pop2{{$}}
80define i32 @load_test4(i32 %n) {
81  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
82  %t = load i32, i32* %add.ptr, align 4
83  ret i32 %t
84}
85
86; CHECK-LABEL: load_test5:
87; CHECK-NEXT: .functype load_test5 (i32) -> (i32){{$}}
88; CHECK-NEXT: i32.const $push0=, 2{{$}}
89; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
90; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
91; CHECK-NEX T: return    $pop2{{$}}
92define i32 @load_test5(i32 %n) {
93  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
94  %t = load i32, i32* %add.ptr, align 4
95  ret i32 %t
96}
97
98; CHECK-LABEL: load_test6:
99; CHECK-NEXT: .functype load_test6 (i32) -> (i32){{$}}
100; CHECK-NEXT: i32.const $push0=, 2{{$}}
101; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
102; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
103; CHECK-NEX T: return    $pop2{{$}}
104define i32 @load_test6(i32 %n) {
105  %add = add nsw i32 %n, 10
106  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
107  %t = load i32, i32* %add.ptr, align 4
108  ret i32 %t
109}
110
111; CHECK-LABEL: load_test7:
112; CHECK-NEXT: .functype load_test7 (i32) -> (i32){{$}}
113; CHECK-NEXT: i32.const $push0=, 2{{$}}
114; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
115; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
116; CHECK-NEX T: return    $pop2{{$}}
117define i32 @load_test7(i32 %n) {
118  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
119  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
120  %t = load i32, i32* %add.ptr1, align 4
121  ret i32 %t
122}
123
124; CHECK-LABEL: load_test8:
125; CHECK-NEXT: .functype load_test8 (i32) -> (i32){{$}}
126; CHECK-NEXT: i32.const $push0=, 2{{$}}
127; CHECK-NEX T: i32.shl   $push1=, $0, $pop0{{$}}
128; CHECK-NEX T: i32.load  $push2=, g+40($pop1){{$}}
129; CHECK-NEX T: return    $pop2{{$}}
130define i32 @load_test8(i32 %n) {
131  %add = add nsw i32 10, %n
132  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
133  %t = load i32, i32* %add.ptr, align 4
134  ret i32 %t
135}
136
137; CHECK-LABEL: load_test9:
138; CHECK-NEXT: .functype load_test9 () -> (i32){{$}}
139; CHECK-NEXT: i32.const $push0=, 0{{$}}
140; CHECK-NEXT: i32.load  $push1=, g-40($pop0){{$}}
141; CHECK-NEXT: return    $pop1{{$}}
142define i32 @load_test9() {
143  %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4
144  ret i32 %t
145}
146
147; CHECK-LABEL: load_test10:
148; CHECK-NEXT: .functype load_test10 (i32) -> (i32){{$}}
149; CHECK-NEXT: i32.const $push0=, 2{{$}}
150; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
151; CHECK-NEXT: i32.const $push2=, g-40{{$}}
152; CHECK-NEXT: i32.add   $push3=, $pop1, $pop2{{$}}
153; CHECK-NEXT: i32.load  $push4=, 0($pop3){{$}}
154; CHECK-NEXT: return    $pop4{{$}}
155define i32 @load_test10(i32 %n) {
156  %add = add nsw i32 %n, -10
157  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
158  %t = load i32, i32* %arrayidx, align 4
159  ret i32 %t
160}
161
162; CHECK-LABEL: load_test11:
163; CHECK-NEXT: .functype load_test11 (i32) -> (i32){{$}}
164; CHECK-NEXT: i32.load  $push0=, 40($0){{$}}
165; CHECK-NEXT: return    $pop0{{$}}
166define i32 @load_test11(i32* %p) {
167  %arrayidx = getelementptr inbounds i32, i32* %p, i32 10
168  %t = load i32, i32* %arrayidx, align 4
169  ret i32 %t
170}
171
172; CHECK-LABEL: load_test11_noinbounds:
173; CHECK-NEXT: .functype load_test11_noinbounds (i32) -> (i32){{$}}
174; CHECK-NEXT: i32.const $push0=, 40{{$}}
175; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
176; CHECK-NEXT: i32.load  $push2=, 0($pop1){{$}}
177; CHECK-NEXT: return    $pop2{{$}}
178define i32 @load_test11_noinbounds(i32* %p) {
179  %arrayidx = getelementptr i32, i32* %p, i32 10
180  %t = load i32, i32* %arrayidx, align 4
181  ret i32 %t
182}
183
184; CHECK-LABEL: load_test12:
185; CHECK-NEXT: .functype load_test12 (i32, i32) -> (i32){{$}}
186; CHECK-NEXT: i32.const $push0=, 2{{$}}
187; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
188; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
189; CHECK-NEXT: i32.const $push3=, 40{{$}}
190; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
191; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
192; CHECK-NEXT: return    $pop5{{$}}
193define i32 @load_test12(i32* %p, i32 %n) {
194  %add = add nsw i32 %n, 10
195  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
196  %t = load i32, i32* %arrayidx, align 4
197  ret i32 %t
198}
199
200; CHECK-LABEL: load_test13:
201; CHECK-NEXT: .functype load_test13 (i32, i32) -> (i32){{$}}
202; CHECK-NEXT: i32.const $push0=, 2{{$}}
203; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
204; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
205; CHECK-NEXT: i32.const $push3=, 40{{$}}
206; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
207; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
208; CHECK-NEXT: return    $pop5{{$}}
209define i32 @load_test13(i32* %p, i32 %n) {
210  %add = add nsw i32 10, %n
211  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
212  %t = load i32, i32* %arrayidx, align 4
213  ret i32 %t
214}
215
216; CHECK-LABEL: load_test14:
217; CHECK-NEXT: .functype load_test14 (i32, i32) -> (i32){{$}}
218; CHECK-NEXT: i32.const $push0=, 2{{$}}
219; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
220; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
221; CHECK-NEXT: i32.load  $push3=, 40($pop2){{$}}
222; CHECK-NEXT: return    $pop3{{$}}
223define i32 @load_test14(i32* %p, i32 %n) {
224  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
225  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
226  %t = load i32, i32* %add.ptr1, align 4
227  ret i32 %t
228}
229
230; CHECK-LABEL: load_test15:
231; CHECK-NEXT: .functype load_test15 (i32, i32) -> (i32){{$}}
232; CHECK-NEXT: i32.const $push0=, 2{{$}}
233; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
234; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
235; CHECK-NEXT: i32.const $push3=, 40{{$}}
236; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
237; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
238; CHECK-NEXT: return    $pop5{{$}}
239define i32 @load_test15(i32* %p, i32 %n) {
240  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
241  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
242  %t = load i32, i32* %add.ptr1, align 4
243  ret i32 %t
244}
245
246; CHECK-LABEL: load_test16:
247; CHECK-NEXT: .functype load_test16 (i32, i32) -> (i32){{$}}
248; CHECK-NEXT: i32.const $push0=, 2{{$}}
249; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
250; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
251; CHECK-NEXT: i32.const $push3=, 40{{$}}
252; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
253; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
254; CHECK-NEXT: return    $pop5{{$}}
255define i32 @load_test16(i32* %p, i32 %n) {
256  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
257  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
258  %t = load i32, i32* %add.ptr1, align 4
259  ret i32 %t
260}
261
262; CHECK-LABEL: load_test17:
263; CHECK-NEXT: .functype load_test17 (i32, i32) -> (i32){{$}}
264; CHECK-NEXT: i32.const $push0=, 2{{$}}
265; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
266; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
267; CHECK-NEXT: i32.const $push3=, 40{{$}}
268; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
269; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
270; CHECK-NEXT: return    $pop5{{$}}
271define i32 @load_test17(i32* %p, i32 %n) {
272  %add = add nsw i32 %n, 10
273  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
274  %t = load i32, i32* %add.ptr, align 4
275  ret i32 %t
276}
277
278; CHECK-LABEL: load_test18:
279; CHECK-NEXT: .functype load_test18 (i32, i32) -> (i32){{$}}
280; CHECK-NEXT: i32.const $push0=, 2{{$}}
281; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
282; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
283; CHECK-NEXT: i32.load  $push3=, 40($pop2){{$}}
284; CHECK-NEXT: return    $pop3{{$}}
285define i32 @load_test18(i32* %p, i32 %n) {
286  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
287  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
288  %t = load i32, i32* %add.ptr1, align 4
289  ret i32 %t
290}
291
292; CHECK-LABEL: load_test19:
293; CHECK-NEXT: .functype load_test19 (i32, i32) -> (i32){{$}}
294; CHECK-NEXT: i32.const $push0=, 2{{$}}
295; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
296; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
297; CHECK-NEXT: i32.const $push3=, 40{{$}}
298; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
299; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
300; CHECK-NEXT: return    $pop5{{$}}
301define i32 @load_test19(i32* %p, i32 %n) {
302  %add = add nsw i32 10, %n
303  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
304  %t = load i32, i32* %add.ptr, align 4
305  ret i32 %t
306}
307
308; CHECK-LABEL: load_test20:
309; CHECK-NEXT: .functype load_test20 (i32) -> (i32){{$}}
310; CHECK-NEXT: i32.const $push0=, -40{{$}}
311; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
312; CHECK-NEXT: i32.load  $push2=, 0($pop1){{$}}
313; CHECK-NEXT: return    $pop2{{$}}
314define i32 @load_test20(i32* %p) {
315  %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10
316  %t = load i32, i32* %arrayidx, align 4
317  ret i32 %t
318}
319
320; CHECK-LABEL: load_test21:
321; CHECK-NEXT: .functype load_test21 (i32, i32) -> (i32){{$}}
322; CHECK-NEXT: i32.const $push0=, 2{{$}}
323; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
324; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
325; CHECK-NEXT: i32.const $push3=, -40{{$}}
326; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
327; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
328; CHECK-NEXT: return    $pop5{{$}}
329define i32 @load_test21(i32* %p, i32 %n) {
330  %add = add nsw i32 %n, -10
331  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
332  %t = load i32, i32* %arrayidx, align 4
333  ret i32 %t
334}
335
336; CHECK-LABEL: store_test0:
337; CHECK-NEXT: .functype store_test0 (i32) -> (){{$}}
338; CHECK-NEXT: i32.const $push0=, 0{{$}}
339; CHECK-NEXT: i32.store g+40($pop0), $0{{$}}
340; CHECK-NEXT: return{{$}}
341define void @store_test0(i32 %i) {
342  store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
343  ret void
344}
345
346; CHECK-LABEL: store_test0_noinbounds:
347; CHECK-NEXT: .functype store_test0_noinbounds (i32) -> (){{$}}
348; CHECK-NEXT: i32.const $push0=, 0{{$}}
349; CHECK-NEXT: i32.store g+40($pop0), $0{{$}}
350; CHECK-NEXT: return{{$}}
351define void @store_test0_noinbounds(i32 %i) {
352  store i32 %i, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
353  ret void
354}
355
356; CHECK-LABEL: store_test1:
357; CHECK-NEXT: .functype store_test1 (i32, i32) -> (){{$}}
358; CHECK-NEXT: i32.const $push0=, 2{{$}}
359; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
360; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
361; CHECK-NEX T: return{{$}}
362define void @store_test1(i32 %n, i32 %i) {
363  %add = add nsw i32 %n, 10
364  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
365  store i32 %i, i32* %arrayidx, align 4
366  ret void
367}
368
369; CHECK-LABEL: store_test2:
370; CHECK-NEXT: .functype store_test2 (i32, i32) -> (){{$}}
371; CHECK-NEXT: i32.const $push0=, 2{{$}}
372; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
373; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
374; CHECK-NEX T: return{{$}}
375define void @store_test2(i32 %n, i32 %i) {
376  %add = add nsw i32 10, %n
377  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
378  store i32 %i, i32* %arrayidx, align 4
379  ret void
380}
381
382; CHECK-LABEL: store_test3:
383; CHECK-NEXT: .functype store_test3 (i32, i32) -> (){{$}}
384; CHECK-NEXT: i32.const $push0=, 2{{$}}
385; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
386; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
387; CHECK-NEX T: return{{$}}
388define void @store_test3(i32 %n, i32 %i) {
389  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
390  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
391  store i32 %i, i32* %add.ptr1, align 4
392  ret void
393}
394
395; CHECK-LABEL: store_test4:
396; CHECK-NEXT: .functype store_test4 (i32, i32) -> (){{$}}
397; CHECK-NEXT: i32.const $push0=, 2{{$}}
398; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
399; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
400; CHECK-NEX T: return{{$}}
401define void @store_test4(i32 %n, i32 %i) {
402  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
403  store i32 %i, i32* %add.ptr, align 4
404  ret void
405}
406
407; CHECK-LABEL: store_test5:
408; CHECK-NEXT: .functype store_test5 (i32, i32) -> (){{$}}
409; CHECK-NEXT: i32.const $push0=, 2{{$}}
410; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
411; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
412; CHECK-NEX T: return{{$}}
413define void @store_test5(i32 %n, i32 %i) {
414  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
415  store i32 %i, i32* %add.ptr, align 4
416  ret void
417}
418
419; CHECK-LABEL: store_test6:
420; CHECK-NEXT: .functype store_test6 (i32, i32) -> (){{$}}
421; CHECK-NEXT: i32.const $push0=, 2{{$}}
422; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
423; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
424; CHECK-NEX T: return{{$}}
425define void @store_test6(i32 %n, i32 %i) {
426  %add = add nsw i32 %n, 10
427  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
428  store i32 %i, i32* %add.ptr, align 4
429  ret void
430}
431
432; CHECK-LABEL: store_test7:
433; CHECK-NEXT: .functype store_test7 (i32, i32) -> (){{$}}
434; CHECK-NEXT: i32.const $push0=, 2{{$}}
435; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
436; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
437; CHECK-NEX T: return{{$}}
438define void @store_test7(i32 %n, i32 %i) {
439  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
440  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
441  store i32 %i, i32* %add.ptr1, align 4
442  ret void
443}
444
445; CHECK-LABEL: store_test8:
446; CHECK-NEXT: .functype store_test8 (i32, i32) -> (){{$}}
447; CHECK-NEXT: i32.const $push0=, 2{{$}}
448; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
449; CHECK-NEX T: i32.store g+40($pop1), $1{{$}}
450; CHECK-NEX T: return{{$}}
451define void @store_test8(i32 %n, i32 %i) {
452  %add = add nsw i32 10, %n
453  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
454  store i32 %i, i32* %add.ptr, align 4
455  ret void
456}
457
458; CHECK-LABEL: store_test9:
459; CHECK-NEXT: .functype store_test9 (i32) -> (){{$}}
460; CHECK-NEXT: i32.const $push0=, 0{{$}}
461; CHECK-NEXT: i32.store g-40($pop0), $0{{$}}
462; CHECK-NEXT: return{{$}}
463define void @store_test9(i32 %i) {
464  store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4
465  ret void
466}
467
468; CHECK-LABEL: store_test10:
469; CHECK-NEXT: .functype store_test10 (i32, i32) -> (){{$}}
470; CHECK-NEXT: i32.const $push0=, 2{{$}}
471; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
472; CHECK-NEXT: i32.const $push2=, g-40{{$}}
473; CHECK-NEXT: i32.add   $push3=, $pop1, $pop2{{$}}
474; CHECK-NEXT: i32.store 0($pop3), $1{{$}}
475; CHECK-NEXT: return{{$}}
476define void @store_test10(i32 %n, i32 %i) {
477  %add = add nsw i32 %n, -10
478  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
479  store i32 %i, i32* %arrayidx, align 4
480  ret void
481}
482
483; CHECK-LABEL: store_test11:
484; CHECK-NEXT: .functype store_test11 (i32, i32) -> (){{$}}
485; CHECK-NEXT: i32.store 40($0), $1{{$}}
486; CHECK-NEXT: return{{$}}
487define void @store_test11(i32* %p, i32 %i) {
488  %arrayidx = getelementptr inbounds i32, i32* %p, i32 10
489  store i32 %i, i32* %arrayidx, align 4
490  ret void
491}
492
493; CHECK-LABEL: store_test11_noinbounds:
494; CHECK-NEXT: .functype store_test11_noinbounds (i32, i32) -> (){{$}}
495; CHECK-NEXT: i32.const $push0=, 40{{$}}
496; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
497; CHECK-NEXT: i32.store 0($pop1), $1{{$}}
498; CHECK-NEXT: return{{$}}
499define void @store_test11_noinbounds(i32* %p, i32 %i) {
500  %arrayidx = getelementptr i32, i32* %p, i32 10
501  store i32 %i, i32* %arrayidx, align 4
502  ret void
503}
504
505; CHECK-LABEL: store_test12:
506; CHECK-NEXT: .functype store_test12 (i32, i32, i32) -> (){{$}}
507; CHECK-NEXT: i32.const $push0=, 2{{$}}
508; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
509; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
510; CHECK-NEXT: i32.const $push3=, 40{{$}}
511; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
512; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
513; CHECK-NEXT: return{{$}}
514define void @store_test12(i32* %p, i32 %n, i32 %i) {
515  %add = add nsw i32 %n, 10
516  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
517  store i32 %i, i32* %arrayidx, align 4
518  ret void
519}
520
521; CHECK-LABEL: store_test13:
522; CHECK-NEXT: .functype store_test13 (i32, i32, i32) -> (){{$}}
523; CHECK-NEXT: i32.const $push0=, 2{{$}}
524; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
525; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
526; CHECK-NEXT: i32.const $push3=, 40{{$}}
527; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
528; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
529; CHECK-NEXT: return{{$}}
530define void @store_test13(i32* %p, i32 %n, i32 %i) {
531  %add = add nsw i32 10, %n
532  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
533  store i32 %i, i32* %arrayidx, align 4
534  ret void
535}
536
537; CHECK-LABEL: store_test14:
538; CHECK-NEXT: .functype store_test14 (i32, i32, i32) -> (){{$}}
539; CHECK-NEXT: i32.const $push0=, 2{{$}}
540; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
541; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
542; CHECK-NEXT: i32.store 40($pop2), $2{{$}}
543; CHECK-NEXT: return{{$}}
544define void @store_test14(i32* %p, i32 %n, i32 %i) {
545  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
546  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
547  store i32 %i, i32* %add.ptr1, align 4
548  ret void
549}
550
551; CHECK-LABEL: store_test15:
552; CHECK-NEXT: .functype store_test15 (i32, i32, i32) -> (){{$}}
553; CHECK-NEXT: i32.const $push0=, 2{{$}}
554; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
555; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
556; CHECK-NEXT: i32.const $push3=, 40{{$}}
557; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
558; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
559; CHECK-NEXT: return{{$}}
560define void @store_test15(i32* %p, i32 %n, i32 %i) {
561  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
562  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
563  store i32 %i, i32* %add.ptr1, align 4
564  ret void
565}
566
567; CHECK-LABEL: store_test16:
568; CHECK-NEXT: .functype store_test16 (i32, i32, i32) -> (){{$}}
569; CHECK-NEXT: i32.const $push0=, 2{{$}}
570; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
571; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
572; CHECK-NEXT: i32.const $push3=, 40{{$}}
573; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
574; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
575; CHECK-NEXT: return{{$}}
576define void @store_test16(i32* %p, i32 %n, i32 %i) {
577  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
578  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
579  store i32 %i, i32* %add.ptr1, align 4
580  ret void
581}
582
583; CHECK-LABEL: store_test17:
584; CHECK-NEXT: .functype store_test17 (i32, i32, i32) -> (){{$}}
585; CHECK-NEXT: i32.const $push0=, 2{{$}}
586; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
587; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
588; CHECK-NEXT: i32.const $push3=, 40{{$}}
589; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
590; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
591; CHECK-NEXT: return{{$}}
592define void @store_test17(i32* %p, i32 %n, i32 %i) {
593  %add = add nsw i32 %n, 10
594  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
595  store i32 %i, i32* %add.ptr, align 4
596  ret void
597}
598
599; CHECK-LABEL: store_test18:
600; CHECK-NEXT: .functype store_test18 (i32, i32, i32) -> (){{$}}
601; CHECK-NEXT: i32.const $push0=, 2{{$}}
602; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
603; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
604; CHECK-NEXT: i32.store 40($pop2), $2{{$}}
605; CHECK-NEXT: return{{$}}
606define void @store_test18(i32* %p, i32 %n, i32 %i) {
607  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
608  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
609  store i32 %i, i32* %add.ptr1, align 4
610  ret void
611}
612
613; CHECK-LABEL: store_test19:
614; CHECK-NEXT: .functype store_test19 (i32, i32, i32) -> (){{$}}
615; CHECK-NEXT: i32.const $push0=, 2{{$}}
616; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
617; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
618; CHECK-NEXT: i32.const $push3=, 40{{$}}
619; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
620; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
621; CHECK-NEXT: return{{$}}
622define void @store_test19(i32* %p, i32 %n, i32 %i) {
623  %add = add nsw i32 10, %n
624  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
625  store i32 %i, i32* %add.ptr, align 4
626  ret void
627}
628
629; CHECK-LABEL: store_test20:
630; CHECK-NEXT: .functype store_test20 (i32, i32) -> (){{$}}
631; CHECK-NEXT: i32.const $push0=, -40{{$}}
632; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
633; CHECK-NEXT: i32.store 0($pop1), $1{{$}}
634; CHECK-NEXT: return{{$}}
635define void @store_test20(i32* %p, i32 %i) {
636  %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10
637  store i32 %i, i32* %arrayidx, align 4
638  ret void
639}
640
641; CHECK-LABEL: store_test21:
642; CHECK-NEXT: .functype store_test21 (i32, i32, i32) -> (){{$}}
643; CHECK-NEXT: i32.const $push0=, 2{{$}}
644; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
645; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
646; CHECK-NEXT: i32.const $push3=, -40{{$}}
647; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
648; CHECK-NEXT: i32.store 0($pop4), $2{{$}}
649; CHECK-NEXT: return{{$}}
650define void @store_test21(i32* %p, i32 %n, i32 %i) {
651  %add = add nsw i32 %n, -10
652  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
653  store i32 %i, i32* %arrayidx, align 4
654  ret void
655}
656