1; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
2; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-THUMB
3
4define i64 @test1(i64* %ptr, i64 %val) {
5; CHECK-LABEL: test1:
6; CHECK: dmb {{ish$}}
7; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
8; CHECK: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
9; CHECK: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
10; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
11; CHECK: cmp
12; CHECK: bne
13; CHECK: dmb {{ish$}}
14
15; CHECK-THUMB-LABEL: test1:
16; CHECK-THUMB: dmb {{ish$}}
17; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
18; CHECK-THUMB: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
19; CHECK-THUMB: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
20; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
21; CHECK-THUMB: cmp
22; CHECK-THUMB: bne
23; CHECK-THUMB: dmb {{ish$}}
24
25  %r = atomicrmw add i64* %ptr, i64 %val seq_cst
26  ret i64 %r
27}
28
29define i64 @test2(i64* %ptr, i64 %val) {
30; CHECK-LABEL: test2:
31; CHECK: dmb {{ish$}}
32; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
33; CHECK: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
34; CHECK: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
35; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
36; CHECK: cmp
37; CHECK: bne
38; CHECK: dmb {{ish$}}
39
40; CHECK-THUMB-LABEL: test2:
41; CHECK-THUMB: dmb {{ish$}}
42; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
43; CHECK-THUMB: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
44; CHECK-THUMB: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
45; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
46; CHECK-THUMB: cmp
47; CHECK-THUMB: bne
48; CHECK-THUMB: dmb {{ish$}}
49
50  %r = atomicrmw sub i64* %ptr, i64 %val seq_cst
51  ret i64 %r
52}
53
54define i64 @test3(i64* %ptr, i64 %val) {
55; CHECK-LABEL: test3:
56; CHECK: dmb {{ish$}}
57; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
58; CHECK: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
59; CHECK: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
60; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
61; CHECK: cmp
62; CHECK: bne
63; CHECK: dmb {{ish$}}
64
65; CHECK-THUMB-LABEL: test3:
66; CHECK-THUMB: dmb {{ish$}}
67; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
68; CHECK-THUMB: and.w [[REG3:[a-z0-9]+]], [[REG1]]
69; CHECK-THUMB: and.w [[REG4:[a-z0-9]+]], [[REG2]]
70; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
71; CHECK-THUMB: cmp
72; CHECK-THUMB: bne
73; CHECK-THUMB: dmb {{ish$}}
74
75  %r = atomicrmw and i64* %ptr, i64 %val seq_cst
76  ret i64 %r
77}
78
79define i64 @test4(i64* %ptr, i64 %val) {
80; CHECK-LABEL: test4:
81; CHECK: dmb {{ish$}}
82; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
83; CHECK: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
84; CHECK: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
85; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
86; CHECK: cmp
87; CHECK: bne
88; CHECK: dmb {{ish$}}
89
90; CHECK-THUMB-LABEL: test4:
91; CHECK-THUMB: dmb {{ish$}}
92; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
93; CHECK-THUMB: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
94; CHECK-THUMB: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
95; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
96; CHECK-THUMB: cmp
97; CHECK-THUMB: bne
98; CHECK-THUMB: dmb {{ish$}}
99
100  %r = atomicrmw or i64* %ptr, i64 %val seq_cst
101  ret i64 %r
102}
103
104define i64 @test5(i64* %ptr, i64 %val) {
105; CHECK-LABEL: test5:
106; CHECK: dmb {{ish$}}
107; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
108; CHECK: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
109; CHECK: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
110; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
111; CHECK: cmp
112; CHECK: bne
113; CHECK: dmb {{ish$}}
114
115; CHECK-THUMB-LABEL: test5:
116; CHECK-THUMB: dmb {{ish$}}
117; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
118; CHECK-THUMB: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
119; CHECK-THUMB: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
120; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
121; CHECK-THUMB: cmp
122; CHECK-THUMB: bne
123; CHECK-THUMB: dmb {{ish$}}
124
125  %r = atomicrmw xor i64* %ptr, i64 %val seq_cst
126  ret i64 %r
127}
128
129define i64 @test6(i64* %ptr, i64 %val) {
130; CHECK-LABEL: test6:
131; CHECK: dmb {{ish$}}
132; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
133; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
134; CHECK: cmp
135; CHECK: bne
136; CHECK: dmb {{ish$}}
137
138; CHECK-THUMB-LABEL: test6:
139; CHECK-THUMB: dmb {{ish$}}
140; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
141; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
142; CHECK-THUMB: cmp
143; CHECK-THUMB: bne
144; CHECK-THUMB: dmb {{ish$}}
145
146  %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst
147  ret i64 %r
148}
149
150define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
151; CHECK-LABEL: test7:
152; CHECK: dmb {{ish$}}
153; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
154; CHECK: cmp [[REG1]]
155; CHECK: cmpeq [[REG2]]
156; CHECK: bne
157; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
158; CHECK: cmp
159; CHECK: bne
160; CHECK: dmb {{ish$}}
161
162; CHECK-THUMB-LABEL: test7:
163; CHECK-THUMB: dmb {{ish$}}
164; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
165; CHECK-THUMB: cmp [[REG1]]
166; CHECK-THUMB: it eq
167; CHECK-THUMB: cmpeq [[REG2]]
168; CHECK-THUMB: bne
169; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
170; CHECK-THUMB: cmp
171; CHECK-THUMB: bne
172; CHECK-THUMB: dmb {{ish$}}
173
174  %r = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst
175  ret i64 %r
176}
177
178; Compiles down to a single ldrexd
179define i64 @test8(i64* %ptr) {
180; CHECK-LABEL: test8:
181; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
182; CHECK: dmb {{ish$}}
183
184; CHECK-THUMB-LABEL: test8:
185; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
186; CHECK-THUMB: dmb {{ish$}}
187
188  %r = load atomic i64* %ptr seq_cst, align 8
189  ret i64 %r
190}
191
192; Compiles down to atomicrmw xchg; there really isn't any more efficient
193; way to write it.
194define void @test9(i64* %ptr, i64 %val) {
195; CHECK-LABEL: test9:
196; CHECK: dmb {{ish$}}
197; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
198; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
199; CHECK: cmp
200; CHECK: bne
201; CHECK: dmb {{ish$}}
202
203; CHECK-THUMB-LABEL: test9:
204; CHECK-THUMB: dmb {{ish$}}
205; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
206; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
207; CHECK-THUMB: cmp
208; CHECK-THUMB: bne
209; CHECK-THUMB: dmb {{ish$}}
210
211  store atomic i64 %val, i64* %ptr seq_cst, align 8
212  ret void
213}
214
215define i64 @test10(i64* %ptr, i64 %val) {
216; CHECK-LABEL: test10:
217; CHECK: dmb {{ish$}}
218; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
219; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
220; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
221; CHECK: blt
222; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
223; CHECK: cmp
224; CHECK: bne
225; CHECK: dmb {{ish$}}
226
227; CHECK-THUMB-LABEL: test10:
228; CHECK-THUMB: dmb {{ish$}}
229; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
230; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
231; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
232; CHECK-THUMB: blt
233; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
234; CHECK-THUMB: cmp
235; CHECK-THUMB: bne
236; CHECK-THUMB: dmb {{ish$}}
237
238  %r = atomicrmw min i64* %ptr, i64 %val seq_cst
239  ret i64 %r
240}
241
242define i64 @test11(i64* %ptr, i64 %val) {
243; CHECK-LABEL: test11:
244; CHECK: dmb {{ish$}}
245; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
246; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
247; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
248; CHECK: blo
249; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
250; CHECK: cmp
251; CHECK: bne
252; CHECK: dmb {{ish$}}
253
254
255; CHECK-THUMB-LABEL: test11:
256; CHECK-THUMB: dmb {{ish$}}
257; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
258; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
259; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
260; CHECK-THUMB: blo
261; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
262; CHECK-THUMB: cmp
263; CHECK-THUMB: bne
264; CHECK-THUMB: dmb {{ish$}}
265
266  %r = atomicrmw umin i64* %ptr, i64 %val seq_cst
267  ret i64 %r
268}
269
270define i64 @test12(i64* %ptr, i64 %val) {
271; CHECK-LABEL: test12:
272; CHECK: dmb {{ish$}}
273; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
274; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
275; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
276; CHECK: bge
277; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
278; CHECK: cmp
279; CHECK: bne
280; CHECK: dmb {{ish$}}
281
282; CHECK-THUMB-LABEL: test12:
283; CHECK-THUMB: dmb {{ish$}}
284; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
285; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
286; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
287; CHECK-THUMB: bge
288; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
289; CHECK-THUMB: cmp
290; CHECK-THUMB: bne
291; CHECK-THUMB: dmb {{ish$}}
292
293  %r = atomicrmw max i64* %ptr, i64 %val seq_cst
294  ret i64 %r
295}
296
297define i64 @test13(i64* %ptr, i64 %val) {
298; CHECK-LABEL: test13:
299; CHECK: dmb {{ish$}}
300; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
301; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
302; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
303; CHECK: bhs
304; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
305; CHECK: cmp
306; CHECK: bne
307; CHECK: dmb {{ish$}}
308
309; CHECK-THUMB-LABEL: test13:
310; CHECK-THUMB: dmb {{ish$}}
311; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
312; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
313; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
314; CHECK-THUMB: bhs
315; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
316; CHECK-THUMB: cmp
317; CHECK-THUMB: bne
318; CHECK-THUMB: dmb {{ish$}}
319  %r = atomicrmw umax i64* %ptr, i64 %val seq_cst
320  ret i64 %r
321}
322
323