1 ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
3 ; Test loads and stores with custom alignment values.
5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6 target triple = "wasm32-unknown-unknown"
8 ;===----------------------------------------------------------------------------
10 ;===----------------------------------------------------------------------------
12 ; CHECK-LABEL: ldi64_a1:
13 ; CHECK-NEXT: .functype ldi64_a1 (i32) -> (i64){{$}}
14 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
15 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
16 define i64 @ldi64_a1(i64 *%p) {
17 %v = load i64, i64* %p, align 1
21 ; CHECK-LABEL: ldi64_a2:
22 ; CHECK-NEXT: .functype ldi64_a2 (i32) -> (i64){{$}}
23 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
24 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
25 define i64 @ldi64_a2(i64 *%p) {
26 %v = load i64, i64* %p, align 2
30 ; CHECK-LABEL: ldi64_a4:
31 ; CHECK-NEXT: .functype ldi64_a4 (i32) -> (i64){{$}}
32 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}}
33 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
34 define i64 @ldi64_a4(i64 *%p) {
35 %v = load i64, i64* %p, align 4
39 ; 8 is the default alignment for i64 so no attribute is needed.
41 ; CHECK-LABEL: ldi64_a8:
42 ; CHECK-NEXT: .functype ldi64_a8 (i32) -> (i64){{$}}
43 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
44 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
45 define i64 @ldi64_a8(i64 *%p) {
46 %v = load i64, i64* %p, align 8
50 ; The default alignment in LLVM is the same as the default alignment in wasm.
53 ; CHECK-NEXT: .functype ldi64 (i32) -> (i64){{$}}
54 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
55 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
56 define i64 @ldi64(i64 *%p) {
57 %v = load i64, i64* %p
61 ; 16 is greater than the default alignment so it is ignored.
63 ; CHECK-LABEL: ldi64_a16:
64 ; CHECK-NEXT: .functype ldi64_a16 (i32) -> (i64){{$}}
65 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
66 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
67 define i64 @ldi64_a16(i64 *%p) {
68 %v = load i64, i64* %p, align 16
72 ;===----------------------------------------------------------------------------
74 ;===----------------------------------------------------------------------------
76 ; CHECK-LABEL: ldi8_a1:
77 ; CHECK-NEXT: .functype ldi8_a1 (i32) -> (i64){{$}}
78 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
79 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
80 define i64 @ldi8_a1(i8 *%p) {
81 %v = load i8, i8* %p, align 1
82 %w = zext i8 %v to i64
86 ; CHECK-LABEL: ldi8_a2:
87 ; CHECK-NEXT: .functype ldi8_a2 (i32) -> (i64){{$}}
88 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
89 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
90 define i64 @ldi8_a2(i8 *%p) {
91 %v = load i8, i8* %p, align 2
92 %w = zext i8 %v to i64
96 ; CHECK-LABEL: ldi16_a1:
97 ; CHECK-NEXT: .functype ldi16_a1 (i32) -> (i64){{$}}
98 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
99 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
100 define i64 @ldi16_a1(i16 *%p) {
101 %v = load i16, i16* %p, align 1
102 %w = zext i16 %v to i64
106 ; CHECK-LABEL: ldi16_a2:
107 ; CHECK-NEXT: .functype ldi16_a2 (i32) -> (i64){{$}}
108 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
109 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
110 define i64 @ldi16_a2(i16 *%p) {
111 %v = load i16, i16* %p, align 2
112 %w = zext i16 %v to i64
116 ; CHECK-LABEL: ldi16_a4:
117 ; CHECK-NEXT: .functype ldi16_a4 (i32) -> (i64){{$}}
118 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
119 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
120 define i64 @ldi16_a4(i16 *%p) {
121 %v = load i16, i16* %p, align 4
122 %w = zext i16 %v to i64
126 ; CHECK-LABEL: ldi32_a1:
127 ; CHECK-NEXT: .functype ldi32_a1 (i32) -> (i64){{$}}
128 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
129 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
130 define i64 @ldi32_a1(i32 *%p) {
131 %v = load i32, i32* %p, align 1
132 %w = zext i32 %v to i64
136 ; CHECK-LABEL: ldi32_a2:
137 ; CHECK-NEXT: .functype ldi32_a2 (i32) -> (i64){{$}}
138 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
139 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
140 define i64 @ldi32_a2(i32 *%p) {
141 %v = load i32, i32* %p, align 2
142 %w = zext i32 %v to i64
146 ; CHECK-LABEL: ldi32_a4:
147 ; CHECK-NEXT: .functype ldi32_a4 (i32) -> (i64){{$}}
148 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
149 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
150 define i64 @ldi32_a4(i32 *%p) {
151 %v = load i32, i32* %p, align 4
152 %w = zext i32 %v to i64
156 ; CHECK-LABEL: ldi32_a8:
157 ; CHECK-NEXT: .functype ldi32_a8 (i32) -> (i64){{$}}
158 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
159 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
160 define i64 @ldi32_a8(i32 *%p) {
161 %v = load i32, i32* %p, align 8
162 %w = zext i32 %v to i64
166 ;===----------------------------------------------------------------------------
168 ;===----------------------------------------------------------------------------
170 ; CHECK-LABEL: sti64_a1:
171 ; CHECK-NEXT: .functype sti64_a1 (i32, i64) -> (){{$}}
172 ; CHECK-NEXT: i64.store 0($0):p2align=0, $1{{$}}
173 ; CHECK-NEXT: return{{$}}
174 define void @sti64_a1(i64 *%p, i64 %v) {
175 store i64 %v, i64* %p, align 1
179 ; CHECK-LABEL: sti64_a2:
180 ; CHECK-NEXT: .functype sti64_a2 (i32, i64) -> (){{$}}
181 ; CHECK-NEXT: i64.store 0($0):p2align=1, $1{{$}}
182 ; CHECK-NEXT: return{{$}}
183 define void @sti64_a2(i64 *%p, i64 %v) {
184 store i64 %v, i64* %p, align 2
188 ; CHECK-LABEL: sti64_a4:
189 ; CHECK-NEXT: .functype sti64_a4 (i32, i64) -> (){{$}}
190 ; CHECK-NEXT: i64.store 0($0):p2align=2, $1{{$}}
191 ; CHECK-NEXT: return{{$}}
192 define void @sti64_a4(i64 *%p, i64 %v) {
193 store i64 %v, i64* %p, align 4
197 ; 8 is the default alignment for i32 so no attribute is needed.
199 ; CHECK-LABEL: sti64_a8:
200 ; CHECK-NEXT: .functype sti64_a8 (i32, i64) -> (){{$}}
201 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
202 ; CHECK-NEXT: return{{$}}
203 define void @sti64_a8(i64 *%p, i64 %v) {
204 store i64 %v, i64* %p, align 8
208 ; The default alignment in LLVM is the same as the default alignment in wasm.
210 ; CHECK-LABEL: sti64:
211 ; CHECK-NEXT: .functype sti64 (i32, i64) -> (){{$}}
212 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
213 ; CHECK-NEXT: return{{$}}
214 define void @sti64(i64 *%p, i64 %v) {
215 store i64 %v, i64* %p
219 ; CHECK-LABEL: sti64_a16:
220 ; CHECK-NEXT: .functype sti64_a16 (i32, i64) -> (){{$}}
221 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
222 ; CHECK-NEXT: return{{$}}
223 define void @sti64_a16(i64 *%p, i64 %v) {
224 store i64 %v, i64* %p, align 16
228 ;===----------------------------------------------------------------------------
230 ;===----------------------------------------------------------------------------
232 ; CHECK-LABEL: sti8_a1:
233 ; CHECK-NEXT: .functype sti8_a1 (i32, i64) -> (){{$}}
234 ; CHECK-NEXT: i64.store8 0($0), $1{{$}}
235 ; CHECK-NEXT: return{{$}}
236 define void @sti8_a1(i8 *%p, i64 %w) {
237 %v = trunc i64 %w to i8
238 store i8 %v, i8* %p, align 1
242 ; CHECK-LABEL: sti8_a2:
243 ; CHECK-NEXT: .functype sti8_a2 (i32, i64) -> (){{$}}
244 ; CHECK-NEXT: i64.store8 0($0), $1{{$}}
245 ; CHECK-NEXT: return{{$}}
246 define void @sti8_a2(i8 *%p, i64 %w) {
247 %v = trunc i64 %w to i8
248 store i8 %v, i8* %p, align 2
252 ; CHECK-LABEL: sti16_a1:
253 ; CHECK-NEXT: .functype sti16_a1 (i32, i64) -> (){{$}}
254 ; CHECK-NEXT: i64.store16 0($0):p2align=0, $1{{$}}
255 ; CHECK-NEXT: return{{$}}
256 define void @sti16_a1(i16 *%p, i64 %w) {
257 %v = trunc i64 %w to i16
258 store i16 %v, i16* %p, align 1
262 ; CHECK-LABEL: sti16_a2:
263 ; CHECK-NEXT: .functype sti16_a2 (i32, i64) -> (){{$}}
264 ; CHECK-NEXT: i64.store16 0($0), $1{{$}}
265 ; CHECK-NEXT: return{{$}}
266 define void @sti16_a2(i16 *%p, i64 %w) {
267 %v = trunc i64 %w to i16
268 store i16 %v, i16* %p, align 2
272 ; CHECK-LABEL: sti16_a4:
273 ; CHECK-NEXT: .functype sti16_a4 (i32, i64) -> (){{$}}
274 ; CHECK-NEXT: i64.store16 0($0), $1{{$}}
275 ; CHECK-NEXT: return{{$}}
276 define void @sti16_a4(i16 *%p, i64 %w) {
277 %v = trunc i64 %w to i16
278 store i16 %v, i16* %p, align 4
282 ; CHECK-LABEL: sti32_a1:
283 ; CHECK-NEXT: .functype sti32_a1 (i32, i64) -> (){{$}}
284 ; CHECK-NEXT: i64.store32 0($0):p2align=0, $1{{$}}
285 ; CHECK-NEXT: return{{$}}
286 define void @sti32_a1(i32 *%p, i64 %w) {
287 %v = trunc i64 %w to i32
288 store i32 %v, i32* %p, align 1
292 ; CHECK-LABEL: sti32_a2:
293 ; CHECK-NEXT: .functype sti32_a2 (i32, i64) -> (){{$}}
294 ; CHECK-NEXT: i64.store32 0($0):p2align=1, $1{{$}}
295 ; CHECK-NEXT: return{{$}}
296 define void @sti32_a2(i32 *%p, i64 %w) {
297 %v = trunc i64 %w to i32
298 store i32 %v, i32* %p, align 2
302 ; CHECK-LABEL: sti32_a4:
303 ; CHECK-NEXT: .functype sti32_a4 (i32, i64) -> (){{$}}
304 ; CHECK-NEXT: i64.store32 0($0), $1{{$}}
305 ; CHECK-NEXT: return{{$}}
306 define void @sti32_a4(i32 *%p, i64 %w) {
307 %v = trunc i64 %w to i32
308 store i32 %v, i32* %p, align 4
312 ; CHECK-LABEL: sti32_a8:
313 ; CHECK-NEXT: .functype sti32_a8 (i32, i64) -> (){{$}}
314 ; CHECK-NEXT: i64.store32 0($0), $1{{$}}
315 ; CHECK-NEXT: return{{$}}
316 define void @sti32_a8(i32 *%p, i64 %w) {
317 %v = trunc i64 %w to i32
318 store i32 %v, i32* %p, align 8
322 ;===----------------------------------------------------------------------------
324 ;===----------------------------------------------------------------------------
326 ; Wasm atomics have the alignment field, but it must always have the type's
329 ; CHECK-LABEL: ldi64_atomic_a8:
330 ; CHECK-NEXT: .functype ldi64_atomic_a8 (i32) -> (i64){{$}}
331 ; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
332 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
333 define i64 @ldi64_atomic_a8(i64 *%p) {
334 %v = load atomic i64, i64* %p seq_cst, align 8
338 ; 16 is greater than the default alignment so it is ignored.
340 ; CHECK-LABEL: ldi64_atomic_a16:
341 ; CHECK-NEXT: .functype ldi64_atomic_a16 (i32) -> (i64){{$}}
342 ; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
343 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
344 define i64 @ldi64_atomic_a16(i64 *%p) {
345 %v = load atomic i64, i64* %p seq_cst, align 16
349 ;===----------------------------------------------------------------------------
351 ;===----------------------------------------------------------------------------
353 ; CHECK-LABEL: sti64_atomic_a4:
354 ; CHECK-NEXT: .functype sti64_atomic_a4 (i32, i64) -> (){{$}}
355 ; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}
356 ; CHECK-NEXT: return{{$}}
357 define void @sti64_atomic_a4(i64 *%p, i64 %v) {
358 store atomic i64 %v, i64* %p seq_cst, align 8
362 ; 16 is greater than the default alignment so it is ignored.
364 ; CHECK-LABEL: sti64_atomic_a8:
365 ; CHECK-NEXT: .functype sti64_atomic_a8 (i32, i64) -> (){{$}}
366 ; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}
367 ; CHECK-NEXT: return{{$}}
368 define void @sti64_atomic_a8(i64 *%p, i64 %v) {
369 store atomic i64 %v, i64* %p seq_cst, align 16