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