blob: 356982c3ae91a6da73d56daad1b99dcbe56673df [file] [log] [blame]
Heejin Ahn8daef072018-07-24 21:06:44 +00001; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt
Wouter van Oortmerssena7be3752018-08-13 23:12:49 +00002; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s
Heejin Ahn8daef072018-07-24 21:06:44 +00003
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}
Heejin Ahnb3724b72018-08-01 19:40:28 +0000142
143; Ternary RMW instruction: cmpxchg
144; The success and failure ordering arguments specify how this cmpxchg
145; synchronizes with other atomic operations. Both ordering parameters must be at
146; least monotonic, the ordering constraint on failure must be no stronger than
147; that on success, and the failure ordering cannot be either release or acq_rel.
148
149; CHECK-LABEL: cmpxchg_i32_monotonic_monotonic:
150; CHECK-NEXT: .param i32, i32, i32{{$}}
151; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
152; CHECK-NEXT: return $pop0{{$}}
153define i32 @cmpxchg_i32_monotonic_monotonic(i32* %p, i32 %exp, i32 %new) {
154 %pair = cmpxchg i32* %p, i32 %exp, i32 %new monotonic monotonic
155 %old = extractvalue { i32, i1 } %pair, 0
156 ret i32 %old
157}
158
159; CHECK-LABEL: cmpxchg_i32_acquire_monotonic:
160; CHECK-NEXT: .param i32, i32, i32{{$}}
161; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
162; CHECK-NEXT: return $pop0{{$}}
163define i32 @cmpxchg_i32_acquire_monotonic(i32* %p, i32 %exp, i32 %new) {
164 %pair = cmpxchg i32* %p, i32 %exp, i32 %new acquire monotonic
165 %old = extractvalue { i32, i1 } %pair, 0
166 ret i32 %old
167}
168
169; CHECK-LABEL: cmpxchg_i32_release_monotonic:
170; CHECK-NEXT: .param i32, i32, i32{{$}}
171; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
172; CHECK-NEXT: return $pop0{{$}}
173define i32 @cmpxchg_i32_release_monotonic(i32* %p, i32 %exp, i32 %new) {
174 %pair = cmpxchg i32* %p, i32 %exp, i32 %new release monotonic
175 %old = extractvalue { i32, i1 } %pair, 0
176 ret i32 %old
177}
178
179; CHECK-LABEL: cmpxchg_i32_acq_rel_monotonic:
180; CHECK-NEXT: .param i32, i32, i32{{$}}
181; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
182; CHECK-NEXT: return $pop0{{$}}
183define i32 @cmpxchg_i32_acq_rel_monotonic(i32* %p, i32 %exp, i32 %new) {
184 %pair = cmpxchg i32* %p, i32 %exp, i32 %new acq_rel monotonic
185 %old = extractvalue { i32, i1 } %pair, 0
186 ret i32 %old
187}
188
189; CHECK-LABEL: cmpxchg_i32_seq_cst_monotonic:
190; CHECK-NEXT: .param i32, i32, i32{{$}}
191; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
192; CHECK-NEXT: return $pop0{{$}}
193define i32 @cmpxchg_i32_seq_cst_monotonic(i32* %p, i32 %exp, i32 %new) {
194 %pair = cmpxchg i32* %p, i32 %exp, i32 %new seq_cst monotonic
195 %old = extractvalue { i32, i1 } %pair, 0
196 ret i32 %old
197}
198
199; CHECK-LABEL: cmpxchg_i32_acquire_acquire:
200; CHECK-NEXT: .param i32, i32, i32{{$}}
201; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
202; CHECK-NEXT: return $pop0{{$}}
203define i32 @cmpxchg_i32_acquire_acquire(i32* %p, i32 %exp, i32 %new) {
204 %pair = cmpxchg i32* %p, i32 %exp, i32 %new acquire acquire
205 %old = extractvalue { i32, i1 } %pair, 0
206 ret i32 %old
207}
208
209; CHECK-LABEL: cmpxchg_i32_release_acquire:
210; CHECK-NEXT: .param i32, i32, i32{{$}}
211; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
212; CHECK-NEXT: return $pop0{{$}}
213define i32 @cmpxchg_i32_release_acquire(i32* %p, i32 %exp, i32 %new) {
214 %pair = cmpxchg i32* %p, i32 %exp, i32 %new release acquire
215 %old = extractvalue { i32, i1 } %pair, 0
216 ret i32 %old
217}
218
219; CHECK-LABEL: cmpxchg_i32_acq_rel_acquire:
220; CHECK-NEXT: .param i32, i32, i32{{$}}
221; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
222; CHECK-NEXT: return $pop0{{$}}
223define i32 @cmpxchg_i32_acq_rel_acquire(i32* %p, i32 %exp, i32 %new) {
224 %pair = cmpxchg i32* %p, i32 %exp, i32 %new acq_rel acquire
225 %old = extractvalue { i32, i1 } %pair, 0
226 ret i32 %old
227}
228
229; CHECK-LABEL: cmpxchg_i32_seq_cst_acquire:
230; CHECK-NEXT: .param i32, i32, i32{{$}}
231; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
232; CHECK-NEXT: return $pop0{{$}}
233define i32 @cmpxchg_i32_seq_cst_acquire(i32* %p, i32 %exp, i32 %new) {
234 %pair = cmpxchg i32* %p, i32 %exp, i32 %new seq_cst acquire
235 %old = extractvalue { i32, i1 } %pair, 0
236 ret i32 %old
237}
238
239; CHECK-LABEL: cmpxchg_i32_seq_cst_seq_cst:
240; CHECK-NEXT: .param i32, i32, i32{{$}}
241; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
242; CHECK-NEXT: return $pop0{{$}}
243define i32 @cmpxchg_i32_seq_cst_seq_cst(i32* %p, i32 %exp, i32 %new) {
244 %pair = cmpxchg i32* %p, i32 %exp, i32 %new seq_cst seq_cst
245 %old = extractvalue { i32, i1 } %pair, 0
246 ret i32 %old
247}