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; Currently all wasm atomic memory access instructions are sequentially
5; consistent, so even if LLVM IR specifies weaker orderings than that, we
6; should upgrade them to sequential ordering and treat them in the same way.
7
8target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
9target triple = "wasm32-unknown-unknown"
10
11;===----------------------------------------------------------------------------
12; Atomic loads
13;===----------------------------------------------------------------------------
14
15; The 'release' and 'acq_rel' orderings are not valid on load instructions.
16
17; CHECK-LABEL: load_i32_unordered:
18; CHECK: i32.atomic.load $push0=, 0($0){{$}}
19; CHECK-NEXT: return $pop0{{$}}
20define i32 @load_i32_unordered(i32 *%p) {
21  %v = load atomic i32, i32* %p unordered, align 4
22  ret i32 %v
23}
24
25; CHECK-LABEL: load_i32_monotonic:
26; CHECK: i32.atomic.load $push0=, 0($0){{$}}
27; CHECK-NEXT: return $pop0{{$}}
28define i32 @load_i32_monotonic(i32 *%p) {
29  %v = load atomic i32, i32* %p monotonic, align 4
30  ret i32 %v
31}
32
33; CHECK-LABEL: load_i32_acquire:
34; CHECK: i32.atomic.load $push0=, 0($0){{$}}
35; CHECK-NEXT: return $pop0{{$}}
36define i32 @load_i32_acquire(i32 *%p) {
37  %v = load atomic i32, i32* %p acquire, align 4
38  ret i32 %v
39}
40
41; CHECK-LABEL: load_i32_seq_cst:
42; CHECK: i32.atomic.load $push0=, 0($0){{$}}
43; CHECK-NEXT: return $pop0{{$}}
44define i32 @load_i32_seq_cst(i32 *%p) {
45  %v = load atomic i32, i32* %p seq_cst, align 4
46  ret i32 %v
47}
48
49;===----------------------------------------------------------------------------
50; Atomic stores
51;===----------------------------------------------------------------------------
52
53; The 'acquire' and 'acq_rel' orderings aren’t valid on store instructions.
54
55; CHECK-LABEL: store_i32_unordered:
56; CHECK-NEXT: .param i32, i32{{$}}
57; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
58; CHECK-NEXT: return{{$}}
59define void @store_i32_unordered(i32 *%p, i32 %v) {
60  store atomic i32 %v, i32* %p unordered, align 4
61  ret void
62}
63
64; CHECK-LABEL: store_i32_monotonic:
65; CHECK-NEXT: .param i32, i32{{$}}
66; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
67; CHECK-NEXT: return{{$}}
68define void @store_i32_monotonic(i32 *%p, i32 %v) {
69  store atomic i32 %v, i32* %p monotonic, align 4
70  ret void
71}
72
73; CHECK-LABEL: store_i32_release:
74; CHECK-NEXT: .param i32, i32{{$}}
75; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
76; CHECK-NEXT: return{{$}}
77define void @store_i32_release(i32 *%p, i32 %v) {
78  store atomic i32 %v, i32* %p release, align 4
79  ret void
80}
81
82; CHECK-LABEL: store_i32_seq_cst:
83; CHECK-NEXT: .param i32, i32{{$}}
84; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}
85; CHECK-NEXT: return{{$}}
86define void @store_i32_seq_cst(i32 *%p, i32 %v) {
87  store atomic i32 %v, i32* %p seq_cst, align 4
88  ret void
89}
90
91;===----------------------------------------------------------------------------
92; Atomic read-modify-writes
93;===----------------------------------------------------------------------------
94
95; Out of several binary RMW instructions, here we test 'add' as an example.
96; The 'unordered' ordering is not valid on atomicrmw instructions.
97
98; CHECK-LABEL: add_i32_monotonic:
99; CHECK-NEXT: .param i32, i32{{$}}
100; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
101; CHECK-NEXT: return $pop0{{$}}
102define i32 @add_i32_monotonic(i32* %p, i32 %v) {
103  %old = atomicrmw add i32* %p, i32 %v monotonic
104  ret i32 %old
105}
106
107; CHECK-LABEL: add_i32_acquire:
108; CHECK-NEXT: .param i32, i32{{$}}
109; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
110; CHECK-NEXT: return $pop0{{$}}
111define i32 @add_i32_acquire(i32* %p, i32 %v) {
112  %old = atomicrmw add i32* %p, i32 %v acquire
113  ret i32 %old
114}
115
116; CHECK-LABEL: add_i32_release:
117; CHECK-NEXT: .param i32, i32{{$}}
118; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
119; CHECK-NEXT: return $pop0{{$}}
120define i32 @add_i32_release(i32* %p, i32 %v) {
121  %old = atomicrmw add i32* %p, i32 %v release
122  ret i32 %old
123}
124
125; CHECK-LABEL: add_i32_acq_rel:
126; CHECK-NEXT: .param i32, i32{{$}}
127; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
128; CHECK-NEXT: return $pop0{{$}}
129define i32 @add_i32_acq_rel(i32* %p, i32 %v) {
130  %old = atomicrmw add i32* %p, i32 %v acq_rel
131  ret i32 %old
132}
133
134; CHECK-LABEL: add_i32_seq_cst:
135; CHECK-NEXT: .param i32, i32{{$}}
136; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}
137; CHECK-NEXT: return $pop0{{$}}
138define i32 @add_i32_seq_cst(i32* %p, i32 %v) {
139  %old = atomicrmw add i32* %p, i32 %v seq_cst
140  ret i32 %old
141}
142