1; 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; CHECK-LABEL: cmpxchg_i32_loaded_value:
68; CHECK-NEXT: .param i32, i32, i32{{$}}
69; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
70; CHECK-NEXT: return $pop0{{$}}
71define i32 @cmpxchg_i32_loaded_value(i32* %p, i32 %exp, i32 %new) {
72  %pair = cmpxchg i32* %p, i32 %exp, i32 %new seq_cst seq_cst
73  %old = extractvalue { i32, i1 } %pair, 0
74  ret i32 %old
75}
76
77; CHECK-LABEL: cmpxchg_i32_success:
78; CHECK-NEXT: .param i32, i32, i32{{$}}
79; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
80; CHECK-NEXT: i32.eq $push1=, $pop0, $1{{$}}
81; CHECK-NEXT: return $pop1{{$}}
82define i1 @cmpxchg_i32_success(i32* %p, i32 %exp, i32 %new) {
83  %pair = cmpxchg i32* %p, i32 %exp, i32 %new seq_cst seq_cst
84  %succ = extractvalue { i32, i1 } %pair, 1
85  ret i1 %succ
86}
87
88;===----------------------------------------------------------------------------
89; Atomic read-modify-writes: 64-bit
90;===----------------------------------------------------------------------------
91
92; CHECK-LABEL: add_i64:
93; CHECK-NEXT: .param i32, i64{{$}}
94; CHECK: i64.atomic.rmw.add $push0=, 0($0), $1{{$}}
95; CHECK-NEXT: return $pop0{{$}}
96define i64 @add_i64(i64* %p, i64 %v) {
97  %old = atomicrmw add i64* %p, i64 %v seq_cst
98  ret i64 %old
99}
100
101; CHECK-LABEL: sub_i64:
102; CHECK-NEXT: .param i32, i64{{$}}
103; CHECK: i64.atomic.rmw.sub $push0=, 0($0), $1{{$}}
104; CHECK-NEXT: return $pop0{{$}}
105define i64 @sub_i64(i64* %p, i64 %v) {
106  %old = atomicrmw sub i64* %p, i64 %v seq_cst
107  ret i64 %old
108}
109
110; CHECK-LABEL: and_i64:
111; CHECK-NEXT: .param i32, i64{{$}}
112; CHECK: i64.atomic.rmw.and $push0=, 0($0), $1{{$}}
113; CHECK-NEXT: return $pop0{{$}}
114define i64 @and_i64(i64* %p, i64 %v) {
115  %old = atomicrmw and i64* %p, i64 %v seq_cst
116  ret i64 %old
117}
118
119; CHECK-LABEL: or_i64:
120; CHECK-NEXT: .param i32, i64{{$}}
121; CHECK: i64.atomic.rmw.or $push0=, 0($0), $1{{$}}
122; CHECK-NEXT: return $pop0{{$}}
123define i64 @or_i64(i64* %p, i64 %v) {
124  %old = atomicrmw or i64* %p, i64 %v seq_cst
125  ret i64 %old
126}
127
128; CHECK-LABEL: xor_i64:
129; CHECK-NEXT: .param i32, i64{{$}}
130; CHECK: i64.atomic.rmw.xor $push0=, 0($0), $1{{$}}
131; CHECK-NEXT: return $pop0{{$}}
132define i64 @xor_i64(i64* %p, i64 %v) {
133  %old = atomicrmw xor i64* %p, i64 %v seq_cst
134  ret i64 %old
135}
136
137; CHECK-LABEL: xchg_i64:
138; CHECK-NEXT: .param i32, i64{{$}}
139; CHECK: i64.atomic.rmw.xchg $push0=, 0($0), $1{{$}}
140; CHECK-NEXT: return $pop0{{$}}
141define i64 @xchg_i64(i64* %p, i64 %v) {
142  %old = atomicrmw xchg i64* %p, i64 %v seq_cst
143  ret i64 %old
144}
145
146; CHECK-LABEL: cmpxchg_i64_loaded_value:
147; CHECK-NEXT: .param i32, i64, i64{{$}}
148; CHECK: i64.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
149; CHECK-NEXT: return $pop0{{$}}
150define i64 @cmpxchg_i64_loaded_value(i64* %p, i64 %exp, i64 %new) {
151  %pair = cmpxchg i64* %p, i64 %exp, i64 %new seq_cst seq_cst
152  %old = extractvalue { i64, i1 } %pair, 0
153  ret i64 %old
154}
155
156; CHECK-LABEL: cmpxchg_i64_success:
157; CHECK-NEXT: .param i32, i64, i64{{$}}
158; CHECK: i64.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
159; CHECK-NEXT: i64.eq $push1=, $pop0, $1{{$}}
160; CHECK-NEXT: return $pop1{{$}}
161define i1 @cmpxchg_i64_success(i64* %p, i64 %exp, i64 %new) {
162  %pair = cmpxchg i64* %p, i64 %exp, i64 %new seq_cst seq_cst
163  %succ = extractvalue { i64, i1 } %pair, 1
164  ret i1 %succ
165}
166
167;===----------------------------------------------------------------------------
168; Atomic truncating & sign-extending RMWs
169;===----------------------------------------------------------------------------
170
171; add
172
173; CHECK-LABEL: add_sext_i8_i32:
174; CHECK-NEXT: .param i32, i32{{$}}
175; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
176; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
177; CHECK-NEXT: return $pop1{{$}}
178define i32 @add_sext_i8_i32(i8* %p, i32 %v) {
179  %t = trunc i32 %v to i8
180  %old = atomicrmw add i8* %p, i8 %t seq_cst
181  %e = sext i8 %old to i32
182  ret i32 %e
183}
184
185; CHECK-LABEL: add_sext_i16_i32:
186; CHECK-NEXT: .param i32, i32{{$}}
187; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
188; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
189; CHECK-NEXT: return $pop1{{$}}
190define i32 @add_sext_i16_i32(i16* %p, i32 %v) {
191  %t = trunc i32 %v to i16
192  %old = atomicrmw add i16* %p, i16 %t seq_cst
193  %e = sext i16 %old to i32
194  ret i32 %e
195}
196
197; CHECK-LABEL: add_sext_i8_i64:
198; CHECK-NEXT: .param i32, i64{{$}}
199; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
200; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
201; CHECK-NEXT: return $pop1{{$}}
202define i64 @add_sext_i8_i64(i8* %p, i64 %v) {
203  %t = trunc i64 %v to i8
204  %old = atomicrmw add i8* %p, i8 %t seq_cst
205  %e = sext i8 %old to i64
206  ret i64 %e
207}
208
209; CHECK-LABEL: add_sext_i16_i64:
210; CHECK-NEXT: .param i32, i64{{$}}
211; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
212; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
213; CHECK-NEXT: return $pop1{{$}}
214define i64 @add_sext_i16_i64(i16* %p, i64 %v) {
215  %t = trunc i64 %v to i16
216  %old = atomicrmw add i16* %p, i16 %t seq_cst
217  %e = sext i16 %old to i64
218  ret i64 %e
219}
220
221; 32->64 sext rmw gets selected as i32.atomic.rmw.add, i64_extend_s/i32
222; CHECK-LABEL: add_sext_i32_i64:
223; CHECK-NEXT: .param i32, i64{{$}}
224; CHECK: i32.wrap/i64 $push0=, $1{{$}}
225; CHECK: i32.atomic.rmw.add $push1=, 0($0), $pop0{{$}}
226; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
227; CHECK-NEXT: return $pop2{{$}}
228define i64 @add_sext_i32_i64(i32* %p, i64 %v) {
229  %t = trunc i64 %v to i32
230  %old = atomicrmw add i32* %p, i32 %t seq_cst
231  %e = sext i32 %old to i64
232  ret i64 %e
233}
234
235; sub
236
237; CHECK-LABEL: sub_sext_i8_i32:
238; CHECK-NEXT: .param i32, i32{{$}}
239; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
240; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
241; CHECK-NEXT: return $pop1{{$}}
242define i32 @sub_sext_i8_i32(i8* %p, i32 %v) {
243  %t = trunc i32 %v to i8
244  %old = atomicrmw sub i8* %p, i8 %t seq_cst
245  %e = sext i8 %old to i32
246  ret i32 %e
247}
248
249; CHECK-LABEL: sub_sext_i16_i32:
250; CHECK-NEXT: .param i32, i32{{$}}
251; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
252; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
253; CHECK-NEXT: return $pop1{{$}}
254define i32 @sub_sext_i16_i32(i16* %p, i32 %v) {
255  %t = trunc i32 %v to i16
256  %old = atomicrmw sub i16* %p, i16 %t seq_cst
257  %e = sext i16 %old to i32
258  ret i32 %e
259}
260
261; CHECK-LABEL: sub_sext_i8_i64:
262; CHECK-NEXT: .param i32, i64{{$}}
263; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
264; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
265; CHECK-NEXT: return $pop1{{$}}
266define i64 @sub_sext_i8_i64(i8* %p, i64 %v) {
267  %t = trunc i64 %v to i8
268  %old = atomicrmw sub i8* %p, i8 %t seq_cst
269  %e = sext i8 %old to i64
270  ret i64 %e
271}
272
273; CHECK-LABEL: sub_sext_i16_i64:
274; CHECK-NEXT: .param i32, i64{{$}}
275; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
276; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
277; CHECK-NEXT: return $pop1{{$}}
278define i64 @sub_sext_i16_i64(i16* %p, i64 %v) {
279  %t = trunc i64 %v to i16
280  %old = atomicrmw sub i16* %p, i16 %t seq_cst
281  %e = sext i16 %old to i64
282  ret i64 %e
283}
284
285; 32->64 sext rmw gets selected as i32.atomic.rmw.sub, i64_extend_s/i32
286; CHECK-LABEL: sub_sext_i32_i64:
287; CHECK-NEXT: .param i32, i64{{$}}
288; CHECK: i32.wrap/i64 $push0=, $1
289; CHECK: i32.atomic.rmw.sub $push1=, 0($0), $pop0{{$}}
290; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
291; CHECK-NEXT: return $pop2{{$}}
292define i64 @sub_sext_i32_i64(i32* %p, i64 %v) {
293  %t = trunc i64 %v to i32
294  %old = atomicrmw sub i32* %p, i32 %t seq_cst
295  %e = sext i32 %old to i64
296  ret i64 %e
297}
298
299; and
300
301; CHECK-LABEL: and_sext_i8_i32:
302; CHECK-NEXT: .param i32, i32{{$}}
303; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
304; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
305; CHECK-NEXT: return $pop1{{$}}
306define i32 @and_sext_i8_i32(i8* %p, i32 %v) {
307  %t = trunc i32 %v to i8
308  %old = atomicrmw and i8* %p, i8 %t seq_cst
309  %e = sext i8 %old to i32
310  ret i32 %e
311}
312
313; CHECK-LABEL: and_sext_i16_i32:
314; CHECK-NEXT: .param i32, i32{{$}}
315; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
316; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
317; CHECK-NEXT: return $pop1{{$}}
318define i32 @and_sext_i16_i32(i16* %p, i32 %v) {
319  %t = trunc i32 %v to i16
320  %old = atomicrmw and i16* %p, i16 %t seq_cst
321  %e = sext i16 %old to i32
322  ret i32 %e
323}
324
325; CHECK-LABEL: and_sext_i8_i64:
326; CHECK-NEXT: .param i32, i64{{$}}
327; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
328; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
329; CHECK-NEXT: return $pop1{{$}}
330define i64 @and_sext_i8_i64(i8* %p, i64 %v) {
331  %t = trunc i64 %v to i8
332  %old = atomicrmw and i8* %p, i8 %t seq_cst
333  %e = sext i8 %old to i64
334  ret i64 %e
335}
336
337; CHECK-LABEL: and_sext_i16_i64:
338; CHECK-NEXT: .param i32, i64{{$}}
339; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
340; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
341; CHECK-NEXT: return $pop1{{$}}
342define i64 @and_sext_i16_i64(i16* %p, i64 %v) {
343  %t = trunc i64 %v to i16
344  %old = atomicrmw and i16* %p, i16 %t seq_cst
345  %e = sext i16 %old to i64
346  ret i64 %e
347}
348
349; 32->64 sext rmw gets selected as i32.atomic.rmw.and, i64_extend_s/i32
350; CHECK-LABEL: and_sext_i32_i64:
351; CHECK-NEXT: .param i32, i64{{$}}
352; CHECK: i32.wrap/i64 $push0=, $1{{$}}
353; CHECK: i32.atomic.rmw.and $push1=, 0($0), $pop0{{$}}
354; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
355; CHECK-NEXT: return $pop2{{$}}
356define i64 @and_sext_i32_i64(i32* %p, i64 %v) {
357  %t = trunc i64 %v to i32
358  %old = atomicrmw and i32* %p, i32 %t seq_cst
359  %e = sext i32 %old to i64
360  ret i64 %e
361}
362
363; or
364
365; CHECK-LABEL: or_sext_i8_i32:
366; CHECK-NEXT: .param i32, i32{{$}}
367; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
368; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
369; CHECK-NEXT: return $pop1{{$}}
370define i32 @or_sext_i8_i32(i8* %p, i32 %v) {
371  %t = trunc i32 %v to i8
372  %old = atomicrmw or i8* %p, i8 %t seq_cst
373  %e = sext i8 %old to i32
374  ret i32 %e
375}
376
377; CHECK-LABEL: or_sext_i16_i32:
378; CHECK-NEXT: .param i32, i32{{$}}
379; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
380; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
381; CHECK-NEXT: return $pop1{{$}}
382define i32 @or_sext_i16_i32(i16* %p, i32 %v) {
383  %t = trunc i32 %v to i16
384  %old = atomicrmw or i16* %p, i16 %t seq_cst
385  %e = sext i16 %old to i32
386  ret i32 %e
387}
388
389; CHECK-LABEL: or_sext_i8_i64:
390; CHECK-NEXT: .param i32, i64{{$}}
391; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
392; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
393; CHECK-NEXT: return $pop1{{$}}
394define i64 @or_sext_i8_i64(i8* %p, i64 %v) {
395  %t = trunc i64 %v to i8
396  %old = atomicrmw or i8* %p, i8 %t seq_cst
397  %e = sext i8 %old to i64
398  ret i64 %e
399}
400
401; CHECK-LABEL: or_sext_i16_i64:
402; CHECK-NEXT: .param i32, i64{{$}}
403; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
404; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
405; CHECK-NEXT: return $pop1{{$}}
406define i64 @or_sext_i16_i64(i16* %p, i64 %v) {
407  %t = trunc i64 %v to i16
408  %old = atomicrmw or i16* %p, i16 %t seq_cst
409  %e = sext i16 %old to i64
410  ret i64 %e
411}
412
413; 32->64 sext rmw gets selected as i32.atomic.rmw.or, i64_extend_s/i32
414; CHECK-LABEL: or_sext_i32_i64:
415; CHECK-NEXT: .param i32, i64{{$}}
416; CHECK: i32.wrap/i64 $push0=, $1{{$}}
417; CHECK: i32.atomic.rmw.or $push1=, 0($0), $pop0{{$}}
418; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
419; CHECK-NEXT: return $pop2{{$}}
420define i64 @or_sext_i32_i64(i32* %p, i64 %v) {
421  %t = trunc i64 %v to i32
422  %old = atomicrmw or i32* %p, i32 %t seq_cst
423  %e = sext i32 %old to i64
424  ret i64 %e
425}
426
427; xor
428
429; CHECK-LABEL: xor_sext_i8_i32:
430; CHECK-NEXT: .param i32, i32{{$}}
431; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
432; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
433; CHECK-NEXT: return $pop1{{$}}
434define i32 @xor_sext_i8_i32(i8* %p, i32 %v) {
435  %t = trunc i32 %v to i8
436  %old = atomicrmw xor i8* %p, i8 %t seq_cst
437  %e = sext i8 %old to i32
438  ret i32 %e
439}
440
441; CHECK-LABEL: xor_sext_i16_i32:
442; CHECK-NEXT: .param i32, i32{{$}}
443; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
444; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
445; CHECK-NEXT: return $pop1{{$}}
446define i32 @xor_sext_i16_i32(i16* %p, i32 %v) {
447  %t = trunc i32 %v to i16
448  %old = atomicrmw xor i16* %p, i16 %t seq_cst
449  %e = sext i16 %old to i32
450  ret i32 %e
451}
452
453; CHECK-LABEL: xor_sext_i8_i64:
454; CHECK-NEXT: .param i32, i64{{$}}
455; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
456; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
457; CHECK-NEXT: return $pop1{{$}}
458define i64 @xor_sext_i8_i64(i8* %p, i64 %v) {
459  %t = trunc i64 %v to i8
460  %old = atomicrmw xor i8* %p, i8 %t seq_cst
461  %e = sext i8 %old to i64
462  ret i64 %e
463}
464
465; CHECK-LABEL: xor_sext_i16_i64:
466; CHECK-NEXT: .param i32, i64{{$}}
467; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
468; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
469; CHECK-NEXT: return $pop1{{$}}
470define i64 @xor_sext_i16_i64(i16* %p, i64 %v) {
471  %t = trunc i64 %v to i16
472  %old = atomicrmw xor i16* %p, i16 %t seq_cst
473  %e = sext i16 %old to i64
474  ret i64 %e
475}
476
477; 32->64 sext rmw gets selected as i32.atomic.rmw.xor, i64_extend_s/i32
478; CHECK-LABEL: xor_sext_i32_i64:
479; CHECK-NEXT: .param i32, i64{{$}}
480; CHECK: i32.wrap/i64 $push0=, $1{{$}}
481; CHECK: i32.atomic.rmw.xor $push1=, 0($0), $pop0{{$}}
482; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
483; CHECK-NEXT: return $pop2{{$}}
484define i64 @xor_sext_i32_i64(i32* %p, i64 %v) {
485  %t = trunc i64 %v to i32
486  %old = atomicrmw xor i32* %p, i32 %t seq_cst
487  %e = sext i32 %old to i64
488  ret i64 %e
489}
490
491; xchg
492
493; CHECK-LABEL: xchg_sext_i8_i32:
494; CHECK-NEXT: .param i32, i32{{$}}
495; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
496; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
497; CHECK-NEXT: return $pop1{{$}}
498define i32 @xchg_sext_i8_i32(i8* %p, i32 %v) {
499  %t = trunc i32 %v to i8
500  %old = atomicrmw xchg i8* %p, i8 %t seq_cst
501  %e = sext i8 %old to i32
502  ret i32 %e
503}
504
505; CHECK-LABEL: xchg_sext_i16_i32:
506; CHECK-NEXT: .param i32, i32{{$}}
507; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
508; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
509; CHECK-NEXT: return $pop1{{$}}
510define i32 @xchg_sext_i16_i32(i16* %p, i32 %v) {
511  %t = trunc i32 %v to i16
512  %old = atomicrmw xchg i16* %p, i16 %t seq_cst
513  %e = sext i16 %old to i32
514  ret i32 %e
515}
516
517; CHECK-LABEL: xchg_sext_i8_i64:
518; CHECK-NEXT: .param i32, i64{{$}}
519; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
520; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
521; CHECK-NEXT: return $pop1{{$}}
522define i64 @xchg_sext_i8_i64(i8* %p, i64 %v) {
523  %t = trunc i64 %v to i8
524  %old = atomicrmw xchg i8* %p, i8 %t seq_cst
525  %e = sext i8 %old to i64
526  ret i64 %e
527}
528
529; CHECK-LABEL: xchg_sext_i16_i64:
530; CHECK-NEXT: .param i32, i64{{$}}
531; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
532; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
533; CHECK-NEXT: return $pop1{{$}}
534define i64 @xchg_sext_i16_i64(i16* %p, i64 %v) {
535  %t = trunc i64 %v to i16
536  %old = atomicrmw xchg i16* %p, i16 %t seq_cst
537  %e = sext i16 %old to i64
538  ret i64 %e
539}
540
541; 32->64 sext rmw gets selected as i32.atomic.rmw.xchg, i64_extend_s/i32
542; CHECK-LABEL: xchg_sext_i32_i64:
543; CHECK-NEXT: .param i32, i64{{$}}
544; CHECK: i32.wrap/i64 $push0=, $1{{$}}
545; CHECK: i32.atomic.rmw.xchg $push1=, 0($0), $pop0{{$}}
546; CHECK-NEXT: i64.extend_s/i32 $push2=, $pop1{{$}}
547; CHECK-NEXT: return $pop2{{$}}
548define i64 @xchg_sext_i32_i64(i32* %p, i64 %v) {
549  %t = trunc i64 %v to i32
550  %old = atomicrmw xchg i32* %p, i32 %t seq_cst
551  %e = sext i32 %old to i64
552  ret i64 %e
553}
554
555; cmpxchg
556
557; CHECK-LABEL: cmpxchg_sext_i8_i32:
558; CHECK-NEXT: .param i32, i32, i32{{$}}
559; CHECK: i32.atomic.rmw8_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
560; CHECK-NEXT: i32.extend8_s $push1=, $pop0{{$}}
561; CHECK-NEXT: return $pop1{{$}}
562define i32 @cmpxchg_sext_i8_i32(i8* %p, i32 %exp, i32 %new) {
563  %exp_t = trunc i32 %exp to i8
564  %new_t = trunc i32 %new to i8
565  %pair = cmpxchg i8* %p, i8 %exp_t, i8 %new_t seq_cst seq_cst
566  %old = extractvalue { i8, i1 } %pair, 0
567  %e = sext i8 %old to i32
568  ret i32 %e
569}
570
571; CHECK-LABEL: cmpxchg_sext_i16_i32:
572; CHECK-NEXT: .param i32, i32, i32{{$}}
573; CHECK: i32.atomic.rmw16_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
574; CHECK-NEXT: i32.extend16_s $push1=, $pop0{{$}}
575; CHECK-NEXT: return $pop1{{$}}
576define i32 @cmpxchg_sext_i16_i32(i16* %p, i32 %exp, i32 %new) {
577  %exp_t = trunc i32 %exp to i16
578  %new_t = trunc i32 %new to i16
579  %pair = cmpxchg i16* %p, i16 %exp_t, i16 %new_t seq_cst seq_cst
580  %old = extractvalue { i16, i1 } %pair, 0
581  %e = sext i16 %old to i32
582  ret i32 %e
583}
584
585; CHECK-LABEL: cmpxchg_sext_i8_i64:
586; CHECK-NEXT: .param i32, i64, i64{{$}}
587; CHECK: i64.atomic.rmw8_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
588; CHECK-NEXT: i64.extend8_s $push1=, $pop0{{$}}
589; CHECK-NEXT: return $pop1{{$}}
590define i64 @cmpxchg_sext_i8_i64(i8* %p, i64 %exp, i64 %new) {
591  %exp_t = trunc i64 %exp to i8
592  %new_t = trunc i64 %new to i8
593  %pair = cmpxchg i8* %p, i8 %exp_t, i8 %new_t seq_cst seq_cst
594  %old = extractvalue { i8, i1 } %pair, 0
595  %e = sext i8 %old to i64
596  ret i64 %e
597}
598
599; CHECK-LABEL: cmpxchg_sext_i16_i64:
600; CHECK-NEXT: .param i32, i64, i64{{$}}
601; CHECK: i64.atomic.rmw16_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
602; CHECK-NEXT: i64.extend16_s $push1=, $pop0{{$}}
603; CHECK-NEXT: return $pop1{{$}}
604define i64 @cmpxchg_sext_i16_i64(i16* %p, i64 %exp, i64 %new) {
605  %exp_t = trunc i64 %exp to i16
606  %new_t = trunc i64 %new to i16
607  %pair = cmpxchg i16* %p, i16 %exp_t, i16 %new_t seq_cst seq_cst
608  %old = extractvalue { i16, i1 } %pair, 0
609  %e = sext i16 %old to i64
610  ret i64 %e
611}
612
613; 32->64 sext rmw gets selected as i32.atomic.rmw.cmpxchg, i64_extend_s/i32
614; CHECK-LABEL: cmpxchg_sext_i32_i64:
615; CHECK-NEXT: .param i32, i64, i64{{$}}
616; CHECK: i32.wrap/i64 $push1=, $1{{$}}
617; CHECK-NEXT: i32.wrap/i64 $push0=, $2{{$}}
618; CHECK-NEXT: i32.atomic.rmw.cmpxchg $push2=, 0($0), $pop1, $pop0{{$}}
619; CHECK-NEXT: i64.extend_s/i32 $push3=, $pop2{{$}}
620; CHECK-NEXT: return $pop3{{$}}
621define i64 @cmpxchg_sext_i32_i64(i32* %p, i64 %exp, i64 %new) {
622  %exp_t = trunc i64 %exp to i32
623  %new_t = trunc i64 %new to i32
624  %pair = cmpxchg i32* %p, i32 %exp_t, i32 %new_t seq_cst seq_cst
625  %old = extractvalue { i32, i1 } %pair, 0
626  %e = sext i32 %old to i64
627  ret i64 %e
628}
629
630;===----------------------------------------------------------------------------
631; Atomic truncating & zero-extending RMWs
632;===----------------------------------------------------------------------------
633
634; add
635
636; CHECK-LABEL: add_zext_i8_i32:
637; CHECK-NEXT: .param i32, i32{{$}}
638; CHECK: i32.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
639; CHECK-NEXT: return $pop0{{$}}
640define i32 @add_zext_i8_i32(i8* %p, i32 %v) {
641  %t = trunc i32 %v to i8
642  %old = atomicrmw add i8* %p, i8 %t seq_cst
643  %e = zext i8 %old to i32
644  ret i32 %e
645}
646
647; CHECK-LABEL: add_zext_i16_i32:
648; CHECK-NEXT: .param i32, i32{{$}}
649; CHECK: i32.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
650; CHECK-NEXT: return $pop0{{$}}
651define i32 @add_zext_i16_i32(i16* %p, i32 %v) {
652  %t = trunc i32 %v to i16
653  %old = atomicrmw add i16* %p, i16 %t seq_cst
654  %e = zext i16 %old to i32
655  ret i32 %e
656}
657
658; CHECK-LABEL: add_zext_i8_i64:
659; CHECK-NEXT: .param i32, i64{{$}}
660; CHECK: i64.atomic.rmw8_u.add $push0=, 0($0), $1{{$}}
661; CHECK-NEXT: return $pop0{{$}}
662define i64 @add_zext_i8_i64(i8* %p, i64 %v) {
663  %t = trunc i64 %v to i8
664  %old = atomicrmw add i8* %p, i8 %t seq_cst
665  %e = zext i8 %old to i64
666  ret i64 %e
667}
668
669; CHECK-LABEL: add_zext_i16_i64:
670; CHECK-NEXT: .param i32, i64{{$}}
671; CHECK: i64.atomic.rmw16_u.add $push0=, 0($0), $1{{$}}
672; CHECK-NEXT: return $pop0{{$}}
673define i64 @add_zext_i16_i64(i16* %p, i64 %v) {
674  %t = trunc i64 %v to i16
675  %old = atomicrmw add i16* %p, i16 %t seq_cst
676  %e = zext i16 %old to i64
677  ret i64 %e
678}
679
680; CHECK-LABEL: add_zext_i32_i64:
681; CHECK-NEXT: .param i32, i64{{$}}
682; CHECK: i64.atomic.rmw32_u.add $push0=, 0($0), $1{{$}}
683; CHECK-NEXT: return $pop0{{$}}
684define i64 @add_zext_i32_i64(i32* %p, i64 %v) {
685  %t = trunc i64 %v to i32
686  %old = atomicrmw add i32* %p, i32 %t seq_cst
687  %e = zext i32 %old to i64
688  ret i64 %e
689}
690
691; sub
692
693; CHECK-LABEL: sub_zext_i8_i32:
694; CHECK-NEXT: .param i32, i32{{$}}
695; CHECK: i32.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
696; CHECK-NEXT: return $pop0{{$}}
697define i32 @sub_zext_i8_i32(i8* %p, i32 %v) {
698  %t = trunc i32 %v to i8
699  %old = atomicrmw sub i8* %p, i8 %t seq_cst
700  %e = zext i8 %old to i32
701  ret i32 %e
702}
703
704; CHECK-LABEL: sub_zext_i16_i32:
705; CHECK-NEXT: .param i32, i32{{$}}
706; CHECK: i32.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
707; CHECK-NEXT: return $pop0{{$}}
708define i32 @sub_zext_i16_i32(i16* %p, i32 %v) {
709  %t = trunc i32 %v to i16
710  %old = atomicrmw sub i16* %p, i16 %t seq_cst
711  %e = zext i16 %old to i32
712  ret i32 %e
713}
714
715; CHECK-LABEL: sub_zext_i8_i64:
716; CHECK-NEXT: .param i32, i64{{$}}
717; CHECK: i64.atomic.rmw8_u.sub $push0=, 0($0), $1{{$}}
718; CHECK-NEXT: return $pop0{{$}}
719define i64 @sub_zext_i8_i64(i8* %p, i64 %v) {
720  %t = trunc i64 %v to i8
721  %old = atomicrmw sub i8* %p, i8 %t seq_cst
722  %e = zext i8 %old to i64
723  ret i64 %e
724}
725
726; CHECK-LABEL: sub_zext_i16_i64:
727; CHECK-NEXT: .param i32, i64{{$}}
728; CHECK: i64.atomic.rmw16_u.sub $push0=, 0($0), $1{{$}}
729; CHECK-NEXT: return $pop0{{$}}
730define i64 @sub_zext_i16_i64(i16* %p, i64 %v) {
731  %t = trunc i64 %v to i16
732  %old = atomicrmw sub i16* %p, i16 %t seq_cst
733  %e = zext i16 %old to i64
734  ret i64 %e
735}
736
737; CHECK-LABEL: sub_zext_i32_i64:
738; CHECK-NEXT: .param i32, i64{{$}}
739; CHECK: i64.atomic.rmw32_u.sub $push0=, 0($0), $1{{$}}
740; CHECK-NEXT: return $pop0{{$}}
741define i64 @sub_zext_i32_i64(i32* %p, i64 %v) {
742  %t = trunc i64 %v to i32
743  %old = atomicrmw sub i32* %p, i32 %t seq_cst
744  %e = zext i32 %old to i64
745  ret i64 %e
746}
747
748; and
749
750; CHECK-LABEL: and_zext_i8_i32:
751; CHECK-NEXT: .param i32, i32{{$}}
752; CHECK: i32.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
753; CHECK-NEXT: return $pop0{{$}}
754define i32 @and_zext_i8_i32(i8* %p, i32 %v) {
755  %t = trunc i32 %v to i8
756  %old = atomicrmw and i8* %p, i8 %t seq_cst
757  %e = zext i8 %old to i32
758  ret i32 %e
759}
760
761; CHECK-LABEL: and_zext_i16_i32:
762; CHECK-NEXT: .param i32, i32{{$}}
763; CHECK: i32.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
764; CHECK-NEXT: return $pop0{{$}}
765define i32 @and_zext_i16_i32(i16* %p, i32 %v) {
766  %t = trunc i32 %v to i16
767  %old = atomicrmw and i16* %p, i16 %t seq_cst
768  %e = zext i16 %old to i32
769  ret i32 %e
770}
771
772; CHECK-LABEL: and_zext_i8_i64:
773; CHECK-NEXT: .param i32, i64{{$}}
774; CHECK: i64.atomic.rmw8_u.and $push0=, 0($0), $1{{$}}
775; CHECK-NEXT: return $pop0{{$}}
776define i64 @and_zext_i8_i64(i8* %p, i64 %v) {
777  %t = trunc i64 %v to i8
778  %old = atomicrmw and i8* %p, i8 %t seq_cst
779  %e = zext i8 %old to i64
780  ret i64 %e
781}
782
783; CHECK-LABEL: and_zext_i16_i64:
784; CHECK-NEXT: .param i32, i64{{$}}
785; CHECK: i64.atomic.rmw16_u.and $push0=, 0($0), $1{{$}}
786; CHECK-NEXT: return $pop0{{$}}
787define i64 @and_zext_i16_i64(i16* %p, i64 %v) {
788  %t = trunc i64 %v to i16
789  %old = atomicrmw and i16* %p, i16 %t seq_cst
790  %e = zext i16 %old to i64
791  ret i64 %e
792}
793
794; CHECK-LABEL: and_zext_i32_i64:
795; CHECK-NEXT: .param i32, i64{{$}}
796; CHECK: i64.atomic.rmw32_u.and $push0=, 0($0), $1{{$}}
797; CHECK-NEXT: return $pop0{{$}}
798define i64 @and_zext_i32_i64(i32* %p, i64 %v) {
799  %t = trunc i64 %v to i32
800  %old = atomicrmw and i32* %p, i32 %t seq_cst
801  %e = zext i32 %old to i64
802  ret i64 %e
803}
804
805; or
806
807; CHECK-LABEL: or_zext_i8_i32:
808; CHECK-NEXT: .param i32, i32{{$}}
809; CHECK: i32.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
810; CHECK-NEXT: return $pop0{{$}}
811define i32 @or_zext_i8_i32(i8* %p, i32 %v) {
812  %t = trunc i32 %v to i8
813  %old = atomicrmw or i8* %p, i8 %t seq_cst
814  %e = zext i8 %old to i32
815  ret i32 %e
816}
817
818; CHECK-LABEL: or_zext_i16_i32:
819; CHECK-NEXT: .param i32, i32{{$}}
820; CHECK: i32.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
821; CHECK-NEXT: return $pop0{{$}}
822define i32 @or_zext_i16_i32(i16* %p, i32 %v) {
823  %t = trunc i32 %v to i16
824  %old = atomicrmw or i16* %p, i16 %t seq_cst
825  %e = zext i16 %old to i32
826  ret i32 %e
827}
828
829; CHECK-LABEL: or_zext_i8_i64:
830; CHECK-NEXT: .param i32, i64{{$}}
831; CHECK: i64.atomic.rmw8_u.or $push0=, 0($0), $1{{$}}
832; CHECK-NEXT: return $pop0{{$}}
833define i64 @or_zext_i8_i64(i8* %p, i64 %v) {
834  %t = trunc i64 %v to i8
835  %old = atomicrmw or i8* %p, i8 %t seq_cst
836  %e = zext i8 %old to i64
837  ret i64 %e
838}
839
840; CHECK-LABEL: or_zext_i16_i64:
841; CHECK-NEXT: .param i32, i64{{$}}
842; CHECK: i64.atomic.rmw16_u.or $push0=, 0($0), $1{{$}}
843; CHECK-NEXT: return $pop0{{$}}
844define i64 @or_zext_i16_i64(i16* %p, i64 %v) {
845  %t = trunc i64 %v to i16
846  %old = atomicrmw or i16* %p, i16 %t seq_cst
847  %e = zext i16 %old to i64
848  ret i64 %e
849}
850
851; CHECK-LABEL: or_zext_i32_i64:
852; CHECK-NEXT: .param i32, i64{{$}}
853; CHECK: i64.atomic.rmw32_u.or $push0=, 0($0), $1{{$}}
854; CHECK-NEXT: return $pop0{{$}}
855define i64 @or_zext_i32_i64(i32* %p, i64 %v) {
856  %t = trunc i64 %v to i32
857  %old = atomicrmw or i32* %p, i32 %t seq_cst
858  %e = zext i32 %old to i64
859  ret i64 %e
860}
861
862; xor
863
864; CHECK-LABEL: xor_zext_i8_i32:
865; CHECK-NEXT: .param i32, i32{{$}}
866; CHECK: i32.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
867; CHECK-NEXT: return $pop0{{$}}
868define i32 @xor_zext_i8_i32(i8* %p, i32 %v) {
869  %t = trunc i32 %v to i8
870  %old = atomicrmw xor i8* %p, i8 %t seq_cst
871  %e = zext i8 %old to i32
872  ret i32 %e
873}
874
875; CHECK-LABEL: xor_zext_i16_i32:
876; CHECK-NEXT: .param i32, i32{{$}}
877; CHECK: i32.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
878; CHECK-NEXT: return $pop0{{$}}
879define i32 @xor_zext_i16_i32(i16* %p, i32 %v) {
880  %t = trunc i32 %v to i16
881  %old = atomicrmw xor i16* %p, i16 %t seq_cst
882  %e = zext i16 %old to i32
883  ret i32 %e
884}
885
886; CHECK-LABEL: xor_zext_i8_i64:
887; CHECK-NEXT: .param i32, i64{{$}}
888; CHECK: i64.atomic.rmw8_u.xor $push0=, 0($0), $1{{$}}
889; CHECK-NEXT: return $pop0{{$}}
890define i64 @xor_zext_i8_i64(i8* %p, i64 %v) {
891  %t = trunc i64 %v to i8
892  %old = atomicrmw xor i8* %p, i8 %t seq_cst
893  %e = zext i8 %old to i64
894  ret i64 %e
895}
896
897; CHECK-LABEL: xor_zext_i16_i64:
898; CHECK-NEXT: .param i32, i64{{$}}
899; CHECK: i64.atomic.rmw16_u.xor $push0=, 0($0), $1{{$}}
900; CHECK-NEXT: return $pop0{{$}}
901define i64 @xor_zext_i16_i64(i16* %p, i64 %v) {
902  %t = trunc i64 %v to i16
903  %old = atomicrmw xor i16* %p, i16 %t seq_cst
904  %e = zext i16 %old to i64
905  ret i64 %e
906}
907
908; CHECK-LABEL: xor_zext_i32_i64:
909; CHECK-NEXT: .param i32, i64{{$}}
910; CHECK: i64.atomic.rmw32_u.xor $push0=, 0($0), $1{{$}}
911; CHECK-NEXT: return $pop0{{$}}
912define i64 @xor_zext_i32_i64(i32* %p, i64 %v) {
913  %t = trunc i64 %v to i32
914  %old = atomicrmw xor i32* %p, i32 %t seq_cst
915  %e = zext i32 %old to i64
916  ret i64 %e
917}
918
919; xchg
920
921; CHECK-LABEL: xchg_zext_i8_i32:
922; CHECK-NEXT: .param i32, i32{{$}}
923; CHECK: i32.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
924; CHECK-NEXT: return $pop0{{$}}
925define i32 @xchg_zext_i8_i32(i8* %p, i32 %v) {
926  %t = trunc i32 %v to i8
927  %old = atomicrmw xchg i8* %p, i8 %t seq_cst
928  %e = zext i8 %old to i32
929  ret i32 %e
930}
931
932; CHECK-LABEL: xchg_zext_i16_i32:
933; CHECK-NEXT: .param i32, i32{{$}}
934; CHECK: i32.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
935; CHECK-NEXT: return $pop0{{$}}
936define i32 @xchg_zext_i16_i32(i16* %p, i32 %v) {
937  %t = trunc i32 %v to i16
938  %old = atomicrmw xchg i16* %p, i16 %t seq_cst
939  %e = zext i16 %old to i32
940  ret i32 %e
941}
942
943; CHECK-LABEL: xchg_zext_i8_i64:
944; CHECK-NEXT: .param i32, i64{{$}}
945; CHECK: i64.atomic.rmw8_u.xchg $push0=, 0($0), $1{{$}}
946; CHECK-NEXT: return $pop0{{$}}
947define i64 @xchg_zext_i8_i64(i8* %p, i64 %v) {
948  %t = trunc i64 %v to i8
949  %old = atomicrmw xchg i8* %p, i8 %t seq_cst
950  %e = zext i8 %old to i64
951  ret i64 %e
952}
953
954; CHECK-LABEL: xchg_zext_i16_i64:
955; CHECK-NEXT: .param i32, i64{{$}}
956; CHECK: i64.atomic.rmw16_u.xchg $push0=, 0($0), $1{{$}}
957; CHECK-NEXT: return $pop0{{$}}
958define i64 @xchg_zext_i16_i64(i16* %p, i64 %v) {
959  %t = trunc i64 %v to i16
960  %old = atomicrmw xchg i16* %p, i16 %t seq_cst
961  %e = zext i16 %old to i64
962  ret i64 %e
963}
964
965; CHECK-LABEL: xchg_zext_i32_i64:
966; CHECK-NEXT: .param i32, i64{{$}}
967; CHECK: i64.atomic.rmw32_u.xchg $push0=, 0($0), $1{{$}}
968; CHECK-NEXT: return $pop0{{$}}
969define i64 @xchg_zext_i32_i64(i32* %p, i64 %v) {
970  %t = trunc i64 %v to i32
971  %old = atomicrmw xchg i32* %p, i32 %t seq_cst
972  %e = zext i32 %old to i64
973  ret i64 %e
974}
975
976; cmpxchg
977
978; CHECK-LABEL: cmpxchg_zext_i8_i32:
979; CHECK-NEXT: .param i32, i32, i32{{$}}
980; CHECK: i32.atomic.rmw8_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
981; CHECK-NEXT: return $pop0{{$}}
982define i32 @cmpxchg_zext_i8_i32(i8* %p, i32 %exp, i32 %new) {
983  %exp_t = trunc i32 %exp to i8
984  %new_t = trunc i32 %new to i8
985  %pair = cmpxchg i8* %p, i8 %exp_t, i8 %new_t seq_cst seq_cst
986  %old = extractvalue { i8, i1 } %pair, 0
987  %e = zext i8 %old to i32
988  ret i32 %e
989}
990
991; CHECK-LABEL: cmpxchg_zext_i16_i32:
992; CHECK-NEXT: .param i32, i32, i32{{$}}
993; CHECK: i32.atomic.rmw16_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
994; CHECK-NEXT: return $pop0{{$}}
995define i32 @cmpxchg_zext_i16_i32(i16* %p, i32 %exp, i32 %new) {
996  %exp_t = trunc i32 %exp to i16
997  %new_t = trunc i32 %new to i16
998  %pair = cmpxchg i16* %p, i16 %exp_t, i16 %new_t seq_cst seq_cst
999  %old = extractvalue { i16, i1 } %pair, 0
1000  %e = zext i16 %old to i32
1001  ret i32 %e
1002}
1003
1004; CHECK-LABEL: cmpxchg_zext_i8_i64:
1005; CHECK-NEXT: .param i32, i64, i64{{$}}
1006; CHECK: i64.atomic.rmw8_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
1007; CHECK-NEXT: return $pop0{{$}}
1008define i64 @cmpxchg_zext_i8_i64(i8* %p, i64 %exp, i64 %new) {
1009  %exp_t = trunc i64 %exp to i8
1010  %new_t = trunc i64 %new to i8
1011  %pair = cmpxchg i8* %p, i8 %exp_t, i8 %new_t seq_cst seq_cst
1012  %old = extractvalue { i8, i1 } %pair, 0
1013  %e = zext i8 %old to i64
1014  ret i64 %e
1015}
1016
1017; CHECK-LABEL: cmpxchg_zext_i16_i64:
1018; CHECK-NEXT: .param i32, i64, i64{{$}}
1019; CHECK: i64.atomic.rmw16_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
1020; CHECK-NEXT: return $pop0{{$}}
1021define i64 @cmpxchg_zext_i16_i64(i16* %p, i64 %exp, i64 %new) {
1022  %exp_t = trunc i64 %exp to i16
1023  %new_t = trunc i64 %new to i16
1024  %pair = cmpxchg i16* %p, i16 %exp_t, i16 %new_t seq_cst seq_cst
1025  %old = extractvalue { i16, i1 } %pair, 0
1026  %e = zext i16 %old to i64
1027  ret i64 %e
1028}
1029
1030; CHECK-LABEL: cmpxchg_zext_i32_i64:
1031; CHECK-NEXT: .param i32, i64, i64{{$}}
1032; CHECK: i64.atomic.rmw32_u.cmpxchg $push0=, 0($0), $1, $2{{$}}
1033; CHECK-NEXT: return $pop0{{$}}
1034define i64 @cmpxchg_zext_i32_i64(i32* %p, i64 %exp, i64 %new) {
1035  %exp_t = trunc i64 %exp to i32
1036  %new_t = trunc i64 %new to i32
1037  %pair = cmpxchg i32* %p, i32 %exp_t, i32 %new_t seq_cst seq_cst
1038  %old = extractvalue { i32, i1 } %pair, 0
1039  %e = zext i32 %old to i64
1040  ret i64 %e
1041}
1042