blob: 1a9b2e84aaad3d6d36fb73eae5a5d044fee27e20 [file] [log] [blame]
Heejin Ahnfed73822018-07-09 22:30:51 +00001; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt
2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s
3
4; Test atomic RMW (read-modify-write) instructions are assembled properly.
5
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
9;===----------------------------------------------------------------------------
10; Atomic read-modify-writes: 32-bit
11;===----------------------------------------------------------------------------
12
13; CHECK-LABEL: add_i32:
14; CHECK-NEXT: .param i32, i32{{$}}
15; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
16; CHECK-NEXT: return $pop0{{$}}
17define i32 @add_i32(i32* %p, i32 %v) {
18 %old = atomicrmw add i32* %p, i32 %v seq_cst
19 ret i32 %old
20}
21
22; CHECK-LABEL: sub_i32:
23; CHECK-NEXT: .param i32, i32{{$}}
24; CHECK: i32.atomic.rmw.sub $push0=, 0($0), $1{{$}}
25; CHECK-NEXT: return $pop0{{$}}
26define i32 @sub_i32(i32* %p, i32 %v) {
27 %old = atomicrmw sub i32* %p, i32 %v seq_cst
28 ret i32 %old
29}
30
31; CHECK-LABEL: and_i32:
32; CHECK-NEXT: .param i32, i32{{$}}
33; CHECK: i32.atomic.rmw.and $push0=, 0($0), $1{{$}}
34; CHECK-NEXT: return $pop0{{$}}
35define i32 @and_i32(i32* %p, i32 %v) {
36 %old = atomicrmw and i32* %p, i32 %v seq_cst
37 ret i32 %old
38}
39
40; CHECK-LABEL: or_i32:
41; CHECK-NEXT: .param i32, i32{{$}}
42; CHECK: i32.atomic.rmw.or $push0=, 0($0), $1{{$}}
43; CHECK-NEXT: return $pop0{{$}}
44define i32 @or_i32(i32* %p, i32 %v) {
45 %old = atomicrmw or i32* %p, i32 %v seq_cst
46 ret i32 %old
47}
48
49; CHECK-LABEL: xor_i32:
50; CHECK-NEXT: .param i32, i32{{$}}
51; CHECK: i32.atomic.rmw.xor $push0=, 0($0), $1{{$}}
52; CHECK-NEXT: return $pop0{{$}}
53define i32 @xor_i32(i32* %p, i32 %v) {
54 %old = atomicrmw xor i32* %p, i32 %v seq_cst
55 ret i32 %old
56}
57
58; CHECK-LABEL: xchg_i32:
59; CHECK-NEXT: .param i32, i32{{$}}
60; CHECK: i32.atomic.rmw.xchg $push0=, 0($0), $1{{$}}
61; CHECK-NEXT: return $pop0{{$}}
62define i32 @xchg_i32(i32* %p, i32 %v) {
63 %old = atomicrmw xchg i32* %p, i32 %v seq_cst
64 ret i32 %old
65}
66
67;===----------------------------------------------------------------------------
68; Atomic read-modify-writes: 64-bit
69;===----------------------------------------------------------------------------
70
71; CHECK-LABEL: add_i64:
72; CHECK-NEXT: .param i32, i64{{$}}
73; CHECK: i64.atomic.rmw.add $push0=, 0($0), $1{{$}}
74; CHECK-NEXT: return $pop0{{$}}
75define i64 @add_i64(i64* %p, i64 %v) {
76 %old = atomicrmw add i64* %p, i64 %v seq_cst
77 ret i64 %old
78}
79
80; CHECK-LABEL: sub_i64:
81; CHECK-NEXT: .param i32, i64{{$}}
82; CHECK: i64.atomic.rmw.sub $push0=, 0($0), $1{{$}}
83; CHECK-NEXT: return $pop0{{$}}
84define i64 @sub_i64(i64* %p, i64 %v) {
85 %old = atomicrmw sub i64* %p, i64 %v seq_cst
86 ret i64 %old
87}
88
89; CHECK-LABEL: and_i64:
90; CHECK-NEXT: .param i32, i64{{$}}
91; CHECK: i64.atomic.rmw.and $push0=, 0($0), $1{{$}}
92; CHECK-NEXT: return $pop0{{$}}
93define i64 @and_i64(i64* %p, i64 %v) {
94 %old = atomicrmw and i64* %p, i64 %v seq_cst
95 ret i64 %old
96}
97
98; CHECK-LABEL: or_i64:
99; CHECK-NEXT: .param i32, i64{{$}}
100; CHECK: i64.atomic.rmw.or $push0=, 0($0), $1{{$}}
101; CHECK-NEXT: return $pop0{{$}}
102define i64 @or_i64(i64* %p, i64 %v) {
103 %old = atomicrmw or i64* %p, i64 %v seq_cst
104 ret i64 %old
105}
106
107; CHECK-LABEL: xor_i64:
108; CHECK-NEXT: .param i32, i64{{$}}
109; CHECK: i64.atomic.rmw.xor $push0=, 0($0), $1{{$}}
110; CHECK-NEXT: return $pop0{{$}}
111define i64 @xor_i64(i64* %p, i64 %v) {
112 %old = atomicrmw xor i64* %p, i64 %v seq_cst
113 ret i64 %old
114}
115
116; CHECK-LABEL: xchg_i64:
117; CHECK-NEXT: .param i32, i64{{$}}
118; CHECK: i64.atomic.rmw.xchg $push0=, 0($0), $1{{$}}
119; CHECK-NEXT: return $pop0{{$}}
120define i64 @xchg_i64(i64* %p, i64 %v) {
121 %old = atomicrmw xchg i64* %p, i64 %v seq_cst
122 ret i64 %old
123}
124
125;===----------------------------------------------------------------------------
126; Atomic truncating & sign-extending RMWs
127;===----------------------------------------------------------------------------
128
129; add
130
131; CHECK-LABEL: add_sext_i8_i32:
132; CHECK-NEXT: .param i32, i32{{$}}
133; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
134; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
135; CHECK-NEXT: return $pop1{{$}}
136define i32 @add_sext_i8_i32(i8* %p, i32 %v) {
137 %t = trunc i32 %v to i8
138 %old = atomicrmw add i8* %p, i8 %t seq_cst
139 %e = sext i8 %old to i32
140 ret i32 %e
141}
142
143; CHECK-LABEL: add_sext_i16_i32:
144; CHECK-NEXT: .param i32, i32{{$}}
145; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
146; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
147; CHECK-NEXT: return $pop1{{$}}
148define i32 @add_sext_i16_i32(i16* %p, i32 %v) {
149 %t = trunc i32 %v to i16
150 %old = atomicrmw add i16* %p, i16 %t seq_cst
151 %e = sext i16 %old to i32
152 ret i32 %e
153}
154
155; CHECK-LABEL: add_sext_i8_i64:
156; CHECK-NEXT: .param i32, i64{{$}}
157; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
158; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
159; CHECK-NEXT: return $pop1{{$}}
160define i64 @add_sext_i8_i64(i8* %p, i64 %v) {
161 %t = trunc i64 %v to i8
162 %old = atomicrmw add i8* %p, i8 %t seq_cst
163 %e = sext i8 %old to i64
164 ret i64 %e
165}
166
167; CHECK-LABEL: add_sext_i16_i64:
168; CHECK-NEXT: .param i32, i64{{$}}
169; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
170; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
171; CHECK-NEXT: return $pop1{{$}}
172define i64 @add_sext_i16_i64(i16* %p, i64 %v) {
173 %t = trunc i64 %v to i16
174 %old = atomicrmw add i16* %p, i16 %t seq_cst
175 %e = sext i16 %old to i64
176 ret i64 %e
177}
178
179; 32->64 sext rmw gets selected as i32.atomic.rmw.add, i64_extend_s/i32
180; CHECK-LABEL: add_sext_i32_i64:
181; CHECK-NEXT: .param i32, i64{{$}}
Heejin Ahn9ef850b2018-07-10 16:00:43 +0000182; CHECK: i32.wrap/i64 $push0=, $1{{$}}
Heejin Ahnfed73822018-07-09 22:30:51 +0000183; CHECK: i32.atomic.rmw.add $push1=, 0($0), $pop0{{$}}
184; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
185; CHECK-NEXT: return $pop2{{$}}
186define i64 @add_sext_i32_i64(i32* %p, i64 %v) {
187 %t = trunc i64 %v to i32
188 %old = atomicrmw add i32* %p, i32 %t seq_cst
189 %e = sext i32 %old to i64
190 ret i64 %e
191}
192
193; sub
194
195; CHECK-LABEL: sub_sext_i8_i32:
196; CHECK-NEXT: .param i32, i32{{$}}
197; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
198; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
199; CHECK-NEXT: return $pop1{{$}}
200define i32 @sub_sext_i8_i32(i8* %p, i32 %v) {
201 %t = trunc i32 %v to i8
202 %old = atomicrmw sub i8* %p, i8 %t seq_cst
203 %e = sext i8 %old to i32
204 ret i32 %e
205}
206
207; CHECK-LABEL: sub_sext_i16_i32:
208; CHECK-NEXT: .param i32, i32{{$}}
209; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
210; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
211; CHECK-NEXT: return $pop1{{$}}
212define i32 @sub_sext_i16_i32(i16* %p, i32 %v) {
213 %t = trunc i32 %v to i16
214 %old = atomicrmw sub i16* %p, i16 %t seq_cst
215 %e = sext i16 %old to i32
216 ret i32 %e
217}
218
219; CHECK-LABEL: sub_sext_i8_i64:
220; CHECK-NEXT: .param i32, i64{{$}}
221; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
222; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
223; CHECK-NEXT: return $pop1{{$}}
224define i64 @sub_sext_i8_i64(i8* %p, i64 %v) {
225 %t = trunc i64 %v to i8
226 %old = atomicrmw sub i8* %p, i8 %t seq_cst
227 %e = sext i8 %old to i64
228 ret i64 %e
229}
230
231; CHECK-LABEL: sub_sext_i16_i64:
232; CHECK-NEXT: .param i32, i64{{$}}
233; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
234; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
235; CHECK-NEXT: return $pop1{{$}}
236define i64 @sub_sext_i16_i64(i16* %p, i64 %v) {
237 %t = trunc i64 %v to i16
238 %old = atomicrmw sub i16* %p, i16 %t seq_cst
239 %e = sext i16 %old to i64
240 ret i64 %e
241}
242
243; 32->64 sext rmw gets selected as i32.atomic.rmw.sub, i64_extend_s/i32
244; CHECK-LABEL: sub_sext_i32_i64:
245; CHECK-NEXT: .param i32, i64{{$}}
246; CHECK: i32.wrap/i64 $push0=, $1
247; CHECK: i32.atomic.rmw.sub $push1=, 0($0), $pop0{{$}}
248; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
249; CHECK-NEXT: return $pop2{{$}}
250define i64 @sub_sext_i32_i64(i32* %p, i64 %v) {
251 %t = trunc i64 %v to i32
252 %old = atomicrmw sub i32* %p, i32 %t seq_cst
253 %e = sext i32 %old to i64
254 ret i64 %e
255}
256
257; and
258
259; CHECK-LABEL: and_sext_i8_i32:
260; CHECK-NEXT: .param i32, i32{{$}}
261; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
262; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
263; CHECK-NEXT: return $pop1{{$}}
264define i32 @and_sext_i8_i32(i8* %p, i32 %v) {
265 %t = trunc i32 %v to i8
266 %old = atomicrmw and i8* %p, i8 %t seq_cst
267 %e = sext i8 %old to i32
268 ret i32 %e
269}
270
271; CHECK-LABEL: and_sext_i16_i32:
272; CHECK-NEXT: .param i32, i32{{$}}
273; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
274; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
275; CHECK-NEXT: return $pop1{{$}}
276define i32 @and_sext_i16_i32(i16* %p, i32 %v) {
277 %t = trunc i32 %v to i16
278 %old = atomicrmw and i16* %p, i16 %t seq_cst
279 %e = sext i16 %old to i32
280 ret i32 %e
281}
282
283; CHECK-LABEL: and_sext_i8_i64:
284; CHECK-NEXT: .param i32, i64{{$}}
285; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
286; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
287; CHECK-NEXT: return $pop1{{$}}
288define i64 @and_sext_i8_i64(i8* %p, i64 %v) {
289 %t = trunc i64 %v to i8
290 %old = atomicrmw and i8* %p, i8 %t seq_cst
291 %e = sext i8 %old to i64
292 ret i64 %e
293}
294
295; CHECK-LABEL: and_sext_i16_i64:
296; CHECK-NEXT: .param i32, i64{{$}}
297; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
298; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
299; CHECK-NEXT: return $pop1{{$}}
300define i64 @and_sext_i16_i64(i16* %p, i64 %v) {
301 %t = trunc i64 %v to i16
302 %old = atomicrmw and i16* %p, i16 %t seq_cst
303 %e = sext i16 %old to i64
304 ret i64 %e
305}
306
307; 32->64 sext rmw gets selected as i32.atomic.rmw.and, i64_extend_s/i32
308; CHECK-LABEL: and_sext_i32_i64:
309; CHECK-NEXT: .param i32, i64{{$}}
Heejin Ahn9ef850b2018-07-10 16:00:43 +0000310; CHECK: i32.wrap/i64 $push0=, $1{{$}}
Heejin Ahnfed73822018-07-09 22:30:51 +0000311; CHECK: i32.atomic.rmw.and $push1=, 0($0), $pop0{{$}}
312; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
313; CHECK-NEXT: return $pop2{{$}}
314define i64 @and_sext_i32_i64(i32* %p, i64 %v) {
315 %t = trunc i64 %v to i32
316 %old = atomicrmw and i32* %p, i32 %t seq_cst
317 %e = sext i32 %old to i64
318 ret i64 %e
319}
320
321; or
322
323; CHECK-LABEL: or_sext_i8_i32:
324; CHECK-NEXT: .param i32, i32{{$}}
325; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
326; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
327; CHECK-NEXT: return $pop1{{$}}
328define i32 @or_sext_i8_i32(i8* %p, i32 %v) {
329 %t = trunc i32 %v to i8
330 %old = atomicrmw or i8* %p, i8 %t seq_cst
331 %e = sext i8 %old to i32
332 ret i32 %e
333}
334
335; CHECK-LABEL: or_sext_i16_i32:
336; CHECK-NEXT: .param i32, i32{{$}}
337; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
338; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
339; CHECK-NEXT: return $pop1{{$}}
340define i32 @or_sext_i16_i32(i16* %p, i32 %v) {
341 %t = trunc i32 %v to i16
342 %old = atomicrmw or i16* %p, i16 %t seq_cst
343 %e = sext i16 %old to i32
344 ret i32 %e
345}
346
347; CHECK-LABEL: or_sext_i8_i64:
348; CHECK-NEXT: .param i32, i64{{$}}
349; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
350; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
351; CHECK-NEXT: return $pop1{{$}}
352define i64 @or_sext_i8_i64(i8* %p, i64 %v) {
353 %t = trunc i64 %v to i8
354 %old = atomicrmw or i8* %p, i8 %t seq_cst
355 %e = sext i8 %old to i64
356 ret i64 %e
357}
358
359; CHECK-LABEL: or_sext_i16_i64:
360; CHECK-NEXT: .param i32, i64{{$}}
361; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
362; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
363; CHECK-NEXT: return $pop1{{$}}
364define i64 @or_sext_i16_i64(i16* %p, i64 %v) {
365 %t = trunc i64 %v to i16
366 %old = atomicrmw or i16* %p, i16 %t seq_cst
367 %e = sext i16 %old to i64
368 ret i64 %e
369}
370
371; 32->64 sext rmw gets selected as i32.atomic.rmw.or, i64_extend_s/i32
372; CHECK-LABEL: or_sext_i32_i64:
373; CHECK-NEXT: .param i32, i64{{$}}
Heejin Ahn9ef850b2018-07-10 16:00:43 +0000374; CHECK: i32.wrap/i64 $push0=, $1{{$}}
Heejin Ahnfed73822018-07-09 22:30:51 +0000375; CHECK: i32.atomic.rmw.or $push1=, 0($0), $pop0{{$}}
376; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
377; CHECK-NEXT: return $pop2{{$}}
378define i64 @or_sext_i32_i64(i32* %p, i64 %v) {
379 %t = trunc i64 %v to i32
380 %old = atomicrmw or i32* %p, i32 %t seq_cst
381 %e = sext i32 %old to i64
382 ret i64 %e
383}
384
385; xor
386
387; CHECK-LABEL: xor_sext_i8_i32:
388; CHECK-NEXT: .param i32, i32{{$}}
389; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
390; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
391; CHECK-NEXT: return $pop1{{$}}
392define i32 @xor_sext_i8_i32(i8* %p, i32 %v) {
393 %t = trunc i32 %v to i8
394 %old = atomicrmw xor i8* %p, i8 %t seq_cst
395 %e = sext i8 %old to i32
396 ret i32 %e
397}
398
399; CHECK-LABEL: xor_sext_i16_i32:
400; CHECK-NEXT: .param i32, i32{{$}}
401; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
402; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
403; CHECK-NEXT: return $pop1{{$}}
404define i32 @xor_sext_i16_i32(i16* %p, i32 %v) {
405 %t = trunc i32 %v to i16
406 %old = atomicrmw xor i16* %p, i16 %t seq_cst
407 %e = sext i16 %old to i32
408 ret i32 %e
409}
410
411; CHECK-LABEL: xor_sext_i8_i64:
412; CHECK-NEXT: .param i32, i64{{$}}
413; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
414; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
415; CHECK-NEXT: return $pop1{{$}}
416define i64 @xor_sext_i8_i64(i8* %p, i64 %v) {
417 %t = trunc i64 %v to i8
418 %old = atomicrmw xor i8* %p, i8 %t seq_cst
419 %e = sext i8 %old to i64
420 ret i64 %e
421}
422
423; CHECK-LABEL: xor_sext_i16_i64:
424; CHECK-NEXT: .param i32, i64{{$}}
425; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
426; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
427; CHECK-NEXT: return $pop1{{$}}
428define i64 @xor_sext_i16_i64(i16* %p, i64 %v) {
429 %t = trunc i64 %v to i16
430 %old = atomicrmw xor i16* %p, i16 %t seq_cst
431 %e = sext i16 %old to i64
432 ret i64 %e
433}
434
435; 32->64 sext rmw gets selected as i32.atomic.rmw.xor, i64_extend_s/i32
436; CHECK-LABEL: xor_sext_i32_i64:
437; CHECK-NEXT: .param i32, i64{{$}}
Heejin Ahn9ef850b2018-07-10 16:00:43 +0000438; CHECK: i32.wrap/i64 $push0=, $1{{$}}
Heejin Ahnfed73822018-07-09 22:30:51 +0000439; CHECK: i32.atomic.rmw.xor $push1=, 0($0), $pop0{{$}}
440; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
441; CHECK-NEXT: return $pop2{{$}}
442define i64 @xor_sext_i32_i64(i32* %p, i64 %v) {
443 %t = trunc i64 %v to i32
444 %old = atomicrmw xor i32* %p, i32 %t seq_cst
445 %e = sext i32 %old to i64
446 ret i64 %e
447}
448
449; xchg
450
451; CHECK-LABEL: xchg_sext_i8_i32:
452; CHECK-NEXT: .param i32, i32{{$}}
453; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
454; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
455; CHECK-NEXT: return $pop1{{$}}
456define i32 @xchg_sext_i8_i32(i8* %p, i32 %v) {
457 %t = trunc i32 %v to i8
458 %old = atomicrmw xchg i8* %p, i8 %t seq_cst
459 %e = sext i8 %old to i32
460 ret i32 %e
461}
462
463; CHECK-LABEL: xchg_sext_i16_i32:
464; CHECK-NEXT: .param i32, i32{{$}}
465; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
466; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
467; CHECK-NEXT: return $pop1{{$}}
468define i32 @xchg_sext_i16_i32(i16* %p, i32 %v) {
469 %t = trunc i32 %v to i16
470 %old = atomicrmw xchg i16* %p, i16 %t seq_cst
471 %e = sext i16 %old to i32
472 ret i32 %e
473}
474
475; CHECK-LABEL: xchg_sext_i8_i64:
476; CHECK-NEXT: .param i32, i64{{$}}
477; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
478; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
479; CHECK-NEXT: return $pop1{{$}}
480define i64 @xchg_sext_i8_i64(i8* %p, i64 %v) {
481 %t = trunc i64 %v to i8
482 %old = atomicrmw xchg i8* %p, i8 %t seq_cst
483 %e = sext i8 %old to i64
484 ret i64 %e
485}
486
487; CHECK-LABEL: xchg_sext_i16_i64:
488; CHECK-NEXT: .param i32, i64{{$}}
489; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
490; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
491; CHECK-NEXT: return $pop1{{$}}
492define i64 @xchg_sext_i16_i64(i16* %p, i64 %v) {
493 %t = trunc i64 %v to i16
494 %old = atomicrmw xchg i16* %p, i16 %t seq_cst
495 %e = sext i16 %old to i64
496 ret i64 %e
497}
498
499; 32->64 sext rmw gets selected as i32.atomic.rmw.xchg, i64_extend_s/i32
500; CHECK-LABEL: xchg_sext_i32_i64:
501; CHECK-NEXT: .param i32, i64{{$}}
Heejin Ahn9ef850b2018-07-10 16:00:43 +0000502; CHECK: i32.wrap/i64 $push0=, $1{{$}}
Heejin Ahnfed73822018-07-09 22:30:51 +0000503; CHECK: i32.atomic.rmw.xchg $push1=, 0($0), $pop0{{$}}
504; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
505; CHECK-NEXT: return $pop2{{$}}
506define i64 @xchg_sext_i32_i64(i32* %p, i64 %v) {
507 %t = trunc i64 %v to i32
508 %old = atomicrmw xchg i32* %p, i32 %t seq_cst
509 %e = sext i32 %old to i64
510 ret i64 %e
511}
512
513;===----------------------------------------------------------------------------
514; Atomic truncating & zero-extending RMWs
515;===----------------------------------------------------------------------------
516
517; add
518
519; CHECK-LABEL: add_zext_i8_i32:
520; CHECK-NEXT: .param i32, i32{{$}}
521; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
522; CHECK-NEXT: return $pop0{{$}}
523define i32 @add_zext_i8_i32(i8* %p, i32 %v) {
524 %t = trunc i32 %v to i8
525 %old = atomicrmw add i8* %p, i8 %t seq_cst
526 %e = zext i8 %old to i32
527 ret i32 %e
528}
529
530; CHECK-LABEL: add_zext_i16_i32:
531; CHECK-NEXT: .param i32, i32{{$}}
532; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
533; CHECK-NEXT: return $pop0{{$}}
534define i32 @add_zext_i16_i32(i16* %p, i32 %v) {
535 %t = trunc i32 %v to i16
536 %old = atomicrmw add i16* %p, i16 %t seq_cst
537 %e = zext i16 %old to i32
538 ret i32 %e
539}
540
541; CHECK-LABEL: add_zext_i8_i64:
542; CHECK-NEXT: .param i32, i64{{$}}
543; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
544; CHECK-NEXT: return $pop0{{$}}
545define i64 @add_zext_i8_i64(i8* %p, i64 %v) {
546 %t = trunc i64 %v to i8
547 %old = atomicrmw add i8* %p, i8 %t seq_cst
548 %e = zext i8 %old to i64
549 ret i64 %e
550}
551
552; CHECK-LABEL: add_zext_i16_i64:
553; CHECK-NEXT: .param i32, i64{{$}}
554; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
555; CHECK-NEXT: return $pop0{{$}}
556define i64 @add_zext_i16_i64(i16* %p, i64 %v) {
557 %t = trunc i64 %v to i16
558 %old = atomicrmw add i16* %p, i16 %t seq_cst
559 %e = zext i16 %old to i64
560 ret i64 %e
561}
562
563; CHECK-LABEL: add_zext_i32_i64:
564; CHECK-NEXT: .param i32, i64{{$}}
565; CHECK: i64.atomic.rmw32_u.add $push0=, 0($0), $1{{$}}
566; CHECK-NEXT: return $pop0{{$}}
567define i64 @add_zext_i32_i64(i32* %p, i64 %v) {
568 %t = trunc i64 %v to i32
569 %old = atomicrmw add i32* %p, i32 %t seq_cst
570 %e = zext i32 %old to i64
571 ret i64 %e
572}
573
574; sub
575
576; CHECK-LABEL: sub_zext_i8_i32:
577; CHECK-NEXT: .param i32, i32{{$}}
578; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
579; CHECK-NEXT: return $pop0{{$}}
580define i32 @sub_zext_i8_i32(i8* %p, i32 %v) {
581 %t = trunc i32 %v to i8
582 %old = atomicrmw sub i8* %p, i8 %t seq_cst
583 %e = zext i8 %old to i32
584 ret i32 %e
585}
586
587; CHECK-LABEL: sub_zext_i16_i32:
588; CHECK-NEXT: .param i32, i32{{$}}
589; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
590; CHECK-NEXT: return $pop0{{$}}
591define i32 @sub_zext_i16_i32(i16* %p, i32 %v) {
592 %t = trunc i32 %v to i16
593 %old = atomicrmw sub i16* %p, i16 %t seq_cst
594 %e = zext i16 %old to i32
595 ret i32 %e
596}
597
598; CHECK-LABEL: sub_zext_i8_i64:
599; CHECK-NEXT: .param i32, i64{{$}}
600; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
601; CHECK-NEXT: return $pop0{{$}}
602define i64 @sub_zext_i8_i64(i8* %p, i64 %v) {
603 %t = trunc i64 %v to i8
604 %old = atomicrmw sub i8* %p, i8 %t seq_cst
605 %e = zext i8 %old to i64
606 ret i64 %e
607}
608
609; CHECK-LABEL: sub_zext_i16_i64:
610; CHECK-NEXT: .param i32, i64{{$}}
611; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
612; CHECK-NEXT: return $pop0{{$}}
613define i64 @sub_zext_i16_i64(i16* %p, i64 %v) {
614 %t = trunc i64 %v to i16
615 %old = atomicrmw sub i16* %p, i16 %t seq_cst
616 %e = zext i16 %old to i64
617 ret i64 %e
618}
619
620; CHECK-LABEL: sub_zext_i32_i64:
621; CHECK-NEXT: .param i32, i64{{$}}
622; CHECK: i64.atomic.rmw32_u.sub $push0=, 0($0), $1{{$}}
623; CHECK-NEXT: return $pop0{{$}}
624define i64 @sub_zext_i32_i64(i32* %p, i64 %v) {
625 %t = trunc i64 %v to i32
626 %old = atomicrmw sub i32* %p, i32 %t seq_cst
627 %e = zext i32 %old to i64
628 ret i64 %e
629}
630
631; and
632
633; CHECK-LABEL: and_zext_i8_i32:
634; CHECK-NEXT: .param i32, i32{{$}}
635; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
636; CHECK-NEXT: return $pop0{{$}}
637define i32 @and_zext_i8_i32(i8* %p, i32 %v) {
638 %t = trunc i32 %v to i8
639 %old = atomicrmw and i8* %p, i8 %t seq_cst
640 %e = zext i8 %old to i32
641 ret i32 %e
642}
643
644; CHECK-LABEL: and_zext_i16_i32:
645; CHECK-NEXT: .param i32, i32{{$}}
646; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
647; CHECK-NEXT: return $pop0{{$}}
648define i32 @and_zext_i16_i32(i16* %p, i32 %v) {
649 %t = trunc i32 %v to i16
650 %old = atomicrmw and i16* %p, i16 %t seq_cst
651 %e = zext i16 %old to i32
652 ret i32 %e
653}
654
655; CHECK-LABEL: and_zext_i8_i64:
656; CHECK-NEXT: .param i32, i64{{$}}
657; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
658; CHECK-NEXT: return $pop0{{$}}
659define i64 @and_zext_i8_i64(i8* %p, i64 %v) {
660 %t = trunc i64 %v to i8
661 %old = atomicrmw and i8* %p, i8 %t seq_cst
662 %e = zext i8 %old to i64
663 ret i64 %e
664}
665
666; CHECK-LABEL: and_zext_i16_i64:
667; CHECK-NEXT: .param i32, i64{{$}}
668; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
669; CHECK-NEXT: return $pop0{{$}}
670define i64 @and_zext_i16_i64(i16* %p, i64 %v) {
671 %t = trunc i64 %v to i16
672 %old = atomicrmw and i16* %p, i16 %t seq_cst
673 %e = zext i16 %old to i64
674 ret i64 %e
675}
676
677; CHECK-LABEL: and_zext_i32_i64:
678; CHECK-NEXT: .param i32, i64{{$}}
679; CHECK: i64.atomic.rmw32_u.and $push0=, 0($0), $1{{$}}
680; CHECK-NEXT: return $pop0{{$}}
681define i64 @and_zext_i32_i64(i32* %p, i64 %v) {
682 %t = trunc i64 %v to i32
683 %old = atomicrmw and i32* %p, i32 %t seq_cst
684 %e = zext i32 %old to i64
685 ret i64 %e
686}
687
688; or
689
690; CHECK-LABEL: or_zext_i8_i32:
691; CHECK-NEXT: .param i32, i32{{$}}
692; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
693; CHECK-NEXT: return $pop0{{$}}
694define i32 @or_zext_i8_i32(i8* %p, i32 %v) {
695 %t = trunc i32 %v to i8
696 %old = atomicrmw or i8* %p, i8 %t seq_cst
697 %e = zext i8 %old to i32
698 ret i32 %e
699}
700
701; CHECK-LABEL: or_zext_i16_i32:
702; CHECK-NEXT: .param i32, i32{{$}}
703; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
704; CHECK-NEXT: return $pop0{{$}}
705define i32 @or_zext_i16_i32(i16* %p, i32 %v) {
706 %t = trunc i32 %v to i16
707 %old = atomicrmw or i16* %p, i16 %t seq_cst
708 %e = zext i16 %old to i32
709 ret i32 %e
710}
711
712; CHECK-LABEL: or_zext_i8_i64:
713; CHECK-NEXT: .param i32, i64{{$}}
714; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
715; CHECK-NEXT: return $pop0{{$}}
716define i64 @or_zext_i8_i64(i8* %p, i64 %v) {
717 %t = trunc i64 %v to i8
718 %old = atomicrmw or i8* %p, i8 %t seq_cst
719 %e = zext i8 %old to i64
720 ret i64 %e
721}
722
723; CHECK-LABEL: or_zext_i16_i64:
724; CHECK-NEXT: .param i32, i64{{$}}
725; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
726; CHECK-NEXT: return $pop0{{$}}
727define i64 @or_zext_i16_i64(i16* %p, i64 %v) {
728 %t = trunc i64 %v to i16
729 %old = atomicrmw or i16* %p, i16 %t seq_cst
730 %e = zext i16 %old to i64
731 ret i64 %e
732}
733
734; CHECK-LABEL: or_zext_i32_i64:
735; CHECK-NEXT: .param i32, i64{{$}}
736; CHECK: i64.atomic.rmw32_u.or $push0=, 0($0), $1{{$}}
737; CHECK-NEXT: return $pop0{{$}}
738define i64 @or_zext_i32_i64(i32* %p, i64 %v) {
739 %t = trunc i64 %v to i32
740 %old = atomicrmw or i32* %p, i32 %t seq_cst
741 %e = zext i32 %old to i64
742 ret i64 %e
743}
744
745; xor
746
747; CHECK-LABEL: xor_zext_i8_i32:
748; CHECK-NEXT: .param i32, i32{{$}}
749; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
750; CHECK-NEXT: return $pop0{{$}}
751define i32 @xor_zext_i8_i32(i8* %p, i32 %v) {
752 %t = trunc i32 %v to i8
753 %old = atomicrmw xor i8* %p, i8 %t seq_cst
754 %e = zext i8 %old to i32
755 ret i32 %e
756}
757
758; CHECK-LABEL: xor_zext_i16_i32:
759; CHECK-NEXT: .param i32, i32{{$}}
760; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
761; CHECK-NEXT: return $pop0{{$}}
762define i32 @xor_zext_i16_i32(i16* %p, i32 %v) {
763 %t = trunc i32 %v to i16
764 %old = atomicrmw xor i16* %p, i16 %t seq_cst
765 %e = zext i16 %old to i32
766 ret i32 %e
767}
768
769; CHECK-LABEL: xor_zext_i8_i64:
770; CHECK-NEXT: .param i32, i64{{$}}
771; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
772; CHECK-NEXT: return $pop0{{$}}
773define i64 @xor_zext_i8_i64(i8* %p, i64 %v) {
774 %t = trunc i64 %v to i8
775 %old = atomicrmw xor i8* %p, i8 %t seq_cst
776 %e = zext i8 %old to i64
777 ret i64 %e
778}
779
780; CHECK-LABEL: xor_zext_i16_i64:
781; CHECK-NEXT: .param i32, i64{{$}}
782; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
783; CHECK-NEXT: return $pop0{{$}}
784define i64 @xor_zext_i16_i64(i16* %p, i64 %v) {
785 %t = trunc i64 %v to i16
786 %old = atomicrmw xor i16* %p, i16 %t seq_cst
787 %e = zext i16 %old to i64
788 ret i64 %e
789}
790
791; CHECK-LABEL: xor_zext_i32_i64:
792; CHECK-NEXT: .param i32, i64{{$}}
793; CHECK: i64.atomic.rmw32_u.xor $push0=, 0($0), $1{{$}}
794; CHECK-NEXT: return $pop0{{$}}
795define i64 @xor_zext_i32_i64(i32* %p, i64 %v) {
796 %t = trunc i64 %v to i32
797 %old = atomicrmw xor i32* %p, i32 %t seq_cst
798 %e = zext i32 %old to i64
799 ret i64 %e
800}
801
802; xchg
803
804; CHECK-LABEL: xchg_zext_i8_i32:
805; CHECK-NEXT: .param i32, i32{{$}}
806; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
807; CHECK-NEXT: return $pop0{{$}}
808define i32 @xchg_zext_i8_i32(i8* %p, i32 %v) {
809 %t = trunc i32 %v to i8
810 %old = atomicrmw xchg i8* %p, i8 %t seq_cst
811 %e = zext i8 %old to i32
812 ret i32 %e
813}
814
815; CHECK-LABEL: xchg_zext_i16_i32:
816; CHECK-NEXT: .param i32, i32{{$}}
817; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
818; CHECK-NEXT: return $pop0{{$}}
819define i32 @xchg_zext_i16_i32(i16* %p, i32 %v) {
820 %t = trunc i32 %v to i16
821 %old = atomicrmw xchg i16* %p, i16 %t seq_cst
822 %e = zext i16 %old to i32
823 ret i32 %e
824}
825
826; CHECK-LABEL: xchg_zext_i8_i64:
827; CHECK-NEXT: .param i32, i64{{$}}
828; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
829; CHECK-NEXT: return $pop0{{$}}
830define i64 @xchg_zext_i8_i64(i8* %p, i64 %v) {
831 %t = trunc i64 %v to i8
832 %old = atomicrmw xchg i8* %p, i8 %t seq_cst
833 %e = zext i8 %old to i64
834 ret i64 %e
835}
836
837; CHECK-LABEL: xchg_zext_i16_i64:
838; CHECK-NEXT: .param i32, i64{{$}}
839; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
840; CHECK-NEXT: return $pop0{{$}}
841define i64 @xchg_zext_i16_i64(i16* %p, i64 %v) {
842 %t = trunc i64 %v to i16
843 %old = atomicrmw xchg i16* %p, i16 %t seq_cst
844 %e = zext i16 %old to i64
845 ret i64 %e
846}
847
848; CHECK-LABEL: xchg_zext_i32_i64:
849; CHECK-NEXT: .param i32, i64{{$}}
850; CHECK: i64.atomic.rmw32_u.xchg $push0=, 0($0), $1{{$}}
851; CHECK-NEXT: return $pop0{{$}}
852define i64 @xchg_zext_i32_i64(i32* %p, i64 %v) {
853 %t = trunc i64 %v to i32
854 %old = atomicrmw xchg i32* %p, i32 %t seq_cst
855 %e = zext i32 %old to i64
856 ret i64 %e
857}