1; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
2; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
3; RUN: llc < %s -mtriple=armebv7 -target-abi apcs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
4; RUN: llc < %s -mtriple=thumbebv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
5; RUN: llc < %s -mtriple=armv7m--none-eabi | FileCheck %s --check-prefix=CHECK-M
6; RUN: llc < %s -mtriple=armv8m--none-eabi | FileCheck %s --check-prefix=CHECK-M
7
8define i64 @test1(i64* %ptr, i64 %val) {
9; CHECK-LABEL: test1:
10; CHECK: dmb {{ish$}}
11; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
12; CHECK-LE: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
13; CHECK-LE: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
14; CHECK-BE: adds [[REG4:(r[0-9]?[13579])]], [[REG2]]
15; CHECK-BE: adc [[REG3:(r[0-9]?[02468])]], [[REG1]]
16; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
17; CHECK: cmp
18; CHECK: bne
19; CHECK: dmb {{ish$}}
20
21; CHECK-THUMB-LABEL: test1:
22; CHECK-THUMB: dmb {{ish$}}
23; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
24; CHECK-THUMB-LE: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
25; CHECK-THUMB-LE: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
26; CHECK-THUMB-BE: adds.w [[REG4:[a-z0-9]+]], [[REG2]]
27; CHECK-THUMB-BE: adc.w [[REG3:[a-z0-9]+]], [[REG1]]
28; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
29; CHECK-THUMB: cmp
30; CHECK-THUMB: bne
31; CHECK-THUMB: dmb {{ish$}}
32
33; CHECK-M: __atomic_fetch_add_8
34
35  %r = atomicrmw add i64* %ptr, i64 %val seq_cst
36  ret i64 %r
37}
38
39define i64 @test2(i64* %ptr, i64 %val) {
40; CHECK-LABEL: test2:
41; CHECK: dmb {{ish$}}
42; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
43; CHECK-LE: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
44; CHECK-LE: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
45; CHECK-BE: subs [[REG4:(r[0-9]?[13579])]], [[REG2]]
46; CHECK-BE: sbc [[REG3:(r[0-9]?[02468])]], [[REG1]]
47; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
48; CHECK: cmp
49; CHECK: bne
50; CHECK: dmb {{ish$}}
51
52; CHECK-THUMB-LABEL: test2:
53; CHECK-THUMB: dmb {{ish$}}
54; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
55; CHECK-THUMB-LE: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
56; CHECK-THUMB-LE: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
57; CHECK-THUMB-BE: subs.w [[REG4:[a-z0-9]+]], [[REG2]]
58; CHECK-THUMB-BE: sbc.w [[REG3:[a-z0-9]+]], [[REG1]]
59; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
60; CHECK-THUMB: cmp
61; CHECK-THUMB: bne
62; CHECK-THUMB: dmb {{ish$}}
63
64; CHECK-M: __atomic_fetch_sub_8
65
66  %r = atomicrmw sub i64* %ptr, i64 %val seq_cst
67  ret i64 %r
68}
69
70define i64 @test3(i64* %ptr, i64 %val) {
71; CHECK-LABEL: test3:
72; CHECK: dmb {{ish$}}
73; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
74; CHECK-LE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
75; CHECK-LE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
76; CHECK-BE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
77; CHECK-BE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
78; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
79; CHECK: cmp
80; CHECK: bne
81; CHECK: dmb {{ish$}}
82
83; CHECK-THUMB-LABEL: test3:
84; CHECK-THUMB: dmb {{ish$}}
85; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
86; CHECK-THUMB-LE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]]
87; CHECK-THUMB-LE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]]
88; CHECK-THUMB-BE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]]
89; CHECK-THUMB-BE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]]
90; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
91; CHECK-THUMB: cmp
92; CHECK-THUMB: bne
93; CHECK-THUMB: dmb {{ish$}}
94
95; CHECK-M: _atomic_fetch_and_8
96
97  %r = atomicrmw and i64* %ptr, i64 %val seq_cst
98  ret i64 %r
99}
100
101define i64 @test4(i64* %ptr, i64 %val) {
102; CHECK-LABEL: test4:
103; CHECK: dmb {{ish$}}
104; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
105; CHECK-LE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
106; CHECK-LE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
107; CHECK-BE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
108; CHECK-BE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
109; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
110; CHECK: cmp
111; CHECK: bne
112; CHECK: dmb {{ish$}}
113
114; CHECK-THUMB-LABEL: test4:
115; CHECK-THUMB: dmb {{ish$}}
116; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
117; CHECK-THUMB-LE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
118; CHECK-THUMB-LE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
119; CHECK-THUMB-BE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
120; CHECK-THUMB-BE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
121; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
122; CHECK-THUMB: cmp
123; CHECK-THUMB: bne
124; CHECK-THUMB: dmb {{ish$}}
125
126; CHECK-M: __atomic_fetch_or_8
127
128  %r = atomicrmw or i64* %ptr, i64 %val seq_cst
129  ret i64 %r
130}
131
132define i64 @test5(i64* %ptr, i64 %val) {
133; CHECK-LABEL: test5:
134; CHECK: dmb {{ish$}}
135; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
136; CHECK-LE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
137; CHECK-LE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
138; CHECK-BE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
139; CHECK-BE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
140; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
141; CHECK: cmp
142; CHECK: bne
143; CHECK: dmb {{ish$}}
144
145; CHECK-THUMB-LABEL: test5:
146; CHECK-THUMB: dmb {{ish$}}
147; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
148; CHECK-THUMB-LE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
149; CHECK-THUMB-LE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
150; CHECK-THUMB-BE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
151; CHECK-THUMB-BE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
152; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
153; CHECK-THUMB: cmp
154; CHECK-THUMB: bne
155; CHECK-THUMB: dmb {{ish$}}
156
157; CHECK-M: __atomic_fetch_xor_8
158
159  %r = atomicrmw xor i64* %ptr, i64 %val seq_cst
160  ret i64 %r
161}
162
163define i64 @test6(i64* %ptr, i64 %val) {
164; CHECK-LABEL: test6:
165; CHECK: dmb {{ish$}}
166; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
167; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
168; CHECK: cmp
169; CHECK: bne
170; CHECK: dmb {{ish$}}
171
172; CHECK-THUMB-LABEL: test6:
173; CHECK-THUMB: dmb {{ish$}}
174; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
175; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
176; CHECK-THUMB: cmp
177; CHECK-THUMB: bne
178; CHECK-THUMB: dmb {{ish$}}
179
180; CHECK-M: __atomic_exchange_8
181
182  %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst
183  ret i64 %r
184}
185
186define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
187; CHECK-LABEL: test7:
188; CHECK-DAG: mov [[VAL1LO:r[0-9]+]], r1
189; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
190; CHECK-LE-DAG: eor     [[MISMATCH_LO:.*]], [[REG1]], [[VAL1LO]]
191; CHECK-LE-DAG: eor     [[MISMATCH_HI:.*]], [[REG2]], r2
192; CHECK-BE-DAG: eor     [[MISMATCH_LO:.*]], [[REG2]], r2
193; CHECK-BE-DAG: eor     [[MISMATCH_HI:.*]], [[REG1]], r1
194; CHECK: orrs    {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
195; CHECK: bne
196; CHECK-DAG: dmb {{ish$}}
197; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
198; CHECK: cmp
199; CHECK: beq
200; CHECK: dmb {{ish$}}
201
202; CHECK-THUMB-LABEL: test7:
203; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
204; CHECK-THUMB-LE-DAG: eor.w     [[MISMATCH_LO:[a-z0-9]+]], [[REG1]], r2
205; CHECK-THUMB-LE-DAG: eor.w     [[MISMATCH_HI:[a-z0-9]+]], [[REG2]], r3
206; CHECK-THUMB-BE-DAG: eor.w     [[MISMATCH_HI:[a-z0-9]+]], [[REG1]], r2
207; CHECK-THUMB-BE-DAG: eor.w     [[MISMATCH_LO:[a-z0-9]+]], [[REG2]], r3
208; CHECK-THUMB-LE: orrs.w    {{.*}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
209; CHECK-THUMB: bne
210; CHECK-THUMB: dmb {{ish$}}
211; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
212; CHECK-THUMB: cmp
213; CHECK-THUMB: beq
214; CHECK-THUMB: dmb {{ish$}}
215
216; CHECK-M: __atomic_compare_exchange_8
217
218  %pair = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst seq_cst
219  %r = extractvalue { i64, i1 } %pair, 0
220  ret i64 %r
221}
222
223; Compiles down to a single ldrexd, except on M class devices where ldrexd
224; isn't supported.
225define i64 @test8(i64* %ptr) {
226; CHECK-LABEL: test8:
227; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
228; CHECK-NOT: strexd
229; CHECK: clrex
230; CHECK-NOT: strexd
231; CHECK: dmb {{ish$}}
232
233; CHECK-THUMB-LABEL: test8:
234; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
235; CHECK-THUMB-NOT: strexd
236; CHECK-THUMB: clrex
237; CHECK-THUMB-NOT: strexd
238; CHECK-THUMB: dmb {{ish$}}
239
240; CHECK-M: __atomic_load_8
241
242  %r = load atomic i64, i64* %ptr seq_cst, align 8
243  ret i64 %r
244}
245
246; Compiles down to atomicrmw xchg; there really isn't any more efficient
247; way to write it. Except on M class devices, where ldrexd/strexd aren't
248; supported.
249define void @test9(i64* %ptr, i64 %val) {
250; CHECK-LABEL: test9:
251; CHECK: dmb {{ish$}}
252; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
253; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
254; CHECK: cmp
255; CHECK: bne
256; CHECK: dmb {{ish$}}
257
258; CHECK-THUMB-LABEL: test9:
259; CHECK-THUMB: dmb {{ish$}}
260; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
261; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
262; CHECK-THUMB: cmp
263; CHECK-THUMB: bne
264; CHECK-THUMB: dmb {{ish$}}
265
266; CHECK-M: __atomic_store_8
267
268  store atomic i64 %val, i64* %ptr seq_cst, align 8
269  ret void
270}
271
272define i64 @test10(i64* %ptr, i64 %val) {
273; CHECK-LABEL: test10:
274; CHECK: dmb {{ish$}}
275; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
276; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
277; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
278; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
279; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
280; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
281; CHECK: mov     [[CMP:[a-z0-9]+]], #0
282; CHECK: movwge  [[CMP]], #1
283; CHECK: cmp     [[CMP]], #0
284; CHECK: movne   [[OUT_HI]], [[REG2]]
285; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
286; CHECK: movne   [[OUT_LO]], [[REG1]]
287; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
288; CHECK: cmp
289; CHECK: bne
290; CHECK: dmb {{ish$}}
291
292; CHECK-THUMB-LABEL: test10:
293; CHECK-THUMB: dmb {{ish$}}
294; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
295; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
296; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
297; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
298; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
299; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
300; CHECK-THUMB: mov.w     [[CMP:[a-z0-9]+]], #0
301; CHECK-THUMB: movge.w   [[CMP]], #1
302; CHECK-THUMB: cmp.w     [[CMP]], #0
303; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
304; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
305; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
306; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
307; CHECK-THUMB: cmp
308; CHECK-THUMB: bne
309; CHECK-THUMB: dmb {{ish$}}
310
311; CHECK-M: __atomic_compare_exchange_8
312
313  %r = atomicrmw min i64* %ptr, i64 %val seq_cst
314  ret i64 %r
315}
316
317define i64 @test11(i64* %ptr, i64 %val) {
318; CHECK-LABEL: test11:
319; CHECK: dmb {{ish$}}
320; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
321; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
322; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
323; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
324; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
325; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
326; CHECK: mov     [[CMP:[a-z0-9]+]], #0
327; CHECK: movwhs  [[CMP]], #1
328; CHECK: cmp     [[CMP]], #0
329; CHECK: movne   [[OUT_HI]], [[REG2]]
330; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
331; CHECK: movne   [[OUT_LO]], [[REG1]]
332; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
333; CHECK: cmp
334; CHECK: bne
335; CHECK: dmb {{ish$}}
336
337; CHECK-THUMB-LABEL: test11:
338; CHECK-THUMB: dmb {{ish$}}
339; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
340; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
341; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
342; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
343; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
344; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
345; CHECK-THUMB: mov.w     [[CMP:[a-z0-9]+]], #0
346; CHECK-THUMB: movhs.w   [[CMP]], #1
347; CHECK-THUMB: cmp.w     [[CMP]], #0
348; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
349; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
350; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
351; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
352; CHECK-THUMB: cmp
353; CHECK-THUMB: bne
354; CHECK-THUMB: dmb {{ish$}}
355
356; CHECK-M: __atomic_compare_exchange_8
357
358  %r = atomicrmw umin i64* %ptr, i64 %val seq_cst
359  ret i64 %r
360}
361
362define i64 @test12(i64* %ptr, i64 %val) {
363; CHECK-LABEL: test12:
364; CHECK: dmb {{ish$}}
365; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
366; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
367; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
368; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
369; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
370; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
371; CHECK: mov     [[CMP:[a-z0-9]+]], #0
372; CHECK: movwlt  [[CMP]], #1
373; CHECK: cmp     [[CMP]], #0
374; CHECK: movne   [[OUT_HI]], [[REG2]]
375; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
376; CHECK: movne   [[OUT_LO]], [[REG1]]
377; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
378; CHECK: cmp
379; CHECK: bne
380; CHECK: dmb {{ish$}}
381
382; CHECK-THUMB-LABEL: test12:
383; CHECK-THUMB: dmb {{ish$}}
384; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
385; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
386; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
387; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
388; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
389; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
390; CHECK-THUMB: mov.w     [[CMP:[a-z0-9]+]], #0
391; CHECK-THUMB: movlt.w   [[CMP]], #1
392; CHECK-THUMB: cmp.w     [[CMP]], #0
393; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
394; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
395; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
396; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
397; CHECK-THUMB: cmp
398; CHECK-THUMB: bne
399; CHECK-THUMB: dmb {{ish$}}
400
401; CHECK-M: __atomic_compare_exchange_8
402
403  %r = atomicrmw max i64* %ptr, i64 %val seq_cst
404  ret i64 %r
405}
406
407define i64 @test13(i64* %ptr, i64 %val) {
408; CHECK-LABEL: test13:
409; CHECK: dmb {{ish$}}
410; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
411; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
412; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
413; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
414; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
415; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
416; CHECK: mov     [[CMP:[a-z0-9]+]], #0
417; CHECK: movwlo  [[CMP]], #1
418; CHECK: cmp     [[CMP]], #0
419; CHECK: movne   [[OUT_HI]], [[REG2]]
420; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
421; CHECK: movne   [[OUT_LO]], [[REG1]]
422; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
423; CHECK: cmp
424; CHECK: bne
425; CHECK: dmb {{ish$}}
426
427; CHECK-THUMB-LABEL: test13:
428; CHECK-THUMB: dmb {{ish$}}
429; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
430; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
431; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
432; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
433; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
434; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
435; CHECK-THUMB: mov.w     [[CMP:[a-z0-9]+]], #0
436; CHECK-THUMB: movlo.w   [[CMP]], #1
437; CHECK-THUMB: cmp.w     [[CMP]], #0
438; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
439; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
440; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
441; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
442; CHECK-THUMB: cmp
443; CHECK-THUMB: bne
444; CHECK-THUMB: dmb {{ish$}}
445
446; CHECK-M: __atomic_compare_exchange_8
447
448  %r = atomicrmw umax i64* %ptr, i64 %val seq_cst
449  ret i64 %r
450}
451
452