blob: 75a0bc9ab6c60af33be946b26d1487747d15b43d [file] [log] [blame]
Dan Gohman4b9d7912015-12-15 22:01:29 +00001; RUN: llc < %s -asm-verbose=false | FileCheck %s
2
3; Test constant load and store address offsets.
4
5target datalayout = "e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8; With an nuw add, we can fold an offset.
9
10; CHECK-LABEL: load_i32_with_folded_offset:
11; CHECK: i32.load $push0=, 24($0){{$}}
12define i32 @load_i32_with_folded_offset(i32* %p) {
13 %q = ptrtoint i32* %p to i32
14 %r = add nuw i32 %q, 24
15 %s = inttoptr i32 %r to i32*
16 %t = load i32, i32* %s
17 ret i32 %t
18}
19
20; Without nuw, and even with nsw, we can't fold an offset.
21
22; CHECK-LABEL: load_i32_with_unfolded_offset:
23; CHECK: i32.const $push0=, 24{{$}}
24; CHECK: i32.add $push1=, $0, $pop0{{$}}
25; CHECK: i32.load $push2=, 0($pop1){{$}}
26define i32 @load_i32_with_unfolded_offset(i32* %p) {
27 %q = ptrtoint i32* %p to i32
28 %r = add nsw i32 %q, 24
29 %s = inttoptr i32 %r to i32*
30 %t = load i32, i32* %s
31 ret i32 %t
32}
33
34; Same as above but with i64.
35
36; CHECK-LABEL: load_i64_with_folded_offset:
37; CHECK: i64.load $push0=, 24($0){{$}}
38define i64 @load_i64_with_folded_offset(i64* %p) {
39 %q = ptrtoint i64* %p to i32
40 %r = add nuw i32 %q, 24
41 %s = inttoptr i32 %r to i64*
42 %t = load i64, i64* %s
43 ret i64 %t
44}
45
46; Same as above but with i64.
47
48; CHECK-LABEL: load_i64_with_unfolded_offset:
49; CHECK: i32.const $push0=, 24{{$}}
50; CHECK: i32.add $push1=, $0, $pop0{{$}}
51; CHECK: i64.load $push2=, 0($pop1){{$}}
52define i64 @load_i64_with_unfolded_offset(i64* %p) {
53 %q = ptrtoint i64* %p to i32
54 %r = add nsw i32 %q, 24
55 %s = inttoptr i32 %r to i64*
56 %t = load i64, i64* %s
57 ret i64 %t
58}
59
60; Same as above but with store.
61
62; CHECK-LABEL: store_i32_with_folded_offset:
63; CHECK: i32.store $discard=, 24($0), $pop0{{$}}
64define void @store_i32_with_folded_offset(i32* %p) {
65 %q = ptrtoint i32* %p to i32
66 %r = add nuw i32 %q, 24
67 %s = inttoptr i32 %r to i32*
68 store i32 0, i32* %s
69 ret void
70}
71
72; Same as above but with store.
73
74; CHECK-LABEL: store_i32_with_unfolded_offset:
75; CHECK: i32.const $push0=, 24{{$}}
76; CHECK: i32.add $push1=, $0, $pop0{{$}}
77; CHECK: i32.store $discard=, 0($pop1), $pop2{{$}}
78define void @store_i32_with_unfolded_offset(i32* %p) {
79 %q = ptrtoint i32* %p to i32
80 %r = add nsw i32 %q, 24
81 %s = inttoptr i32 %r to i32*
82 store i32 0, i32* %s
83 ret void
84}
85
86; Same as above but with store with i64.
87
88; CHECK-LABEL: store_i64_with_folded_offset:
89; CHECK: i64.store $discard=, 24($0), $pop0{{$}}
90define void @store_i64_with_folded_offset(i64* %p) {
91 %q = ptrtoint i64* %p to i32
92 %r = add nuw i32 %q, 24
93 %s = inttoptr i32 %r to i64*
94 store i64 0, i64* %s
95 ret void
96}
97
98; Same as above but with store with i64.
99
100; CHECK-LABEL: store_i64_with_unfolded_offset:
101; CHECK: i32.const $push0=, 24{{$}}
102; CHECK: i32.add $push1=, $0, $pop0{{$}}
103; CHECK: i64.store $discard=, 0($pop1), $pop2{{$}}
104define void @store_i64_with_unfolded_offset(i64* %p) {
105 %q = ptrtoint i64* %p to i32
106 %r = add nsw i32 %q, 24
107 %s = inttoptr i32 %r to i64*
108 store i64 0, i64* %s
109 ret void
110}
111
112; When loading from a fixed address, materialize a zero.
113
114; CHECK-LABEL: load_i32_from_numeric_address
115; CHECK: i32.const $push0=, 0{{$}}
116; CHECK: i32.load $push1=, 42($pop0){{$}}
117define i32 @load_i32_from_numeric_address() {
118 %s = inttoptr i32 42 to i32*
119 %t = load i32, i32* %s
120 ret i32 %t
121}
122
123; CHECK-LABEL: load_i32_from_global_address
124; CHECK: i32.const $push0=, 0{{$}}
125; CHECK: i32.load $push1=, gv($pop0){{$}}
126@gv = global i32 0
127define i32 @load_i32_from_global_address() {
128 %t = load i32, i32* @gv
129 ret i32 %t
130}
131
132; CHECK-LABEL: store_i32_to_numeric_address:
133; CHECK: i32.const $0=, 0{{$}}
134; CHECK: i32.store $discard=, 42($0), $0{{$}}
135define void @store_i32_to_numeric_address() {
136 %s = inttoptr i32 42 to i32*
137 store i32 0, i32* %s
138 ret void
139}
140
141; CHECK-LABEL: store_i32_to_global_address:
142; CHECK: i32.const $0=, 0{{$}}
143; CHECK: i32.store $discard=, gv($0), $0{{$}}
144define void @store_i32_to_global_address() {
145 store i32 0, i32* @gv
146 ret void
147}
148
149; Fold an offset into a sign-extending load.
150
151; CHECK-LABEL: load_i8_s_with_folded_offset:
152; CHECK: i32.load8_s $push0=, 24($0){{$}}
153define i32 @load_i8_s_with_folded_offset(i8* %p) {
154 %q = ptrtoint i8* %p to i32
155 %r = add nuw i32 %q, 24
156 %s = inttoptr i32 %r to i8*
157 %t = load i8, i8* %s
158 %u = sext i8 %t to i32
159 ret i32 %u
160}
161
162; Fold an offset into a zero-extending load.
163
164; CHECK-LABEL: load_i8_u_with_folded_offset:
165; CHECK: i32.load8_u $push0=, 24($0){{$}}
166define i32 @load_i8_u_with_folded_offset(i8* %p) {
167 %q = ptrtoint i8* %p to i32
168 %r = add nuw i32 %q, 24
169 %s = inttoptr i32 %r to i8*
170 %t = load i8, i8* %s
171 %u = zext i8 %t to i32
172 ret i32 %u
173}
174
175; Fold an offset into a truncating store.
176
177; CHECK-LABEL: store_i8_with_folded_offset:
178; CHECK: i32.store8 $discard=, 24($0), $pop0{{$}}
179define void @store_i8_with_folded_offset(i8* %p) {
180 %q = ptrtoint i8* %p to i32
181 %r = add nuw i32 %q, 24
182 %s = inttoptr i32 %r to i8*
183 store i8 0, i8* %s
184 ret void
185}