Use Align for TFL::TransientStackAlignment
[llvm-core.git] / test / CodeGen / WebAssembly / i64-load-store-alignment.ll
blob5af843bcbaacb27aeb764786591c13affcc7ecf7
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 ;===----------------------------------------------------------------------------
9 ; Loads
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
18   ret i64 %v
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
27   ret i64 %v
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
36   ret i64 %v
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
47   ret i64 %v
50 ; The default alignment in LLVM is the same as the default alignment in wasm.
52 ; CHECK-LABEL: ldi64:
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
58   ret i64 %v
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
69   ret i64 %v
72 ;===----------------------------------------------------------------------------
73 ; Extending loads
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
83   ret i64 %w
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
93   ret i64 %w
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
103   ret i64 %w
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
113   ret i64 %w
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
123   ret i64 %w
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
133   ret i64 %w
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
143   ret i64 %w
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
153   ret i64 %w
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
163   ret i64 %w
166 ;===----------------------------------------------------------------------------
167 ; Stores
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
176   ret void
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
185   ret void
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
194   ret void
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
205   ret void
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
216   ret void
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
225   ret void
228 ;===----------------------------------------------------------------------------
229 ; Truncating stores
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
239   ret void
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
249   ret void
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
259   ret void
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
269   ret void
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
279   ret void
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
289   ret void
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
299   ret void
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
309   ret void
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
319   ret void
322 ;===----------------------------------------------------------------------------
323 ; Atomic loads
324 ;===----------------------------------------------------------------------------
326 ; Wasm atomics have the alignment field, but it must always have the type's
327 ; natural alignment.
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
335   ret i64 %v
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
346   ret i64 %v
349 ;===----------------------------------------------------------------------------
350 ; Atomic stores
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
359  ret void
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
370  ret void