blob: 1ca78bfd1e32ad835810a36eb53218a1bb27be37 [file] [log] [blame]
Tim Northoverc882eb02014-04-03 11:44:58 +00001; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
2; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-THUMB
Amara Emersonb4ad2f32013-09-26 12:22:36 +00003
4@var8 = global i8 0
5@var16 = global i16 0
6@var32 = global i32 0
7@var64 = global i64 0
8
9define i8 @test_atomic_load_add_i8(i8 %offset) nounwind {
10; CHECK-LABEL: test_atomic_load_add_i8:
11 %old = atomicrmw add i8* @var8, i8 %offset seq_cst
12; CHECK-NOT: dmb
13; CHECK-NOT: mcr
14; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
15; CHECK: movt r[[ADDR]], :upper16:var8
16
17; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +000018; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +000019 ; r0 below is a reasonable guess but could change: it certainly comes into the
20 ; function there.
21; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
22; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
23; CHECK-NEXT: cmp [[STATUS]], #0
24; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
25; CHECK-NOT: dmb
26; CHECK-NOT: mcr
27
28; CHECK: mov r0, r[[OLD]]
29 ret i8 %old
30}
31
32define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
33; CHECK-LABEL: test_atomic_load_add_i16:
34 %old = atomicrmw add i16* @var16, i16 %offset acquire
35; CHECK-NOT: dmb
36; CHECK-NOT: mcr
37; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
38; CHECK: movt r[[ADDR]], :upper16:var16
39
40; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +000041; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +000042 ; r0 below is a reasonable guess but could change: it certainly comes into the
43 ; function there.
44; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
45; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
46; CHECK-NEXT: cmp [[STATUS]], #0
47; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
48; CHECK-NOT: dmb
49; CHECK-NOT: mcr
50
51; CHECK: mov r0, r[[OLD]]
52 ret i16 %old
53}
54
55define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
56; CHECK-LABEL: test_atomic_load_add_i32:
57 %old = atomicrmw add i32* @var32, i32 %offset release
58; CHECK-NOT: dmb
59; CHECK-NOT: mcr
60; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
61; CHECK: movt r[[ADDR]], :upper16:var32
62
63; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +000064; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +000065 ; r0 below is a reasonable guess but could change: it certainly comes into the
66 ; function there.
67; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
68; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
69; CHECK-NEXT: cmp [[STATUS]], #0
70; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
71; CHECK-NOT: dmb
72; CHECK-NOT: mcr
73
74; CHECK: mov r0, r[[OLD]]
75 ret i32 %old
76}
77
Tim Northoverc882eb02014-04-03 11:44:58 +000078define void @test_atomic_load_add_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +000079; CHECK-LABEL: test_atomic_load_add_i64:
80 %old = atomicrmw add i64* @var64, i64 %offset monotonic
81; CHECK-NOT: dmb
82; CHECK-NOT: mcr
83; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
84; CHECK: movt r[[ADDR]], :upper16:var64
85
86; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +000087; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +000088 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
89 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +000090; CHECK-NEXT: adds{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +000091; CHECK-NEXT: adc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
92; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
93; CHECK-NEXT: cmp [[STATUS]], #0
94; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
95; CHECK-NOT: dmb
96; CHECK-NOT: mcr
97
Tim Northoverc882eb02014-04-03 11:44:58 +000098; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
99 store i64 %old, i64* @var64
100 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000101}
102
103define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
104; CHECK-LABEL: test_atomic_load_sub_i8:
105 %old = atomicrmw sub i8* @var8, i8 %offset monotonic
106; CHECK-NOT: dmb
107; CHECK-NOT: mcr
108; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
109; CHECK: movt r[[ADDR]], :upper16:var8
110
111; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000112; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000113 ; r0 below is a reasonable guess but could change: it certainly comes into the
114 ; function there.
115; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
116; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
117; CHECK-NEXT: cmp [[STATUS]], #0
118; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
119; CHECK-NOT: dmb
120; CHECK-NOT: mcr
121
122; CHECK: mov r0, r[[OLD]]
123 ret i8 %old
124}
125
126define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
127; CHECK-LABEL: test_atomic_load_sub_i16:
128 %old = atomicrmw sub i16* @var16, i16 %offset release
129; CHECK-NOT: dmb
130; CHECK-NOT: mcr
131; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
132; CHECK: movt r[[ADDR]], :upper16:var16
133
134; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000135; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000136 ; r0 below is a reasonable guess but could change: it certainly comes into the
137 ; function there.
138; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
139; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
140; CHECK-NEXT: cmp [[STATUS]], #0
141; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
142; CHECK-NOT: dmb
143; CHECK-NOT: mcr
144
145; CHECK: mov r0, r[[OLD]]
146 ret i16 %old
147}
148
149define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
150; CHECK-LABEL: test_atomic_load_sub_i32:
151 %old = atomicrmw sub i32* @var32, i32 %offset acquire
152; CHECK-NOT: dmb
153; CHECK-NOT: mcr
154; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
155; CHECK: movt r[[ADDR]], :upper16:var32
156
157; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000158; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000159 ; r0 below is a reasonable guess but could change: it certainly comes into the
160 ; function there.
161; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
162; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
163; CHECK-NEXT: cmp [[STATUS]], #0
164; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
165; CHECK-NOT: dmb
166; CHECK-NOT: mcr
167
168; CHECK: mov r0, r[[OLD]]
169 ret i32 %old
170}
171
Tim Northoverc882eb02014-04-03 11:44:58 +0000172define void @test_atomic_load_sub_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000173; CHECK-LABEL: test_atomic_load_sub_i64:
174 %old = atomicrmw sub i64* @var64, i64 %offset seq_cst
175; CHECK-NOT: dmb
176; CHECK-NOT: mcr
177; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
178; CHECK: movt r[[ADDR]], :upper16:var64
179
180; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000181; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000182 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
183 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000184; CHECK-NEXT: subs{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000185; CHECK-NEXT: sbc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
186; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
187; CHECK-NEXT: cmp [[STATUS]], #0
188; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
189; CHECK-NOT: dmb
190; CHECK-NOT: mcr
191
Tim Northoverc882eb02014-04-03 11:44:58 +0000192; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
193 store i64 %old, i64* @var64
194 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000195}
196
197define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
198; CHECK-LABEL: test_atomic_load_and_i8:
199 %old = atomicrmw and i8* @var8, i8 %offset release
200; CHECK-NOT: dmb
201; CHECK-NOT: mcr
202; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
203; CHECK: movt r[[ADDR]], :upper16:var8
204
205; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000206; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000207 ; r0 below is a reasonable guess but could change: it certainly comes into the
208 ; function there.
209; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
210; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
211; CHECK-NEXT: cmp [[STATUS]], #0
212; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
213; CHECK-NOT: dmb
214; CHECK-NOT: mcr
215
216; CHECK: mov r0, r[[OLD]]
217 ret i8 %old
218}
219
220define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
221; CHECK-LABEL: test_atomic_load_and_i16:
222 %old = atomicrmw and i16* @var16, i16 %offset monotonic
223; CHECK-NOT: dmb
224; CHECK-NOT: mcr
225; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
226; CHECK: movt r[[ADDR]], :upper16:var16
227
228; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000229; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000230 ; r0 below is a reasonable guess but could change: it certainly comes into the
231 ; function there.
232; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
233; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
234; CHECK-NEXT: cmp [[STATUS]], #0
235; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
236; CHECK-NOT: dmb
237; CHECK-NOT: mcr
238
239; CHECK: mov r0, r[[OLD]]
240 ret i16 %old
241}
242
243define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
244; CHECK-LABEL: test_atomic_load_and_i32:
245 %old = atomicrmw and i32* @var32, i32 %offset seq_cst
246; CHECK-NOT: dmb
247; CHECK-NOT: mcr
248; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
249; CHECK: movt r[[ADDR]], :upper16:var32
250
251; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000252; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000253 ; r0 below is a reasonable guess but could change: it certainly comes into the
254 ; function there.
255; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
256; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
257; CHECK-NEXT: cmp [[STATUS]], #0
258; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
259; CHECK-NOT: dmb
260; CHECK-NOT: mcr
261
262; CHECK: mov r0, r[[OLD]]
263 ret i32 %old
264}
265
Tim Northoverc882eb02014-04-03 11:44:58 +0000266define void @test_atomic_load_and_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000267; CHECK-LABEL: test_atomic_load_and_i64:
268 %old = atomicrmw and i64* @var64, i64 %offset acquire
269; CHECK-NOT: dmb
270; CHECK-NOT: mcr
271; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
272; CHECK: movt r[[ADDR]], :upper16:var64
273
274; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000275; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000276 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
277 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000278; CHECK-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
279; CHECK-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
280; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000281; CHECK-NEXT: cmp [[STATUS]], #0
282; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
283; CHECK-NOT: dmb
284; CHECK-NOT: mcr
285
Tim Northoverc882eb02014-04-03 11:44:58 +0000286; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
287 store i64 %old, i64* @var64
288 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000289}
290
291define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
292; CHECK-LABEL: test_atomic_load_or_i8:
293 %old = atomicrmw or i8* @var8, i8 %offset seq_cst
294; CHECK-NOT: dmb
295; CHECK-NOT: mcr
296; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
297; CHECK: movt r[[ADDR]], :upper16:var8
298
299; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000300; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000301 ; r0 below is a reasonable guess but could change: it certainly comes into the
302 ; function there.
303; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
304; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
305; CHECK-NEXT: cmp [[STATUS]], #0
306; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
307; CHECK-NOT: dmb
308; CHECK-NOT: mcr
309
310; CHECK: mov r0, r[[OLD]]
311 ret i8 %old
312}
313
314define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
315; CHECK-LABEL: test_atomic_load_or_i16:
316 %old = atomicrmw or i16* @var16, i16 %offset monotonic
317; CHECK-NOT: dmb
318; CHECK-NOT: mcr
319; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
320; CHECK: movt r[[ADDR]], :upper16:var16
321
322; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000323; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000324 ; r0 below is a reasonable guess but could change: it certainly comes into the
325 ; function there.
326; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
327; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
328; CHECK-NEXT: cmp [[STATUS]], #0
329; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
330; CHECK-NOT: dmb
331; CHECK-NOT: mcr
332
333; CHECK: mov r0, r[[OLD]]
334 ret i16 %old
335}
336
337define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
338; CHECK-LABEL: test_atomic_load_or_i32:
339 %old = atomicrmw or i32* @var32, i32 %offset acquire
340; CHECK-NOT: dmb
341; CHECK-NOT: mcr
342; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
343; CHECK: movt r[[ADDR]], :upper16:var32
344
345; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000346; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000347 ; r0 below is a reasonable guess but could change: it certainly comes into the
348 ; function there.
349; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
350; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
351; CHECK-NEXT: cmp [[STATUS]], #0
352; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
353; CHECK-NOT: dmb
354; CHECK-NOT: mcr
355
356; CHECK: mov r0, r[[OLD]]
357 ret i32 %old
358}
359
Tim Northoverc882eb02014-04-03 11:44:58 +0000360define void @test_atomic_load_or_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000361; CHECK-LABEL: test_atomic_load_or_i64:
362 %old = atomicrmw or i64* @var64, i64 %offset release
363; CHECK-NOT: dmb
364; CHECK-NOT: mcr
365; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
366; CHECK: movt r[[ADDR]], :upper16:var64
367
368; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000369; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000370 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
371 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000372; CHECK-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
373; CHECK-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
374; CHECK: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000375; CHECK-NEXT: cmp [[STATUS]], #0
376; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
377; CHECK-NOT: dmb
378; CHECK-NOT: mcr
379
Tim Northoverc882eb02014-04-03 11:44:58 +0000380; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
381 store i64 %old, i64* @var64
382 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000383}
384
385define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
386; CHECK-LABEL: test_atomic_load_xor_i8:
387 %old = atomicrmw xor i8* @var8, i8 %offset acquire
388; CHECK-NOT: dmb
389; CHECK-NOT: mcr
390; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
391; CHECK: movt r[[ADDR]], :upper16:var8
392
393; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000394; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000395 ; r0 below is a reasonable guess but could change: it certainly comes into the
396 ; function there.
397; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
398; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
399; CHECK-NEXT: cmp [[STATUS]], #0
400; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
401; CHECK-NOT: dmb
402; CHECK-NOT: mcr
403
404; CHECK: mov r0, r[[OLD]]
405 ret i8 %old
406}
407
408define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
409; CHECK-LABEL: test_atomic_load_xor_i16:
410 %old = atomicrmw xor i16* @var16, i16 %offset release
411; CHECK-NOT: dmb
412; CHECK-NOT: mcr
413; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
414; CHECK: movt r[[ADDR]], :upper16:var16
415
416; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000417; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000418 ; r0 below is a reasonable guess but could change: it certainly comes into the
419 ; function there.
420; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
421; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
422; CHECK-NEXT: cmp [[STATUS]], #0
423; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
424; CHECK-NOT: dmb
425; CHECK-NOT: mcr
426
427; CHECK: mov r0, r[[OLD]]
428 ret i16 %old
429}
430
431define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
432; CHECK-LABEL: test_atomic_load_xor_i32:
433 %old = atomicrmw xor i32* @var32, i32 %offset seq_cst
434; CHECK-NOT: dmb
435; CHECK-NOT: mcr
436; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
437; CHECK: movt r[[ADDR]], :upper16:var32
438
439; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000440; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000441 ; r0 below is a reasonable guess but could change: it certainly comes into the
442 ; function there.
443; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
444; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
445; CHECK-NEXT: cmp [[STATUS]], #0
446; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
447; CHECK-NOT: dmb
448; CHECK-NOT: mcr
449
450; CHECK: mov r0, r[[OLD]]
451 ret i32 %old
452}
453
Tim Northoverc882eb02014-04-03 11:44:58 +0000454define void @test_atomic_load_xor_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000455; CHECK-LABEL: test_atomic_load_xor_i64:
456 %old = atomicrmw xor i64* @var64, i64 %offset monotonic
457; CHECK-NOT: dmb
458; CHECK-NOT: mcr
459; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
460; CHECK: movt r[[ADDR]], :upper16:var64
461
462; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000463; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000464 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
465 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000466; CHECK-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
467; CHECK-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
468; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000469; CHECK-NEXT: cmp [[STATUS]], #0
470; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
471; CHECK-NOT: dmb
472; CHECK-NOT: mcr
473
Tim Northoverc882eb02014-04-03 11:44:58 +0000474; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
475 store i64 %old, i64* @var64
476 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000477}
478
479define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
480; CHECK-LABEL: test_atomic_load_xchg_i8:
481 %old = atomicrmw xchg i8* @var8, i8 %offset monotonic
482; CHECK-NOT: dmb
483; CHECK-NOT: mcr
484; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
485; CHECK: movt r[[ADDR]], :upper16:var8
486
487; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000488; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000489 ; r0 below is a reasonable guess but could change: it certainly comes into the
490 ; function there.
491; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
492; CHECK-NEXT: cmp [[STATUS]], #0
493; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
494; CHECK-NOT: dmb
495; CHECK-NOT: mcr
496
497; CHECK: mov r0, r[[OLD]]
498 ret i8 %old
499}
500
501define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
502; CHECK-LABEL: test_atomic_load_xchg_i16:
503 %old = atomicrmw xchg i16* @var16, i16 %offset seq_cst
504; CHECK-NOT: dmb
505; CHECK-NOT: mcr
506; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
507; CHECK: movt r[[ADDR]], :upper16:var16
508
509; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000510; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000511 ; r0 below is a reasonable guess but could change: it certainly comes into the
512 ; function there.
513; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
514; CHECK-NEXT: cmp [[STATUS]], #0
515; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
516; CHECK-NOT: dmb
517; CHECK-NOT: mcr
518
519; CHECK: mov r0, r[[OLD]]
520 ret i16 %old
521}
522
523define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
524; CHECK-LABEL: test_atomic_load_xchg_i32:
525 %old = atomicrmw xchg i32* @var32, i32 %offset release
526; CHECK-NOT: dmb
527; CHECK-NOT: mcr
528; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
529; CHECK: movt r[[ADDR]], :upper16:var32
530
531; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000532; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000533 ; r0 below is a reasonable guess but could change: it certainly comes into the
534 ; function there.
535; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
536; CHECK-NEXT: cmp [[STATUS]], #0
537; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
538; CHECK-NOT: dmb
539; CHECK-NOT: mcr
540
541; CHECK: mov r0, r[[OLD]]
542 ret i32 %old
543}
544
Tim Northoverc882eb02014-04-03 11:44:58 +0000545define void @test_atomic_load_xchg_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000546; CHECK-LABEL: test_atomic_load_xchg_i64:
547 %old = atomicrmw xchg i64* @var64, i64 %offset acquire
548; CHECK-NOT: dmb
549; CHECK-NOT: mcr
550; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
551; CHECK: movt r[[ADDR]], :upper16:var64
552
553; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000554; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000555 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
556 ; function there.
557; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
558; CHECK-NEXT: cmp [[STATUS]], #0
559; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
560; CHECK-NOT: dmb
561; CHECK-NOT: mcr
562
Tim Northoverc882eb02014-04-03 11:44:58 +0000563; CHECK: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
564 store i64 %old, i64* @var64
565 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000566}
567
Tim Northoverc882eb02014-04-03 11:44:58 +0000568define i8 @test_atomic_load_min_i8(i8 signext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000569; CHECK-LABEL: test_atomic_load_min_i8:
570 %old = atomicrmw min i8* @var8, i8 %offset acquire
571; CHECK-NOT: dmb
572; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000573; CHECK-DAG: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
574; CHECK-DAG: movt [[ADDR]], :upper16:var8
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000575
576; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000577; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000578; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
579 ; r0 below is a reasonable guess but could change: it certainly comes into the
580 ; function there.
581; CHECK-NEXT: cmp r[[OLDX]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000582; Thumb mode: it le
583; CHECK: movle r[[OLDX]], r[[OLD]]
584; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000585; CHECK-NEXT: cmp [[STATUS]], #0
586; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
587; CHECK-NOT: dmb
588; CHECK-NOT: mcr
589
590; CHECK: mov r0, r[[OLD]]
591 ret i8 %old
592}
593
Tim Northoverc882eb02014-04-03 11:44:58 +0000594define i16 @test_atomic_load_min_i16(i16 signext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000595; CHECK-LABEL: test_atomic_load_min_i16:
596 %old = atomicrmw min i16* @var16, i16 %offset release
597; CHECK-NOT: dmb
598; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000599; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
600; CHECK: movt [[ADDR]], :upper16:var16
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000601
602; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000603; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000604; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
605 ; r0 below is a reasonable guess but could change: it certainly comes into the
606 ; function there.
607; CHECK-NEXT: cmp r[[OLDX]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000608; Thumb mode: it le
609; CHECK: movle r[[OLDX]], r[[OLD]]
610; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000611; CHECK-NEXT: cmp [[STATUS]], #0
612; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
613; CHECK-NOT: dmb
614; CHECK-NOT: mcr
615
616; CHECK: mov r0, r[[OLD]]
617 ret i16 %old
618}
619
620define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
621; CHECK-LABEL: test_atomic_load_min_i32:
622 %old = atomicrmw min i32* @var32, i32 %offset monotonic
623; CHECK-NOT: dmb
624; CHECK-NOT: mcr
625; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
626; CHECK: movt r[[ADDR]], :upper16:var32
627
628; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000629; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000630 ; r0 below is a reasonable guess but could change: it certainly comes into the
631 ; function there.
632; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
633; CHECK-NEXT: cmp r[[OLD]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000634; Thumb mode: it le
635; CHECK: movle r[[NEW]], r[[OLD]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000636; CHECK-NEXT: strex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
637; CHECK-NEXT: cmp [[STATUS]], #0
638; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
639; CHECK-NOT: dmb
640; CHECK-NOT: mcr
641
642; CHECK: mov r0, r[[OLD]]
643 ret i32 %old
644}
645
Tim Northoverc882eb02014-04-03 11:44:58 +0000646define void @test_atomic_load_min_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000647; CHECK-LABEL: test_atomic_load_min_i64:
648 %old = atomicrmw min i64* @var64, i64 %offset seq_cst
649; CHECK-NOT: dmb
650; CHECK-NOT: mcr
651; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
652; CHECK: movt r[[ADDR]], :upper16:var64
653
654; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000655; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000656 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
657 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000658; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
659; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
660; CHECK-ARM: cmp [[OLD1]], r0
661; CHECK-ARM: movwls [[LOCARRY]], #1
662; CHECK-ARM: cmp [[OLD2]], r1
663; CHECK-ARM: movwle [[HICARRY]], #1
664; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
665; CHECK-ARM: cmp [[HICARRY]], #0
666; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
667; CHECK-ARM: movne [[MINHI]], [[OLD2]]
668; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
669; CHECK-ARM: movne [[MINLO]], [[OLD1]]
670; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
671; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000672; CHECK-NEXT: cmp [[STATUS]], #0
673; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
674; CHECK-NOT: dmb
675; CHECK-NOT: mcr
676
Tim Northoverc882eb02014-04-03 11:44:58 +0000677; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
678 store i64 %old, i64* @var64
679 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000680}
681
Tim Northoverc882eb02014-04-03 11:44:58 +0000682define i8 @test_atomic_load_max_i8(i8 signext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000683; CHECK-LABEL: test_atomic_load_max_i8:
684 %old = atomicrmw max i8* @var8, i8 %offset seq_cst
685; CHECK-NOT: dmb
686; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000687; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
688; CHECK: movt [[ADDR]], :upper16:var8
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000689
690; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000691; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000692; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
693 ; r0 below is a reasonable guess but could change: it certainly comes into the
694 ; function there.
695; CHECK-NEXT: cmp r[[OLDX]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000696; Thumb mode: it gt
697; CHECK: movgt r[[OLDX]], r[[OLD]]
698; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000699; CHECK-NEXT: cmp [[STATUS]], #0
700; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
701; CHECK-NOT: dmb
702; CHECK-NOT: mcr
703
704; CHECK: mov r0, r[[OLD]]
705 ret i8 %old
706}
707
Tim Northoverc882eb02014-04-03 11:44:58 +0000708define i16 @test_atomic_load_max_i16(i16 signext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000709; CHECK-LABEL: test_atomic_load_max_i16:
710 %old = atomicrmw max i16* @var16, i16 %offset acquire
711; CHECK-NOT: dmb
712; CHECK-NOT: mcr
713; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
714; CHECK: movt r[[ADDR]], :upper16:var16
715
716; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000717; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000718; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
719 ; r0 below is a reasonable guess but could change: it certainly comes into the
720 ; function there.
721; CHECK-NEXT: cmp r[[OLDX]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000722; Thumb mode: it gt
723; CHECK: movgt r[[OLDX]], r[[OLD]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000724; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
725; CHECK-NEXT: cmp [[STATUS]], #0
726; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
727; CHECK-NOT: dmb
728; CHECK-NOT: mcr
729
730; CHECK: mov r0, r[[OLD]]
731 ret i16 %old
732}
733
734define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
735; CHECK-LABEL: test_atomic_load_max_i32:
736 %old = atomicrmw max i32* @var32, i32 %offset release
737; CHECK-NOT: dmb
738; CHECK-NOT: mcr
739; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
740; CHECK: movt r[[ADDR]], :upper16:var32
741
742; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000743; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000744 ; r0 below is a reasonable guess but could change: it certainly comes into the
745 ; function there.
746; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
747; CHECK-NEXT: cmp r[[OLD]], r0
748; Thumb mode: it gt
749; CHECK: movgt r[[NEW]], r[[OLD]]
750; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
751; CHECK-NEXT: cmp [[STATUS]], #0
752; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
753; CHECK-NOT: dmb
754; CHECK-NOT: mcr
755
756; CHECK: mov r0, r[[OLD]]
757 ret i32 %old
758}
759
Tim Northoverc882eb02014-04-03 11:44:58 +0000760define void @test_atomic_load_max_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000761; CHECK-LABEL: test_atomic_load_max_i64:
762 %old = atomicrmw max i64* @var64, i64 %offset monotonic
763; CHECK-NOT: dmb
764; CHECK-NOT: mcr
765; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
766; CHECK: movt r[[ADDR]], :upper16:var64
767
768; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000769; CHECK: ldrexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000770 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
771 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000772; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
773; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
774; CHECK-ARM: cmp [[OLD1]], r0
775; CHECK-ARM: movwhi [[LOCARRY]], #1
776; CHECK-ARM: cmp [[OLD2]], r1
777; CHECK-ARM: movwgt [[HICARRY]], #1
778; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
779; CHECK-ARM: cmp [[HICARRY]], #0
780; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
781; CHECK-ARM: movne [[MINHI]], [[OLD2]]
782; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
783; CHECK-ARM: movne [[MINLO]], [[OLD1]]
784; CHECK-ARM: strexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
785; CHECK-THUMB: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000786; CHECK-NEXT: cmp [[STATUS]], #0
787; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
788; CHECK-NOT: dmb
789; CHECK-NOT: mcr
790
Tim Northoverc882eb02014-04-03 11:44:58 +0000791; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
792 store i64 %old, i64* @var64
793 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000794}
795
Tim Northoverc882eb02014-04-03 11:44:58 +0000796define i8 @test_atomic_load_umin_i8(i8 zeroext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000797; CHECK-LABEL: test_atomic_load_umin_i8:
798 %old = atomicrmw umin i8* @var8, i8 %offset monotonic
799; CHECK-NOT: dmb
800; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000801; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
802; CHECK: movt [[ADDR]], :upper16:var8
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000803
804; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000805; CHECK: ldrexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000806 ; r0 below is a reasonable guess but could change: it certainly comes into the
807 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000808; CHECK-NEXT: uxtb r[[OLDX]], r[[OLD]]
809; CHECK-NEXT: cmp r[[OLDX]], r0
810; Thumb mode: it ls
811; CHECK: movls r[[NEW]], r[[OLD]]
812; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000813; CHECK-NEXT: cmp [[STATUS]], #0
814; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
815; CHECK-NOT: dmb
816; CHECK-NOT: mcr
817
818; CHECK: mov r0, r[[OLD]]
819 ret i8 %old
820}
821
Tim Northoverc882eb02014-04-03 11:44:58 +0000822define i16 @test_atomic_load_umin_i16(i16 zeroext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000823; CHECK-LABEL: test_atomic_load_umin_i16:
824 %old = atomicrmw umin i16* @var16, i16 %offset acquire
825; CHECK-NOT: dmb
826; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000827; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
828; CHECK: movt [[ADDR]], :upper16:var16
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000829
830; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000831; CHECK: ldaexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000832 ; r0 below is a reasonable guess but could change: it certainly comes into the
833 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000834; CHECK-NEXT: uxth r[[OLDX]], r[[OLD]]
835; CHECK-NEXT: cmp r[[OLDX]], r0
836; Thumb mode: it ls
837; CHECK: movls r[[NEW]], r[[OLD]]
838; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000839; CHECK-NEXT: cmp [[STATUS]], #0
840; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
841; CHECK-NOT: dmb
842; CHECK-NOT: mcr
843
844; CHECK: mov r0, r[[OLD]]
845 ret i16 %old
846}
847
848define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
849; CHECK-LABEL: test_atomic_load_umin_i32:
850 %old = atomicrmw umin i32* @var32, i32 %offset seq_cst
851; CHECK-NOT: dmb
852; CHECK-NOT: mcr
853; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
854; CHECK: movt r[[ADDR]], :upper16:var32
855
856; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000857; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000858 ; r0 below is a reasonable guess but could change: it certainly comes into the
859 ; function there.
860; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
861; CHECK-NEXT: cmp r[[OLD]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000862; Thumb mode: it ls
863; CHECK: movls r[[NEW]], r[[OLD]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000864; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
865; CHECK-NEXT: cmp [[STATUS]], #0
866; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
867; CHECK-NOT: dmb
868; CHECK-NOT: mcr
869
870; CHECK: mov r0, r[[OLD]]
871 ret i32 %old
872}
873
Tim Northoverc882eb02014-04-03 11:44:58 +0000874define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000875; CHECK-LABEL: test_atomic_load_umin_i64:
Tim Northoverc882eb02014-04-03 11:44:58 +0000876 %old = atomicrmw umin i64* @var64, i64 %offset seq_cst
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000877; CHECK-NOT: dmb
878; CHECK-NOT: mcr
879; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
880; CHECK: movt r[[ADDR]], :upper16:var64
881
882; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000883; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000884 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
885 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000886; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
887; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
888; CHECK-ARM: cmp [[OLD1]], r0
889; CHECK-ARM: movwls [[LOCARRY]], #1
890; CHECK-ARM: cmp [[OLD2]], r1
891; CHECK-ARM: movwls [[HICARRY]], #1
892; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
893; CHECK-ARM: cmp [[HICARRY]], #0
894; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
895; CHECK-ARM: movne [[MINHI]], [[OLD2]]
896; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
897; CHECK-ARM: movne [[MINLO]], [[OLD1]]
898; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
899; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000900; CHECK-NEXT: cmp [[STATUS]], #0
901; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
902; CHECK-NOT: dmb
903; CHECK-NOT: mcr
904
Tim Northoverc882eb02014-04-03 11:44:58 +0000905; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
906 store i64 %old, i64* @var64
907 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000908}
909
Tim Northoverc882eb02014-04-03 11:44:58 +0000910define i8 @test_atomic_load_umax_i8(i8 zeroext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000911; CHECK-LABEL: test_atomic_load_umax_i8:
912 %old = atomicrmw umax i8* @var8, i8 %offset acq_rel
913; CHECK-NOT: dmb
914; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000915; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
916; CHECK: movt [[ADDR]], :upper16:var8
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000917
918; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000919; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000920 ; r0 below is a reasonable guess but could change: it certainly comes into the
921 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000922; CHECK-NEXT: uxtb r[[OLDX:[0-9]+]], r[[OLD]]
923; CHECK-NEXT: cmp r[[OLDX]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000924; Thumb mode: it hi
925; CHECK: movhi r[[NEW]], r[[OLD]]
Tim Northoverc882eb02014-04-03 11:44:58 +0000926; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000927; CHECK-NEXT: cmp [[STATUS]], #0
928; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
929; CHECK-NOT: dmb
930; CHECK-NOT: mcr
931
932; CHECK: mov r0, r[[OLD]]
933 ret i8 %old
934}
935
Tim Northoverc882eb02014-04-03 11:44:58 +0000936define i16 @test_atomic_load_umax_i16(i16 zeroext %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000937; CHECK-LABEL: test_atomic_load_umax_i16:
938 %old = atomicrmw umax i16* @var16, i16 %offset monotonic
939; CHECK-NOT: dmb
940; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +0000941; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
942; CHECK: movt [[ADDR]], :upper16:var16
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000943
944; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000945; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000946 ; r0 below is a reasonable guess but could change: it certainly comes into the
947 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +0000948; CHECK-NEXT: uxth r[[OLDX:[0-9]+]], r[[OLD]]
949; CHECK-NEXT: cmp r[[OLDX]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000950; Thumb mode: it hi
951; CHECK: movhi r[[NEW]], r[[OLD]]
Tim Northoverc882eb02014-04-03 11:44:58 +0000952; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000953; CHECK-NEXT: cmp [[STATUS]], #0
954; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
955; CHECK-NOT: dmb
956; CHECK-NOT: mcr
957
958; CHECK: mov r0, r[[OLD]]
959 ret i16 %old
960}
961
962define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
963; CHECK-LABEL: test_atomic_load_umax_i32:
964 %old = atomicrmw umax i32* @var32, i32 %offset seq_cst
965; CHECK-NOT: dmb
966; CHECK-NOT: mcr
967; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
968; CHECK: movt r[[ADDR]], :upper16:var32
969
970; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000971; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000972 ; r0 below is a reasonable guess but could change: it certainly comes into the
973 ; function there.
974; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
975; CHECK-NEXT: cmp r[[OLD]], r0
976; Thumb mode: it hi
977; CHECK: movhi r[[NEW]], r[[OLD]]
978; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
979; CHECK-NEXT: cmp [[STATUS]], #0
980; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
981; CHECK-NOT: dmb
982; CHECK-NOT: mcr
983
984; CHECK: mov r0, r[[OLD]]
985 ret i32 %old
986}
987
Tim Northoverc882eb02014-04-03 11:44:58 +0000988define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000989; CHECK-LABEL: test_atomic_load_umax_i64:
Tim Northoverc882eb02014-04-03 11:44:58 +0000990 %old = atomicrmw umax i64* @var64, i64 %offset seq_cst
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000991; CHECK-NOT: dmb
992; CHECK-NOT: mcr
993; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
994; CHECK: movt r[[ADDR]], :upper16:var64
995
996; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +0000997; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +0000998 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
999 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001000; CHECK-ARM: mov [[LOCARRY:r[0-9]+|lr]], #0
1001; CHECK-ARM: mov [[HICARRY:r[0-9]+|lr]], #0
1002; CHECK-ARM: cmp [[OLD1]], r0
1003; CHECK-ARM: movwhi [[LOCARRY]], #1
1004; CHECK-ARM: cmp [[OLD2]], r1
1005; CHECK-ARM: movwhi [[HICARRY]], #1
1006; CHECK-ARM: moveq [[HICARRY]], [[LOCARRY]]
1007; CHECK-ARM: cmp [[HICARRY]], #0
1008; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
1009; CHECK-ARM: movne [[MINHI]], [[OLD2]]
1010; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
1011; CHECK-ARM: movne [[MINLO]], [[OLD1]]
1012; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
1013; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001014; CHECK-NEXT: cmp [[STATUS]], #0
1015; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1016; CHECK-NOT: dmb
1017; CHECK-NOT: mcr
1018
Tim Northoverc882eb02014-04-03 11:44:58 +00001019; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
1020 store i64 %old, i64* @var64
1021 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001022}
1023
Tim Northoverc882eb02014-04-03 11:44:58 +00001024define i8 @test_atomic_cmpxchg_i8(i8 zeroext %wanted, i8 zeroext %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001025; CHECK-LABEL: test_atomic_cmpxchg_i8:
Tim Northovere94a5182014-03-11 10:48:52 +00001026 %old = cmpxchg i8* @var8, i8 %wanted, i8 %new acquire acquire
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001027; CHECK-NOT: dmb
1028; CHECK-NOT: mcr
1029; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1030; CHECK: movt r[[ADDR]], :upper16:var8
1031
1032; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001033; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001034 ; r0 below is a reasonable guess but could change: it certainly comes into the
1035 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001036; CHECK-NEXT: uxtb r[[OLDX:[0-9]+]], r[[OLD]]
1037; CHECK-NEXT: cmp r[[OLDX]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001038; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1039; CHECK-NEXT: BB#2:
1040 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001041; CHECK: strexb [[STATUS:r[0-9]+]], r1, {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001042; CHECK-NEXT: cmp [[STATUS]], #0
1043; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1044; CHECK-NOT: dmb
1045; CHECK-NOT: mcr
1046
1047; CHECK: mov r0, r[[OLD]]
1048 ret i8 %old
1049}
1050
Tim Northoverc882eb02014-04-03 11:44:58 +00001051define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001052; CHECK-LABEL: test_atomic_cmpxchg_i16:
Tim Northovere94a5182014-03-11 10:48:52 +00001053 %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst seq_cst
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001054; CHECK-NOT: dmb
1055; CHECK-NOT: mcr
1056; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1057; CHECK: movt r[[ADDR]], :upper16:var16
1058
1059; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001060; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001061 ; r0 below is a reasonable guess but could change: it certainly comes into the
1062 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001063; CHECK-NEXT: uxth r[[OLDX:[0-9]+]], r[[OLD]]
1064; CHECK-NEXT: cmp r[[OLDX]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001065; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1066; CHECK-NEXT: BB#2:
1067 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001068; CHECK: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001069; CHECK-NEXT: cmp [[STATUS]], #0
1070; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1071; CHECK-NOT: dmb
1072; CHECK-NOT: mcr
1073
1074; CHECK: mov r0, r[[OLD]]
1075 ret i16 %old
1076}
1077
1078define i32 @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
1079; CHECK-LABEL: test_atomic_cmpxchg_i32:
Tim Northovere94a5182014-03-11 10:48:52 +00001080 %old = cmpxchg i32* @var32, i32 %wanted, i32 %new release monotonic
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001081; CHECK-NOT: dmb
1082; CHECK-NOT: mcr
1083; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
1084; CHECK: movt r[[ADDR]], :upper16:var32
1085
1086; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001087; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001088 ; r0 below is a reasonable guess but could change: it certainly comes into the
1089 ; function there.
1090; CHECK-NEXT: cmp r[[OLD]], r0
1091; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1092; CHECK-NEXT: BB#2:
1093 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001094; CHECK: stlex [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001095; CHECK-NEXT: cmp [[STATUS]], #0
1096; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1097; CHECK-NOT: dmb
1098; CHECK-NOT: mcr
1099
1100; CHECK: mov r0, r[[OLD]]
1101 ret i32 %old
1102}
1103
Tim Northoverc882eb02014-04-03 11:44:58 +00001104define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001105; CHECK-LABEL: test_atomic_cmpxchg_i64:
Tim Northovere94a5182014-03-11 10:48:52 +00001106 %old = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic monotonic
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001107; CHECK-NOT: dmb
1108; CHECK-NOT: mcr
1109; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1110; CHECK: movt r[[ADDR]], :upper16:var64
1111
1112; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001113; CHECK: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001114 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1115 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001116; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
1117; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
1118; CHECK: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001119; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1120; CHECK-NEXT: BB#2:
1121 ; As above, r2, r3 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001122; CHECK: strexd [[STATUS:r[0-9]+]], r2, r3, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001123; CHECK-NEXT: cmp [[STATUS]], #0
1124; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1125; CHECK-NOT: dmb
1126; CHECK-NOT: mcr
1127
Tim Northoverc882eb02014-04-03 11:44:58 +00001128; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
1129 store i64 %old, i64* @var64
1130 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001131}
1132
1133define i8 @test_atomic_load_monotonic_i8() nounwind {
1134; CHECK-LABEL: test_atomic_load_monotonic_i8:
1135 %val = load atomic i8* @var8 monotonic, align 1
1136; CHECK-NOT: dmb
1137; CHECK-NOT: mcr
1138; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1139; CHECK: movt r[[ADDR]], :upper16:var8
1140; CHECK: ldrb r0, [r[[ADDR]]]
1141; CHECK-NOT: dmb
1142; CHECK-NOT: mcr
1143
1144 ret i8 %val
1145}
1146
1147define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
1148; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
1149 %addr_int = add i64 %base, %off
1150 %addr = inttoptr i64 %addr_int to i8*
1151
1152 %val = load atomic i8* %addr monotonic, align 1
1153; CHECK-NOT: dmb
1154; CHECK-NOT: mcr
1155; CHECK: ldrb r0, [r0, r2]
1156; CHECK-NOT: dmb
1157; CHECK-NOT: mcr
1158
1159 ret i8 %val
1160}
1161
1162define i8 @test_atomic_load_acquire_i8() nounwind {
1163; CHECK-LABEL: test_atomic_load_acquire_i8:
1164 %val = load atomic i8* @var8 acquire, align 1
1165; CHECK-NOT: dmb
1166; CHECK-NOT: mcr
1167; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1168; CHECK-NOT: dmb
1169; CHECK-NOT: mcr
1170; CHECK: movt r[[ADDR]], :upper16:var8
1171; CHECK-NOT: dmb
1172; CHECK-NOT: mcr
1173; CHECK: ldab r0, [r[[ADDR]]]
1174; CHECK-NOT: dmb
1175; CHECK-NOT: mcr
1176 ret i8 %val
1177}
1178
1179define i8 @test_atomic_load_seq_cst_i8() nounwind {
1180; CHECK-LABEL: test_atomic_load_seq_cst_i8:
1181 %val = load atomic i8* @var8 seq_cst, align 1
1182; CHECK-NOT: dmb
1183; CHECK-NOT: mcr
1184; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1185; CHECK-NOT: dmb
1186; CHECK-NOT: mcr
1187; CHECK: movt r[[ADDR]], :upper16:var8
1188; CHECK-NOT: dmb
1189; CHECK-NOT: mcr
1190; CHECK: ldab r0, [r[[ADDR]]]
1191; CHECK-NOT: dmb
1192; CHECK-NOT: mcr
1193 ret i8 %val
1194}
1195
1196define i16 @test_atomic_load_monotonic_i16() nounwind {
1197; CHECK-LABEL: test_atomic_load_monotonic_i16:
1198 %val = load atomic i16* @var16 monotonic, align 2
1199; CHECK-NOT: dmb
1200; CHECK-NOT: mcr
1201; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1202; CHECK-NOT: dmb
1203; CHECK-NOT: mcr
1204; CHECK: movt r[[ADDR]], :upper16:var16
1205; CHECK-NOT: dmb
1206; CHECK-NOT: mcr
1207; CHECK: ldrh r0, [r[[ADDR]]]
1208; CHECK-NOT: dmb
1209; CHECK-NOT: mcr
1210
1211 ret i16 %val
1212}
1213
1214define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
1215; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
1216 %addr_int = add i64 %base, %off
1217 %addr = inttoptr i64 %addr_int to i32*
1218
1219 %val = load atomic i32* %addr monotonic, align 4
1220; CHECK-NOT: dmb
1221; CHECK-NOT: mcr
1222; CHECK: ldr r0, [r0, r2]
1223; CHECK-NOT: dmb
1224; CHECK-NOT: mcr
1225
1226 ret i32 %val
1227}
1228
1229define i64 @test_atomic_load_seq_cst_i64() nounwind {
1230; CHECK-LABEL: test_atomic_load_seq_cst_i64:
1231 %val = load atomic i64* @var64 seq_cst, align 8
1232; CHECK-NOT: dmb
1233; CHECK-NOT: mcr
1234; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1235; CHECK-NOT: dmb
1236; CHECK-NOT: mcr
1237; CHECK: movt r[[ADDR]], :upper16:var64
1238; CHECK-NOT: dmb
1239; CHECK-NOT: mcr
1240; CHECK: ldaexd r0, r1, [r[[ADDR]]]
1241; CHECK-NOT: dmb
1242; CHECK-NOT: mcr
1243 ret i64 %val
1244}
1245
1246define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
1247; CHECK-LABEL: test_atomic_store_monotonic_i8:
1248 store atomic i8 %val, i8* @var8 monotonic, align 1
1249; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1250; CHECK: movt r[[ADDR]], :upper16:var8
1251; CHECK: strb r0, [r[[ADDR]]]
1252
1253 ret void
1254}
1255
1256define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
1257; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
1258
1259 %addr_int = add i64 %base, %off
1260 %addr = inttoptr i64 %addr_int to i8*
1261
1262 store atomic i8 %val, i8* %addr monotonic, align 1
1263; CHECK: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp]
1264; CHECK: strb [[VAL]], [r0, r2]
1265
1266 ret void
1267}
1268
1269define void @test_atomic_store_release_i8(i8 %val) nounwind {
1270; CHECK-LABEL: test_atomic_store_release_i8:
1271 store atomic i8 %val, i8* @var8 release, align 1
1272; CHECK-NOT: dmb
1273; CHECK-NOT: mcr
1274; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1275; CHECK-NOT: dmb
1276; CHECK-NOT: mcr
1277; CHECK: movt r[[ADDR]], :upper16:var8
1278; CHECK-NOT: dmb
1279; CHECK-NOT: mcr
1280; CHECK: stlb r0, [r[[ADDR]]]
1281; CHECK-NOT: dmb
1282; CHECK-NOT: mcr
1283 ret void
1284}
1285
1286define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
1287; CHECK-LABEL: test_atomic_store_seq_cst_i8:
1288 store atomic i8 %val, i8* @var8 seq_cst, align 1
1289; CHECK-NOT: dmb
1290; CHECK-NOT: mcr
1291; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1292; CHECK-NOT: dmb
1293; CHECK-NOT: mcr
1294; CHECK: movt r[[ADDR]], :upper16:var8
1295; CHECK-NOT: dmb
1296; CHECK-NOT: mcr
1297; CHECK: stlb r0, [r[[ADDR]]]
1298; CHECK-NOT: dmb
1299; CHECK-NOT: mcr
1300 ret void
1301}
1302
1303define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
1304; CHECK-LABEL: test_atomic_store_monotonic_i16:
1305 store atomic i16 %val, i16* @var16 monotonic, align 2
1306; CHECK-NOT: dmb
1307; CHECK-NOT: mcr
1308; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1309; CHECK-NOT: dmb
1310; CHECK-NOT: mcr
1311; CHECK: movt r[[ADDR]], :upper16:var16
1312; CHECK-NOT: dmb
1313; CHECK-NOT: mcr
1314; CHECK: strh r0, [r[[ADDR]]]
1315; CHECK-NOT: dmb
1316; CHECK-NOT: mcr
1317 ret void
1318}
1319
1320define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
1321; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
1322
1323 %addr_int = add i64 %base, %off
1324 %addr = inttoptr i64 %addr_int to i32*
1325
1326 store atomic i32 %val, i32* %addr monotonic, align 4
1327; CHECK-NOT: dmb
1328; CHECK-NOT: mcr
1329; CHECK: ldr [[VAL:r[0-9]+]], [sp]
1330; CHECK-NOT: dmb
1331; CHECK-NOT: mcr
1332; CHECK: str [[VAL]], [r0, r2]
1333; CHECK-NOT: dmb
1334; CHECK-NOT: mcr
1335
1336 ret void
1337}
1338
1339define void @test_atomic_store_release_i64(i64 %val) nounwind {
1340; CHECK-LABEL: test_atomic_store_release_i64:
1341 store atomic i64 %val, i64* @var64 release, align 8
1342; CHECK-NOT: dmb
1343; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +00001344; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var64
1345; CHECK: movt [[ADDR]], :upper16:var64
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001346
1347; CHECK: .LBB{{[0-9]+}}_1:
1348 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1349 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001350; CHECK: stlexd [[STATUS:r[0-9]+]], r0, r1, {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001351; CHECK-NEXT: cmp [[STATUS]], #0
1352; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1353; CHECK-NOT: dmb
1354; CHECK-NOT: mcr
1355
1356 ret void
1357}
1358
1359define i32 @not.barriers(i32* %var, i1 %cond) {
1360; CHECK-LABEL: not.barriers:
1361 br i1 %cond, label %atomic_ver, label %simple_ver
1362simple_ver:
1363 %oldval = load i32* %var
1364 %newval = add nsw i32 %oldval, -1
1365 store i32 %newval, i32* %var
1366 br label %somewhere
1367atomic_ver:
1368 fence seq_cst
1369 %val = atomicrmw add i32* %var, i32 -1 monotonic
1370 fence seq_cst
1371 br label %somewhere
1372; CHECK: dmb
1373; CHECK: ldrex
1374; CHECK: dmb
1375 ; The key point here is that the second dmb isn't immediately followed by the
1376 ; simple_ver basic block, which LLVM attempted to do when DMB had been marked
1377 ; with isBarrier. For now, look for something that looks like "somewhere".
Tim Northoverc882eb02014-04-03 11:44:58 +00001378; CHECK-NEXT: {{mov|bx}}
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001379somewhere:
1380 %combined = phi i32 [ %val, %atomic_ver ], [ %newval, %simple_ver]
1381 ret i32 %combined
1382}