xref: /llvm-project/llvm/test/CodeGen/ARM/atomic-64bit.ll (revision e0ed0333f0fed2e73f805afd58b61176a87aa3ad)
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(ptr %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 ptr %ptr, i64 %val seq_cst
36  ret i64 %r
37}
38
39define i64 @test2(ptr %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 ptr %ptr, i64 %val seq_cst
67  ret i64 %r
68}
69
70define i64 @test3(ptr %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 ptr %ptr, i64 %val seq_cst
98  ret i64 %r
99}
100
101define i64 @test4(ptr %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 ptr %ptr, i64 %val seq_cst
129  ret i64 %r
130}
131
132define i64 @test5(ptr %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 ptr %ptr, i64 %val seq_cst
160  ret i64 %r
161}
162
163define i64 @test6(ptr %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 ptr %ptr, i64 %val seq_cst
183  ret i64 %r
184}
185
186define i64 @test7(ptr %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 ptr %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(ptr %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, ptr %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(ptr %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, ptr %ptr seq_cst, align 8
269  ret void
270}
271
272define i64 @test10(ptr %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: movge   [[OUT_HI]], [[REG2]]
282; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
283; CHECK: movge   [[OUT_LO]], [[REG1]]
284; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
285; CHECK: cmp
286; CHECK: bne
287; CHECK: dmb {{ish$}}
288
289; CHECK-THUMB-LABEL: test10:
290; CHECK-THUMB: dmb {{ish$}}
291; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
292; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
293; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
294; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
295; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
296; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
297; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
298; CHECK-THUMB: itt     ge
299; CHECK-THUMB: movge   [[OUT_HI]], [[REG2]]
300; CHECK-THUMB: movge   [[OUT_LO]], [[REG1]]
301; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
302; CHECK-THUMB: cmp
303; CHECK-THUMB: bne
304; CHECK-THUMB: dmb {{ish$}}
305
306; CHECK-M: __atomic_compare_exchange_8
307
308  %r = atomicrmw min ptr %ptr, i64 %val seq_cst
309  ret i64 %r
310}
311
312define i64 @test11(ptr %ptr, i64 %val) {
313; CHECK-LABEL: test11:
314; CHECK: dmb {{ish$}}
315; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
316; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
317; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
318; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
319; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
320; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
321; CHECK: movhs   [[OUT_HI]], [[REG2]]
322; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
323; CHECK: movhs   [[OUT_LO]], [[REG1]]
324; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
325; CHECK: cmp
326; CHECK: bne
327; CHECK: dmb {{ish$}}
328
329; CHECK-THUMB-LABEL: test11:
330; CHECK-THUMB: dmb {{ish$}}
331; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
332; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
333; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
334; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
335; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
336; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
337; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
338; CHECK-THUMB: itt     hs
339; CHECK-THUMB: movhs   [[OUT_HI]], [[REG2]]
340; CHECK-THUMB: movhs   [[OUT_LO]], [[REG1]]
341; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
342; CHECK-THUMB: cmp
343; CHECK-THUMB: bne
344; CHECK-THUMB: dmb {{ish$}}
345
346; CHECK-M: __atomic_compare_exchange_8
347
348  %r = atomicrmw umin ptr %ptr, i64 %val seq_cst
349  ret i64 %r
350}
351
352define i64 @test12(ptr %ptr, i64 %val) {
353; CHECK-LABEL: test12:
354; CHECK: dmb {{ish$}}
355; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
356; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
357; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
358; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
359; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
360; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
361; CHECK: movlt   [[OUT_HI]], [[REG2]]
362; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
363; CHECK: movlt   [[OUT_LO]], [[REG1]]
364; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
365; CHECK: cmp
366; CHECK: bne
367; CHECK: dmb {{ish$}}
368
369; CHECK-THUMB-LABEL: test12:
370; CHECK-THUMB: dmb {{ish$}}
371; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
372; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
373; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
374; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
375; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
376; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
377; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
378; CHECK-THUMB: itt     lt
379; CHECK-THUMB: movlt   [[OUT_HI]], [[REG2]]
380; CHECK-THUMB: movlt   [[OUT_LO]], [[REG1]]
381; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
382; CHECK-THUMB: cmp
383; CHECK-THUMB: bne
384; CHECK-THUMB: dmb {{ish$}}
385
386; CHECK-M: __atomic_compare_exchange_8
387
388  %r = atomicrmw max ptr %ptr, i64 %val seq_cst
389  ret i64 %r
390}
391
392define i64 @test13(ptr %ptr, i64 %val) {
393; CHECK-LABEL: test13:
394; CHECK: dmb {{ish$}}
395; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
396; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
397; CHECK-LE: subs    {{[^,]+}}, r1, [[REG1]]
398; CHECK-BE: subs    {{[^,]+}}, r2, [[REG2]]
399; CHECK-LE: sbcs    {{[^,]+}}, r2, [[REG2]]
400; CHECK-BE: sbcs    {{[^,]+}}, r1, [[REG1]]
401; CHECK: movlo   [[OUT_HI]], [[REG2]]
402; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
403; CHECK: movlo   [[OUT_LO]], [[REG1]]
404; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
405; CHECK: cmp
406; CHECK: bne
407; CHECK: dmb {{ish$}}
408
409; CHECK-THUMB-LABEL: test13:
410; CHECK-THUMB: dmb {{ish$}}
411; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
412; CHECK-THUMB: mov      [[OUT_LO:[a-z0-9]+]], r2
413; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
414; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
415; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
416; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
417; CHECK-THUMB: mov       [[OUT_HI:[a-z0-9]+]], r3
418; CHECK-THUMB: itt     lo
419; CHECK-THUMB: movlo   [[OUT_HI]], [[REG2]]
420; CHECK-THUMB: movlo   [[OUT_LO]], [[REG1]]
421; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
422; CHECK-THUMB: cmp
423; CHECK-THUMB: bne
424; CHECK-THUMB: dmb {{ish$}}
425
426; CHECK-M: __atomic_compare_exchange_8
427
428  %r = atomicrmw umax ptr %ptr, i64 %val seq_cst
429  ret i64 %r
430}
431
432