IR: add "cmpxchg weak" variant to support permitted failure.
[oota-llvm.git] / test / CodeGen / ARM / atomic-64bit.ll
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 | 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
6 define 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
35 define 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
64 define 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
93 define 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
122 define 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
151 define 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
172 define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
173 ; CHECK-LABEL: test7:
174 ; CHECK: dmb {{ish$}}
175 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
176 ; CHECK-LE-DAG: eor     [[MISMATCH_LO:r[0-9]+]], [[REG1]], r1
177 ; CHECK-LE-DAG: eor     [[MISMATCH_HI:r[0-9]+]], [[REG2]], r2
178 ; CHECK-BE-DAG: eor     [[MISMATCH_LO:r[0-9]+]], [[REG2]], r2
179 ; CHECK-BE-DAG: eor     [[MISMATCH_HI:r[0-9]+]], [[REG1]], r1
180 ; CHECK: orrs    {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
181 ; CHECK: bne
182 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
183 ; CHECK: cmp
184 ; CHECK: bne
185 ; CHECK: dmb {{ish$}}
186
187 ; CHECK-THUMB-LABEL: test7:
188 ; CHECK-THUMB: dmb {{ish$}}
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    [[MISMATCH_HI]], [[MISMATCH_LO]]
195 ; CHECK-THUMB: bne
196 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
197 ; CHECK-THUMB: cmp
198 ; CHECK-THUMB: bne
199 ; CHECK-THUMB: dmb {{ish$}}
200
201   %pair = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst seq_cst
202   %r = extractvalue { i64, i1 } %pair, 0
203   ret i64 %r
204 }
205
206 ; Compiles down to a single ldrexd
207 define i64 @test8(i64* %ptr) {
208 ; CHECK-LABEL: test8:
209 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
210 ; CHECK: dmb {{ish$}}
211
212 ; CHECK-THUMB-LABEL: test8:
213 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
214 ; CHECK-THUMB: dmb {{ish$}}
215
216   %r = load atomic i64* %ptr seq_cst, align 8
217   ret i64 %r
218 }
219
220 ; Compiles down to atomicrmw xchg; there really isn't any more efficient
221 ; way to write it.
222 define void @test9(i64* %ptr, i64 %val) {
223 ; CHECK-LABEL: test9:
224 ; CHECK: dmb {{ish$}}
225 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
226 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
227 ; CHECK: cmp
228 ; CHECK: bne
229 ; CHECK: dmb {{ish$}}
230
231 ; CHECK-THUMB-LABEL: test9:
232 ; CHECK-THUMB: dmb {{ish$}}
233 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
234 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
235 ; CHECK-THUMB: cmp
236 ; CHECK-THUMB: bne
237 ; CHECK-THUMB: dmb {{ish$}}
238
239   store atomic i64 %val, i64* %ptr seq_cst, align 8
240   ret void
241 }
242
243 define i64 @test10(i64* %ptr, i64 %val) {
244 ; CHECK-LABEL: test10:
245 ; CHECK: dmb {{ish$}}
246 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
247 ; CHECK: mov     [[CARRY_LO:[a-z0-9]+]], #0
248 ; CHECK: mov     [[CARRY_HI:[a-z0-9]+]], #0
249 ; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
250 ; CHECK-LE: cmp     [[REG1]], r1
251 ; CHECK-BE: cmp     [[REG2]], r2
252 ; CHECK: movwls  [[CARRY_LO]], #1
253 ; CHECK-LE: cmp     [[REG2]], r2
254 ; CHECK-BE: cmp     [[REG1]], r1
255 ; CHECK: movwle  [[CARRY_HI]], #1
256 ; CHECK: moveq   [[CARRY_HI]], [[CARRY_LO]]
257 ; CHECK: cmp     [[CARRY_HI]], #0
258 ; CHECK: movne   [[OUT_HI]], [[REG2]]
259 ; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
260 ; CHECK: movne   [[OUT_LO]], [[REG1]]
261 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
262 ; CHECK: cmp
263 ; CHECK: bne
264 ; CHECK: dmb {{ish$}}
265
266 ; CHECK-THUMB-LABEL: test10:
267 ; CHECK-THUMB: dmb {{ish$}}
268 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
269 ; CHECK-THUMB: mov.w     [[CARRY_LO:[a-z0-9]+|lr]], #0
270 ; CHECK-THUMB: movs     [[CARRY_HI:[a-z0-9]+|lr]], #0
271 ; CHECK-THUMB-LE: cmp     [[REG1]], r2
272 ; CHECK-THUMB-BE: cmp     [[REG2]], r3
273 ; CHECK-THUMB: movls.w  [[CARRY_LO]], #1
274 ; CHECK-THUMB-LE: cmp     [[REG2]], r3
275 ; CHECK-THUMB-BE: cmp     [[REG1]], r2
276 ; CHECK-THUMB: movle  [[CARRY_HI]], #1
277 ; CHECK-THUMB: moveq   [[CARRY_HI]], [[CARRY_LO]]
278 ; CHECK-THUMB: mov     [[OUT_HI:[a-z0-9]+]], r3
279 ; CHECK-THUMB: cmp     [[CARRY_HI]], #0
280 ; CHECK-THUMB: mov     [[OUT_LO:[a-z0-9]+]], r2
281 ; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
282 ; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
283 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
284 ; CHECK-THUMB: cmp
285 ; CHECK-THUMB: bne
286 ; CHECK-THUMB: dmb {{ish$}}
287
288   %r = atomicrmw min i64* %ptr, i64 %val seq_cst
289   ret i64 %r
290 }
291
292 define i64 @test11(i64* %ptr, i64 %val) {
293 ; CHECK-LABEL: test11:
294 ; CHECK: dmb {{ish$}}
295 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
296 ; CHECK: mov     [[CARRY_LO:[a-z0-9]+]], #0
297 ; CHECK: mov     [[CARRY_HI:[a-z0-9]+]], #0
298 ; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
299 ; CHECK-LE: cmp     [[REG1]], r1
300 ; CHECK-BE: cmp     [[REG2]], r2
301 ; CHECK: movwls  [[CARRY_LO]], #1
302 ; CHECK-LE: cmp     [[REG2]], r2
303 ; CHECK-BE: cmp     [[REG1]], r1
304 ; CHECK: movwls  [[CARRY_HI]], #1
305 ; CHECK: moveq   [[CARRY_HI]], [[CARRY_LO]]
306 ; CHECK: cmp     [[CARRY_HI]], #0
307 ; CHECK: movne   [[OUT_HI]], [[REG2]]
308 ; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
309 ; CHECK: movne   [[OUT_LO]], [[REG1]]
310 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
311 ; CHECK: cmp
312 ; CHECK: bne
313 ; CHECK: dmb {{ish$}}
314
315 ; CHECK-THUMB-LABEL: test11:
316 ; CHECK-THUMB: dmb {{ish$}}
317 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
318 ; CHECK-THUMB: mov.w     [[CARRY_LO:[a-z0-9]+]], #0
319 ; CHECK-THUMB: movs     [[CARRY_HI:[a-z0-9]+]], #0
320 ; CHECK-THUMB-LE: cmp     [[REG1]], r2
321 ; CHECK-THUMB-BE: cmp     [[REG2]], r3
322 ; CHECK-THUMB: movls.w  [[CARRY_LO]], #1
323 ; CHECK-THUMB-LE: cmp     [[REG2]], r3
324 ; CHECK-THUMB-BE: cmp     [[REG1]], r2
325 ; CHECK-THUMB: movls  [[CARRY_HI]], #1
326 ; CHECK-THUMB: moveq   [[CARRY_HI]], [[CARRY_LO]]
327 ; CHECK-THUMB: mov     [[OUT_HI:[a-z0-9]+]], r3
328 ; CHECK-THUMB: cmp     [[CARRY_HI]], #0
329 ; CHECK-THUMB: mov     [[OUT_LO:[a-z0-9]+]], r2
330 ; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
331 ; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
332 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
333 ; CHECK-THUMB: cmp
334 ; CHECK-THUMB: bne
335 ; CHECK-THUMB: dmb {{ish$}}
336
337   %r = atomicrmw umin i64* %ptr, i64 %val seq_cst
338   ret i64 %r
339 }
340
341 define i64 @test12(i64* %ptr, i64 %val) {
342 ; CHECK-LABEL: test12:
343 ; CHECK: dmb {{ish$}}
344 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
345 ; CHECK: mov     [[CARRY_LO:[a-z0-9]+]], #0
346 ; CHECK: mov     [[CARRY_HI:[a-z0-9]+]], #0
347 ; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
348 ; CHECK-LE: cmp     [[REG1]], r1
349 ; CHECK-BE: cmp     [[REG2]], r2
350 ; CHECK: movwhi  [[CARRY_LO]], #1
351 ; CHECK-LE: cmp     [[REG2]], r2
352 ; CHECK-BE: cmp     [[REG1]], r1
353 ; CHECK: movwgt  [[CARRY_HI]], #1
354 ; CHECK: moveq   [[CARRY_HI]], [[CARRY_LO]]
355 ; CHECK: cmp     [[CARRY_HI]], #0
356 ; CHECK: movne   [[OUT_HI]], [[REG2]]
357 ; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
358 ; CHECK: movne   [[OUT_LO]], [[REG1]]
359 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
360 ; CHECK: cmp
361 ; CHECK: bne
362 ; CHECK: dmb {{ish$}}
363
364 ; CHECK-THUMB-LABEL: test12:
365 ; CHECK-THUMB: dmb {{ish$}}
366 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
367 ; CHECK-THUMB: mov.w     [[CARRY_LO:[a-z0-9]+]], #0
368 ; CHECK-THUMB: movs     [[CARRY_HI:[a-z0-9]+]], #0
369 ; CHECK-THUMB-LE: cmp     [[REG1]], r2
370 ; CHECK-THUMB-BE: cmp     [[REG2]], r3
371 ; CHECK-THUMB: movhi.w  [[CARRY_LO]], #1
372 ; CHECK-THUMB-LE: cmp     [[REG2]], r3
373 ; CHECK-THUMB-BE: cmp     [[REG1]], r2
374 ; CHECK-THUMB: movgt  [[CARRY_HI]], #1
375 ; CHECK-THUMB: moveq   [[CARRY_HI]], [[CARRY_LO]]
376 ; CHECK-THUMB: mov     [[OUT_HI:[a-z0-9]+]], r3
377 ; CHECK-THUMB: cmp     [[CARRY_HI]], #0
378 ; CHECK-THUMB: mov     [[OUT_LO:[a-z0-9]+]], r2
379 ; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
380 ; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
381 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
382 ; CHECK-THUMB: cmp
383 ; CHECK-THUMB: bne
384 ; CHECK-THUMB: dmb {{ish$}}
385
386   %r = atomicrmw max i64* %ptr, i64 %val seq_cst
387   ret i64 %r
388 }
389
390 define i64 @test13(i64* %ptr, i64 %val) {
391 ; CHECK-LABEL: test13:
392 ; CHECK: dmb {{ish$}}
393 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
394 ; CHECK: mov     [[CARRY_LO:[a-z0-9]+]], #0
395 ; CHECK: mov     [[CARRY_HI:[a-z0-9]+]], #0
396 ; CHECK: mov     [[OUT_HI:[a-z0-9]+]], r2
397 ; CHECK-LE: cmp     [[REG1]], r1
398 ; CHECK-BE: cmp     [[REG2]], r2
399 ; CHECK: movwhi  [[CARRY_LO]], #1
400 ; CHECK-LE: cmp     [[REG2]], r2
401 ; CHECK-BE: cmp     [[REG1]], r1
402 ; CHECK: movwhi  [[CARRY_HI]], #1
403 ; CHECK: moveq   [[CARRY_HI]], [[CARRY_LO]]
404 ; CHECK: cmp     [[CARRY_HI]], #0
405 ; CHECK: movne   [[OUT_HI]], [[REG2]]
406 ; CHECK: mov     [[OUT_LO:[a-z0-9]+]], r1
407 ; CHECK: movne   [[OUT_LO]], [[REG1]]
408 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
409 ; CHECK: cmp
410 ; CHECK: bne
411 ; CHECK: dmb {{ish$}}
412
413 ; CHECK-THUMB-LABEL: test13:
414 ; CHECK-THUMB: dmb {{ish$}}
415 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
416 ; CHECK-THUMB: mov.w     [[CARRY_LO:[a-z0-9]+]], #0
417 ; CHECK-THUMB: movs     [[CARRY_HI:[a-z0-9]+]], #0
418 ; CHECK-THUMB-LE: cmp     [[REG1]], r2
419 ; CHECK-THUMB-BE: cmp     [[REG2]], r3
420 ; CHECK-THUMB: movhi.w  [[CARRY_LO]], #1
421 ; CHECK-THUMB-LE: cmp     [[REG2]], r3
422 ; CHECK-THUMB-BE: cmp     [[REG1]], r2
423 ; CHECK-THUMB: movhi  [[CARRY_HI]], #1
424 ; CHECK-THUMB: moveq   [[CARRY_HI]], [[CARRY_LO]]
425 ; CHECK-THUMB: mov     [[OUT_HI:[a-z0-9]+]], r3
426 ; CHECK-THUMB: cmp     [[CARRY_HI]], #0
427 ; CHECK-THUMB: mov     [[OUT_LO:[a-z0-9]+]], r2
428 ; CHECK-THUMB: movne   [[OUT_HI]], [[REG2]]
429 ; CHECK-THUMB: movne   [[OUT_LO]], [[REG1]]
430 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
431 ; CHECK-THUMB: cmp
432 ; CHECK-THUMB: bne
433 ; CHECK-THUMB: dmb {{ish$}}
434   %r = atomicrmw umax i64* %ptr, i64 %val seq_cst
435   ret i64 %r
436 }
437