xref: /aosp_15_r20/external/llvm/test/CodeGen/WebAssembly/i64-load-store-alignment.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
2
3; Test loads and stores with custom alignment values.
4
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8; CHECK-LABEL: ldi64_a1:
9; CHECK-NEXT: .param i32{{$}}
10; CHECK-NEXT: .result i64{{$}}
11; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
12; CHECK-NEXT: return $pop[[NUM]]{{$}}
13define i64 @ldi64_a1(i64 *%p) {
14  %v = load i64, i64* %p, align 1
15  ret i64 %v
16}
17
18; CHECK-LABEL: ldi64_a2:
19; CHECK-NEXT: .param i32{{$}}
20; CHECK-NEXT: .result i64{{$}}
21; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
22; CHECK-NEXT: return $pop[[NUM]]{{$}}
23define i64 @ldi64_a2(i64 *%p) {
24  %v = load i64, i64* %p, align 2
25  ret i64 %v
26}
27
28; CHECK-LABEL: ldi64_a4:
29; CHECK-NEXT: .param i32{{$}}
30; CHECK-NEXT: .result i64{{$}}
31; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}}
32; CHECK-NEXT: return $pop[[NUM]]{{$}}
33define i64 @ldi64_a4(i64 *%p) {
34  %v = load i64, i64* %p, align 4
35  ret i64 %v
36}
37
38; 8 is the default alignment for i64 so no attribute is needed.
39
40; CHECK-LABEL: ldi64_a8:
41; CHECK-NEXT: .param i32{{$}}
42; CHECK-NEXT: .result i64{{$}}
43; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
44; CHECK-NEXT: return $pop[[NUM]]{{$}}
45define i64 @ldi64_a8(i64 *%p) {
46  %v = load i64, i64* %p, align 8
47  ret i64 %v
48}
49
50; The default alignment in LLVM is the same as the defualt alignment in wasm.
51
52; CHECK-LABEL: ldi64:
53; CHECK-NEXT: .param i32{{$}}
54; CHECK-NEXT: .result i64{{$}}
55; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
56; CHECK-NEXT: return $pop[[NUM]]{{$}}
57define i64 @ldi64(i64 *%p) {
58  %v = load i64, i64* %p
59  ret i64 %v
60}
61
62; 16 is greater than the default alignment so it is ignored.
63
64; CHECK-LABEL: ldi64_a16:
65; CHECK-NEXT: .param i32{{$}}
66; CHECK-NEXT: .result i64{{$}}
67; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}
68; CHECK-NEXT: return $pop[[NUM]]{{$}}
69define i64 @ldi64_a16(i64 *%p) {
70  %v = load i64, i64* %p, align 16
71  ret i64 %v
72}
73
74; Extending loads.
75
76; CHECK-LABEL: ldi8_a1:
77; CHECK-NEXT: .param i32{{$}}
78; CHECK-NEXT: .result i64{{$}}
79; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
80; CHECK-NEXT: return $pop[[NUM]]{{$}}
81define i64 @ldi8_a1(i8 *%p) {
82  %v = load i8, i8* %p, align 1
83  %w = zext i8 %v to i64
84  ret i64 %w
85}
86
87; CHECK-LABEL: ldi8_a2:
88; CHECK-NEXT: .param i32{{$}}
89; CHECK-NEXT: .result i64{{$}}
90; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
91; CHECK-NEXT: return $pop[[NUM]]{{$}}
92define i64 @ldi8_a2(i8 *%p) {
93  %v = load i8, i8* %p, align 2
94  %w = zext i8 %v to i64
95  ret i64 %w
96}
97
98; CHECK-LABEL: ldi16_a1:
99; CHECK-NEXT: .param i32{{$}}
100; CHECK-NEXT: .result i64{{$}}
101; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
102; CHECK-NEXT: return $pop[[NUM]]{{$}}
103define i64 @ldi16_a1(i16 *%p) {
104  %v = load i16, i16* %p, align 1
105  %w = zext i16 %v to i64
106  ret i64 %w
107}
108
109; CHECK-LABEL: ldi16_a2:
110; CHECK-NEXT: .param i32{{$}}
111; CHECK-NEXT: .result i64{{$}}
112; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
113; CHECK-NEXT: return $pop[[NUM]]{{$}}
114define i64 @ldi16_a2(i16 *%p) {
115  %v = load i16, i16* %p, align 2
116  %w = zext i16 %v to i64
117  ret i64 %w
118}
119
120; CHECK-LABEL: ldi16_a4:
121; CHECK-NEXT: .param i32{{$}}
122; CHECK-NEXT: .result i64{{$}}
123; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
124; CHECK-NEXT: return $pop[[NUM]]{{$}}
125define i64 @ldi16_a4(i16 *%p) {
126  %v = load i16, i16* %p, align 4
127  %w = zext i16 %v to i64
128  ret i64 %w
129}
130
131; CHECK-LABEL: ldi32_a1:
132; CHECK-NEXT: .param i32{{$}}
133; CHECK-NEXT: .result i64{{$}}
134; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}
135; CHECK-NEXT: return $pop[[NUM]]{{$}}
136define i64 @ldi32_a1(i32 *%p) {
137  %v = load i32, i32* %p, align 1
138  %w = zext i32 %v to i64
139  ret i64 %w
140}
141
142; CHECK-LABEL: ldi32_a2:
143; CHECK-NEXT: .param i32{{$}}
144; CHECK-NEXT: .result i64{{$}}
145; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}
146; CHECK-NEXT: return $pop[[NUM]]{{$}}
147define i64 @ldi32_a2(i32 *%p) {
148  %v = load i32, i32* %p, align 2
149  %w = zext i32 %v to i64
150  ret i64 %w
151}
152
153; CHECK-LABEL: ldi32_a4:
154; CHECK-NEXT: .param i32{{$}}
155; CHECK-NEXT: .result i64{{$}}
156; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
157; CHECK-NEXT: return $pop[[NUM]]{{$}}
158define i64 @ldi32_a4(i32 *%p) {
159  %v = load i32, i32* %p, align 4
160  %w = zext i32 %v to i64
161  ret i64 %w
162}
163
164; CHECK-LABEL: ldi32_a8:
165; CHECK-NEXT: .param i32{{$}}
166; CHECK-NEXT: .result i64{{$}}
167; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}
168; CHECK-NEXT: return $pop[[NUM]]{{$}}
169define i64 @ldi32_a8(i32 *%p) {
170  %v = load i32, i32* %p, align 8
171  %w = zext i32 %v to i64
172  ret i64 %w
173}
174
175; Stores.
176
177; CHECK-LABEL: sti64_a1:
178; CHECK-NEXT: .param i32, i64{{$}}
179; CHECK-NEXT: i64.store $drop=, 0($0):p2align=0, $1{{$}}
180; CHECK-NEXT: return{{$}}
181define void @sti64_a1(i64 *%p, i64 %v) {
182  store i64 %v, i64* %p, align 1
183  ret void
184}
185
186; CHECK-LABEL: sti64_a2:
187; CHECK-NEXT: .param i32, i64{{$}}
188; CHECK-NEXT: i64.store $drop=, 0($0):p2align=1, $1{{$}}
189; CHECK-NEXT: return{{$}}
190define void @sti64_a2(i64 *%p, i64 %v) {
191  store i64 %v, i64* %p, align 2
192  ret void
193}
194
195; CHECK-LABEL: sti64_a4:
196; CHECK-NEXT: .param i32, i64{{$}}
197; CHECK-NEXT: i64.store $drop=, 0($0):p2align=2, $1{{$}}
198; CHECK-NEXT: return{{$}}
199define void @sti64_a4(i64 *%p, i64 %v) {
200  store i64 %v, i64* %p, align 4
201  ret void
202}
203
204; 8 is the default alignment for i32 so no attribute is needed.
205
206; CHECK-LABEL: sti64_a8:
207; CHECK-NEXT: .param i32, i64{{$}}
208; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
209; CHECK-NEXT: return{{$}}
210define void @sti64_a8(i64 *%p, i64 %v) {
211  store i64 %v, i64* %p, align 8
212  ret void
213}
214
215; The default alignment in LLVM is the same as the defualt alignment in wasm.
216
217; CHECK-LABEL: sti64:
218; CHECK-NEXT: .param i32, i64{{$}}
219; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
220; CHECK-NEXT: return{{$}}
221define void @sti64(i64 *%p, i64 %v) {
222  store i64 %v, i64* %p
223  ret void
224}
225
226; CHECK-LABEL: sti64_a16:
227; CHECK-NEXT: .param i32, i64{{$}}
228; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}}
229; CHECK-NEXT: return{{$}}
230define void @sti64_a16(i64 *%p, i64 %v) {
231  store i64 %v, i64* %p, align 16
232  ret void
233}
234
235; Truncating stores.
236
237; CHECK-LABEL: sti8_a1:
238; CHECK-NEXT: .param i32, i64{{$}}
239; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}}
240; CHECK-NEXT: return{{$}}
241define void @sti8_a1(i8 *%p, i64 %w) {
242  %v = trunc i64 %w to i8
243  store i8 %v, i8* %p, align 1
244  ret void
245}
246
247; CHECK-LABEL: sti8_a2:
248; CHECK-NEXT: .param i32, i64{{$}}
249; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}}
250; CHECK-NEXT: return{{$}}
251define void @sti8_a2(i8 *%p, i64 %w) {
252  %v = trunc i64 %w to i8
253  store i8 %v, i8* %p, align 2
254  ret void
255}
256
257; CHECK-LABEL: sti16_a1:
258; CHECK-NEXT: .param i32, i64{{$}}
259; CHECK-NEXT: i64.store16 $drop=, 0($0):p2align=0, $1{{$}}
260; CHECK-NEXT: return{{$}}
261define void @sti16_a1(i16 *%p, i64 %w) {
262  %v = trunc i64 %w to i16
263  store i16 %v, i16* %p, align 1
264  ret void
265}
266
267; CHECK-LABEL: sti16_a2:
268; CHECK-NEXT: .param i32, i64{{$}}
269; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}}
270; CHECK-NEXT: return{{$}}
271define void @sti16_a2(i16 *%p, i64 %w) {
272  %v = trunc i64 %w to i16
273  store i16 %v, i16* %p, align 2
274  ret void
275}
276
277; CHECK-LABEL: sti16_a4:
278; CHECK-NEXT: .param i32, i64{{$}}
279; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}}
280; CHECK-NEXT: return{{$}}
281define void @sti16_a4(i16 *%p, i64 %w) {
282  %v = trunc i64 %w to i16
283  store i16 %v, i16* %p, align 4
284  ret void
285}
286
287; CHECK-LABEL: sti32_a1:
288; CHECK-NEXT: .param i32, i64{{$}}
289; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=0, $1{{$}}
290; CHECK-NEXT: return{{$}}
291define void @sti32_a1(i32 *%p, i64 %w) {
292  %v = trunc i64 %w to i32
293  store i32 %v, i32* %p, align 1
294  ret void
295}
296
297; CHECK-LABEL: sti32_a2:
298; CHECK-NEXT: .param i32, i64{{$}}
299; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=1, $1{{$}}
300; CHECK-NEXT: return{{$}}
301define void @sti32_a2(i32 *%p, i64 %w) {
302  %v = trunc i64 %w to i32
303  store i32 %v, i32* %p, align 2
304  ret void
305}
306
307; CHECK-LABEL: sti32_a4:
308; CHECK-NEXT: .param i32, i64{{$}}
309; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}}
310; CHECK-NEXT: return{{$}}
311define void @sti32_a4(i32 *%p, i64 %w) {
312  %v = trunc i64 %w to i32
313  store i32 %v, i32* %p, align 4
314  ret void
315}
316
317; CHECK-LABEL: sti32_a8:
318; CHECK-NEXT: .param i32, i64{{$}}
319; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}}
320; CHECK-NEXT: return{{$}}
321define void @sti32_a8(i32 *%p, i64 %w) {
322  %v = trunc i64 %w to i32
323  store i32 %v, i32* %p, align 8
324  ret void
325}
326