Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / CodeGen / WebAssembly / i64-load-store-alignment.ll
blob5f484d492069c17c9d85772d213d736ed212a896
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 triple = "wasm32-unknown-unknown"
7 ;===----------------------------------------------------------------------------
8 ; Loads
9 ;===----------------------------------------------------------------------------
11 ; CHECK-LABEL: ldi64_a1:
12 ; CHECK-NEXT: .functype ldi64_a1 (i32) -> (i64){{$}}
13 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
14 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
15 define i64 @ldi64_a1(ptr %p) {
16   %v = load i64, ptr %p, align 1
17   ret i64 %v
20 ; CHECK-LABEL: ldi64_a2:
21 ; CHECK-NEXT: .functype ldi64_a2 (i32) -> (i64){{$}}
22 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
23 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
24 define i64 @ldi64_a2(ptr %p) {
25   %v = load i64, ptr %p, align 2
26   ret i64 %v
29 ; CHECK-LABEL: ldi64_a4:
30 ; CHECK-NEXT: .functype ldi64_a4 (i32) -> (i64){{$}}
31 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}}
32 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
33 define i64 @ldi64_a4(ptr %p) {
34   %v = load i64, ptr %p, align 4
35   ret i64 %v
38 ; 8 is the default alignment for i64 so no attribute is needed.
40 ; CHECK-LABEL: ldi64_a8:
41 ; CHECK-NEXT: .functype ldi64_a8 (i32) -> (i64){{$}}
42 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
43 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
44 define i64 @ldi64_a8(ptr %p) {
45   %v = load i64, ptr %p, align 8
46   ret i64 %v
49 ; The default alignment in LLVM is the same as the default alignment in wasm.
51 ; CHECK-LABEL: ldi64:
52 ; CHECK-NEXT: .functype ldi64 (i32) -> (i64){{$}}
53 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
54 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
55 define i64 @ldi64(ptr %p) {
56   %v = load i64, ptr %p
57   ret i64 %v
60 ; 16 is greater than the default alignment so it is ignored.
62 ; CHECK-LABEL: ldi64_a16:
63 ; CHECK-NEXT: .functype ldi64_a16 (i32) -> (i64){{$}}
64 ; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
65 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
66 define i64 @ldi64_a16(ptr %p) {
67   %v = load i64, ptr %p, align 16
68   ret i64 %v
71 ;===----------------------------------------------------------------------------
72 ; Extending loads
73 ;===----------------------------------------------------------------------------
75 ; CHECK-LABEL: ldi8_a1:
76 ; CHECK-NEXT: .functype ldi8_a1 (i32) -> (i64){{$}}
77 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
78 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
79 define i64 @ldi8_a1(ptr %p) {
80   %v = load i8, ptr %p, align 1
81   %w = zext i8 %v to i64
82   ret i64 %w
85 ; CHECK-LABEL: ldi8_a2:
86 ; CHECK-NEXT: .functype ldi8_a2 (i32) -> (i64){{$}}
87 ; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
88 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
89 define i64 @ldi8_a2(ptr %p) {
90   %v = load i8, ptr %p, align 2
91   %w = zext i8 %v to i64
92   ret i64 %w
95 ; CHECK-LABEL: ldi16_a1:
96 ; CHECK-NEXT: .functype ldi16_a1 (i32) -> (i64){{$}}
97 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
98 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
99 define i64 @ldi16_a1(ptr %p) {
100   %v = load i16, ptr %p, align 1
101   %w = zext i16 %v to i64
102   ret i64 %w
105 ; CHECK-LABEL: ldi16_a2:
106 ; CHECK-NEXT: .functype ldi16_a2 (i32) -> (i64){{$}}
107 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
108 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
109 define i64 @ldi16_a2(ptr %p) {
110   %v = load i16, ptr %p, align 2
111   %w = zext i16 %v to i64
112   ret i64 %w
115 ; CHECK-LABEL: ldi16_a4:
116 ; CHECK-NEXT: .functype ldi16_a4 (i32) -> (i64){{$}}
117 ; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
118 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
119 define i64 @ldi16_a4(ptr %p) {
120   %v = load i16, ptr %p, align 4
121   %w = zext i16 %v to i64
122   ret i64 %w
125 ; CHECK-LABEL: ldi32_a1:
126 ; CHECK-NEXT: .functype ldi32_a1 (i32) -> (i64){{$}}
127 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
128 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
129 define i64 @ldi32_a1(ptr %p) {
130   %v = load i32, ptr %p, align 1
131   %w = zext i32 %v to i64
132   ret i64 %w
135 ; CHECK-LABEL: ldi32_a2:
136 ; CHECK-NEXT: .functype ldi32_a2 (i32) -> (i64){{$}}
137 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
138 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
139 define i64 @ldi32_a2(ptr %p) {
140   %v = load i32, ptr %p, align 2
141   %w = zext i32 %v to i64
142   ret i64 %w
145 ; CHECK-LABEL: ldi32_a4:
146 ; CHECK-NEXT: .functype ldi32_a4 (i32) -> (i64){{$}}
147 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
148 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
149 define i64 @ldi32_a4(ptr %p) {
150   %v = load i32, ptr %p, align 4
151   %w = zext i32 %v to i64
152   ret i64 %w
155 ; CHECK-LABEL: ldi32_a8:
156 ; CHECK-NEXT: .functype ldi32_a8 (i32) -> (i64){{$}}
157 ; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
158 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
159 define i64 @ldi32_a8(ptr %p) {
160   %v = load i32, ptr %p, align 8
161   %w = zext i32 %v to i64
162   ret i64 %w
165 ;===----------------------------------------------------------------------------
166 ; Stores
167 ;===----------------------------------------------------------------------------
169 ; CHECK-LABEL: sti64_a1:
170 ; CHECK-NEXT: .functype sti64_a1 (i32, i64) -> (){{$}}
171 ; CHECK-NEXT: i64.store 0($0):p2align=0, $1{{$}}
172 ; CHECK-NEXT: return{{$}}
173 define void @sti64_a1(ptr %p, i64 %v) {
174   store i64 %v, ptr %p, align 1
175   ret void
178 ; CHECK-LABEL: sti64_a2:
179 ; CHECK-NEXT: .functype sti64_a2 (i32, i64) -> (){{$}}
180 ; CHECK-NEXT: i64.store 0($0):p2align=1, $1{{$}}
181 ; CHECK-NEXT: return{{$}}
182 define void @sti64_a2(ptr %p, i64 %v) {
183   store i64 %v, ptr %p, align 2
184   ret void
187 ; CHECK-LABEL: sti64_a4:
188 ; CHECK-NEXT: .functype sti64_a4 (i32, i64) -> (){{$}}
189 ; CHECK-NEXT: i64.store 0($0):p2align=2, $1{{$}}
190 ; CHECK-NEXT: return{{$}}
191 define void @sti64_a4(ptr %p, i64 %v) {
192   store i64 %v, ptr %p, align 4
193   ret void
196 ; 8 is the default alignment for i32 so no attribute is needed.
198 ; CHECK-LABEL: sti64_a8:
199 ; CHECK-NEXT: .functype sti64_a8 (i32, i64) -> (){{$}}
200 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
201 ; CHECK-NEXT: return{{$}}
202 define void @sti64_a8(ptr %p, i64 %v) {
203   store i64 %v, ptr %p, align 8
204   ret void
207 ; The default alignment in LLVM is the same as the default alignment in wasm.
209 ; CHECK-LABEL: sti64:
210 ; CHECK-NEXT: .functype sti64 (i32, i64) -> (){{$}}
211 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
212 ; CHECK-NEXT: return{{$}}
213 define void @sti64(ptr %p, i64 %v) {
214   store i64 %v, ptr %p
215   ret void
218 ; CHECK-LABEL: sti64_a16:
219 ; CHECK-NEXT: .functype sti64_a16 (i32, i64) -> (){{$}}
220 ; CHECK-NEXT: i64.store 0($0), $1{{$}}
221 ; CHECK-NEXT: return{{$}}
222 define void @sti64_a16(ptr %p, i64 %v) {
223   store i64 %v, ptr %p, align 16
224   ret void
227 ;===----------------------------------------------------------------------------
228 ; Truncating stores
229 ;===----------------------------------------------------------------------------
231 ; CHECK-LABEL: sti8_a1:
232 ; CHECK-NEXT: .functype sti8_a1 (i32, i64) -> (){{$}}
233 ; CHECK-NEXT: i64.store8 0($0), $1{{$}}
234 ; CHECK-NEXT: return{{$}}
235 define void @sti8_a1(ptr %p, i64 %w) {
236   %v = trunc i64 %w to i8
237   store i8 %v, ptr %p, align 1
238   ret void
241 ; CHECK-LABEL: sti8_a2:
242 ; CHECK-NEXT: .functype sti8_a2 (i32, i64) -> (){{$}}
243 ; CHECK-NEXT: i64.store8 0($0), $1{{$}}
244 ; CHECK-NEXT: return{{$}}
245 define void @sti8_a2(ptr %p, i64 %w) {
246   %v = trunc i64 %w to i8
247   store i8 %v, ptr %p, align 2
248   ret void
251 ; CHECK-LABEL: sti16_a1:
252 ; CHECK-NEXT: .functype sti16_a1 (i32, i64) -> (){{$}}
253 ; CHECK-NEXT: i64.store16 0($0):p2align=0, $1{{$}}
254 ; CHECK-NEXT: return{{$}}
255 define void @sti16_a1(ptr %p, i64 %w) {
256   %v = trunc i64 %w to i16
257   store i16 %v, ptr %p, align 1
258   ret void
261 ; CHECK-LABEL: sti16_a2:
262 ; CHECK-NEXT: .functype sti16_a2 (i32, i64) -> (){{$}}
263 ; CHECK-NEXT: i64.store16 0($0), $1{{$}}
264 ; CHECK-NEXT: return{{$}}
265 define void @sti16_a2(ptr %p, i64 %w) {
266   %v = trunc i64 %w to i16
267   store i16 %v, ptr %p, align 2
268   ret void
271 ; CHECK-LABEL: sti16_a4:
272 ; CHECK-NEXT: .functype sti16_a4 (i32, i64) -> (){{$}}
273 ; CHECK-NEXT: i64.store16 0($0), $1{{$}}
274 ; CHECK-NEXT: return{{$}}
275 define void @sti16_a4(ptr %p, i64 %w) {
276   %v = trunc i64 %w to i16
277   store i16 %v, ptr %p, align 4
278   ret void
281 ; CHECK-LABEL: sti32_a1:
282 ; CHECK-NEXT: .functype sti32_a1 (i32, i64) -> (){{$}}
283 ; CHECK-NEXT: i64.store32 0($0):p2align=0, $1{{$}}
284 ; CHECK-NEXT: return{{$}}
285 define void @sti32_a1(ptr %p, i64 %w) {
286   %v = trunc i64 %w to i32
287   store i32 %v, ptr %p, align 1
288   ret void
291 ; CHECK-LABEL: sti32_a2:
292 ; CHECK-NEXT: .functype sti32_a2 (i32, i64) -> (){{$}}
293 ; CHECK-NEXT: i64.store32 0($0):p2align=1, $1{{$}}
294 ; CHECK-NEXT: return{{$}}
295 define void @sti32_a2(ptr %p, i64 %w) {
296   %v = trunc i64 %w to i32
297   store i32 %v, ptr %p, align 2
298   ret void
301 ; CHECK-LABEL: sti32_a4:
302 ; CHECK-NEXT: .functype sti32_a4 (i32, i64) -> (){{$}}
303 ; CHECK-NEXT: i64.store32 0($0), $1{{$}}
304 ; CHECK-NEXT: return{{$}}
305 define void @sti32_a4(ptr %p, i64 %w) {
306   %v = trunc i64 %w to i32
307   store i32 %v, ptr %p, align 4
308   ret void
311 ; CHECK-LABEL: sti32_a8:
312 ; CHECK-NEXT: .functype sti32_a8 (i32, i64) -> (){{$}}
313 ; CHECK-NEXT: i64.store32 0($0), $1{{$}}
314 ; CHECK-NEXT: return{{$}}
315 define void @sti32_a8(ptr %p, i64 %w) {
316   %v = trunc i64 %w to i32
317   store i32 %v, ptr %p, align 8
318   ret void
321 ;===----------------------------------------------------------------------------
322 ; Atomic loads
323 ;===----------------------------------------------------------------------------
325 ; Wasm atomics have the alignment field, but it must always have the type's
326 ; natural alignment.
328 ; CHECK-LABEL: ldi64_atomic_a8:
329 ; CHECK-NEXT: .functype ldi64_atomic_a8 (i32) -> (i64){{$}}
330 ; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
331 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
332 define i64 @ldi64_atomic_a8(ptr %p) {
333   %v = load atomic i64, ptr %p seq_cst, align 8
334   ret i64 %v
337 ; 16 is greater than the default alignment so it is ignored.
339 ; CHECK-LABEL: ldi64_atomic_a16:
340 ; CHECK-NEXT: .functype ldi64_atomic_a16 (i32) -> (i64){{$}}
341 ; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
342 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
343 define i64 @ldi64_atomic_a16(ptr %p) {
344   %v = load atomic i64, ptr %p seq_cst, align 16
345   ret i64 %v
348 ;===----------------------------------------------------------------------------
349 ; Atomic stores
350 ;===----------------------------------------------------------------------------
352 ; CHECK-LABEL: sti64_atomic_a4:
353 ; CHECK-NEXT: .functype sti64_atomic_a4 (i32, i64) -> (){{$}}
354 ; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}
355 ; CHECK-NEXT: return{{$}}
356 define void @sti64_atomic_a4(ptr %p, i64 %v) {
357  store atomic i64 %v, ptr %p seq_cst, align 8
358  ret void
361 ; 16 is greater than the default alignment so it is ignored.
363 ; CHECK-LABEL: sti64_atomic_a8:
364 ; CHECK-NEXT: .functype sti64_atomic_a8 (i32, i64) -> (){{$}}
365 ; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}
366 ; CHECK-NEXT: return{{$}}
367 define void @sti64_atomic_a8(ptr %p, i64 %v) {
368  store atomic i64 %v, ptr %p seq_cst, align 16
369  ret void