blob: 7922e2220309f340b6a93ec2af7e412a99c74a2f [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 Northover01b4aa92014-04-03 15:10:35 +0000808; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
809; CHECK-NEXT: cmp r[[OLD]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000810; 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 Northover01b4aa92014-04-03 15:10:35 +0000834; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
835; CHECK-NEXT: cmp r[[OLD]], r0
Tim Northoverc882eb02014-04-03 11:44:58 +0000836; 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 Northover01b4aa92014-04-03 15:10:35 +0000922; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
923; CHECK-NEXT: cmp r[[OLD]], 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 Northover01b4aa92014-04-03 15:10:35 +0000948; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
949; CHECK-NEXT: cmp r[[OLD]], 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 Northover01b4aa92014-04-03 15:10:35 +00001036; CHECK-NEXT: cmp r[[OLD]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001037; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1038; CHECK-NEXT: BB#2:
1039 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001040; CHECK: strexb [[STATUS:r[0-9]+]], r1, {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001041; CHECK-NEXT: cmp [[STATUS]], #0
1042; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1043; CHECK-NOT: dmb
1044; CHECK-NOT: mcr
1045
1046; CHECK: mov r0, r[[OLD]]
1047 ret i8 %old
1048}
1049
Tim Northoverc882eb02014-04-03 11:44:58 +00001050define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001051; CHECK-LABEL: test_atomic_cmpxchg_i16:
Tim Northovere94a5182014-03-11 10:48:52 +00001052 %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst seq_cst
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001053; CHECK-NOT: dmb
1054; CHECK-NOT: mcr
1055; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1056; CHECK: movt r[[ADDR]], :upper16:var16
1057
1058; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001059; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001060 ; r0 below is a reasonable guess but could change: it certainly comes into the
1061 ; function there.
Tim Northover01b4aa92014-04-03 15:10:35 +00001062; CHECK-NEXT: cmp r[[OLD]], r0
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001063; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1064; CHECK-NEXT: BB#2:
1065 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001066; CHECK: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001067; CHECK-NEXT: cmp [[STATUS]], #0
1068; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1069; CHECK-NOT: dmb
1070; CHECK-NOT: mcr
1071
1072; CHECK: mov r0, r[[OLD]]
1073 ret i16 %old
1074}
1075
Tim Northover70450c52014-04-03 13:06:54 +00001076define void @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001077; CHECK-LABEL: test_atomic_cmpxchg_i32:
Tim Northovere94a5182014-03-11 10:48:52 +00001078 %old = cmpxchg i32* @var32, i32 %wanted, i32 %new release monotonic
Tim Northover70450c52014-04-03 13:06:54 +00001079 store i32 %old, i32* @var32
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001080; CHECK-NOT: dmb
1081; CHECK-NOT: mcr
1082; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
1083; CHECK: movt r[[ADDR]], :upper16:var32
1084
1085; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001086; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001087 ; r0 below is a reasonable guess but could change: it certainly comes into the
1088 ; function there.
1089; CHECK-NEXT: cmp r[[OLD]], r0
1090; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1091; CHECK-NEXT: BB#2:
1092 ; As above, r1 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001093; CHECK: stlex [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001094; CHECK-NEXT: cmp [[STATUS]], #0
1095; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1096; CHECK-NOT: dmb
1097; CHECK-NOT: mcr
1098
Tim Northover70450c52014-04-03 13:06:54 +00001099; CHECK: str{{(.w)?}} r[[OLD]],
1100 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001101}
1102
Tim Northoverc882eb02014-04-03 11:44:58 +00001103define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001104; CHECK-LABEL: test_atomic_cmpxchg_i64:
Tim Northovere94a5182014-03-11 10:48:52 +00001105 %old = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic monotonic
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001106; CHECK-NOT: dmb
1107; CHECK-NOT: mcr
1108; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1109; CHECK: movt r[[ADDR]], :upper16:var64
1110
1111; CHECK: .LBB{{[0-9]+}}_1:
Tim Northoverc882eb02014-04-03 11:44:58 +00001112; CHECK: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001113 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1114 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001115; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
1116; CHECK-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
1117; CHECK: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001118; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1119; CHECK-NEXT: BB#2:
1120 ; As above, r2, r3 is a reasonable guess.
Tim Northoverc882eb02014-04-03 11:44:58 +00001121; CHECK: strexd [[STATUS:r[0-9]+]], r2, r3, [r[[ADDR]]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001122; CHECK-NEXT: cmp [[STATUS]], #0
1123; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1124; CHECK-NOT: dmb
1125; CHECK-NOT: mcr
1126
Tim Northoverc882eb02014-04-03 11:44:58 +00001127; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
1128 store i64 %old, i64* @var64
1129 ret void
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001130}
1131
1132define i8 @test_atomic_load_monotonic_i8() nounwind {
1133; CHECK-LABEL: test_atomic_load_monotonic_i8:
1134 %val = load atomic i8* @var8 monotonic, align 1
1135; CHECK-NOT: dmb
1136; CHECK-NOT: mcr
1137; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1138; CHECK: movt r[[ADDR]], :upper16:var8
1139; CHECK: ldrb r0, [r[[ADDR]]]
1140; CHECK-NOT: dmb
1141; CHECK-NOT: mcr
1142
1143 ret i8 %val
1144}
1145
1146define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
1147; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
1148 %addr_int = add i64 %base, %off
1149 %addr = inttoptr i64 %addr_int to i8*
1150
1151 %val = load atomic i8* %addr monotonic, align 1
1152; CHECK-NOT: dmb
1153; CHECK-NOT: mcr
1154; CHECK: ldrb r0, [r0, r2]
1155; CHECK-NOT: dmb
1156; CHECK-NOT: mcr
1157
1158 ret i8 %val
1159}
1160
1161define i8 @test_atomic_load_acquire_i8() nounwind {
1162; CHECK-LABEL: test_atomic_load_acquire_i8:
1163 %val = load atomic i8* @var8 acquire, align 1
1164; CHECK-NOT: dmb
1165; CHECK-NOT: mcr
1166; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1167; CHECK-NOT: dmb
1168; CHECK-NOT: mcr
1169; CHECK: movt r[[ADDR]], :upper16:var8
1170; CHECK-NOT: dmb
1171; CHECK-NOT: mcr
1172; CHECK: ldab r0, [r[[ADDR]]]
1173; CHECK-NOT: dmb
1174; CHECK-NOT: mcr
1175 ret i8 %val
1176}
1177
1178define i8 @test_atomic_load_seq_cst_i8() nounwind {
1179; CHECK-LABEL: test_atomic_load_seq_cst_i8:
1180 %val = load atomic i8* @var8 seq_cst, align 1
1181; CHECK-NOT: dmb
1182; CHECK-NOT: mcr
1183; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1184; CHECK-NOT: dmb
1185; CHECK-NOT: mcr
1186; CHECK: movt r[[ADDR]], :upper16:var8
1187; CHECK-NOT: dmb
1188; CHECK-NOT: mcr
1189; CHECK: ldab r0, [r[[ADDR]]]
1190; CHECK-NOT: dmb
1191; CHECK-NOT: mcr
1192 ret i8 %val
1193}
1194
1195define i16 @test_atomic_load_monotonic_i16() nounwind {
1196; CHECK-LABEL: test_atomic_load_monotonic_i16:
1197 %val = load atomic i16* @var16 monotonic, align 2
1198; CHECK-NOT: dmb
1199; CHECK-NOT: mcr
1200; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1201; CHECK-NOT: dmb
1202; CHECK-NOT: mcr
1203; CHECK: movt r[[ADDR]], :upper16:var16
1204; CHECK-NOT: dmb
1205; CHECK-NOT: mcr
1206; CHECK: ldrh r0, [r[[ADDR]]]
1207; CHECK-NOT: dmb
1208; CHECK-NOT: mcr
1209
1210 ret i16 %val
1211}
1212
1213define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
1214; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
1215 %addr_int = add i64 %base, %off
1216 %addr = inttoptr i64 %addr_int to i32*
1217
1218 %val = load atomic i32* %addr monotonic, align 4
1219; CHECK-NOT: dmb
1220; CHECK-NOT: mcr
1221; CHECK: ldr r0, [r0, r2]
1222; CHECK-NOT: dmb
1223; CHECK-NOT: mcr
1224
1225 ret i32 %val
1226}
1227
1228define i64 @test_atomic_load_seq_cst_i64() nounwind {
1229; CHECK-LABEL: test_atomic_load_seq_cst_i64:
1230 %val = load atomic i64* @var64 seq_cst, align 8
1231; CHECK-NOT: dmb
1232; CHECK-NOT: mcr
1233; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1234; CHECK-NOT: dmb
1235; CHECK-NOT: mcr
1236; CHECK: movt r[[ADDR]], :upper16:var64
1237; CHECK-NOT: dmb
1238; CHECK-NOT: mcr
1239; CHECK: ldaexd r0, r1, [r[[ADDR]]]
1240; CHECK-NOT: dmb
1241; CHECK-NOT: mcr
1242 ret i64 %val
1243}
1244
1245define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
1246; CHECK-LABEL: test_atomic_store_monotonic_i8:
1247 store atomic i8 %val, i8* @var8 monotonic, align 1
1248; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1249; CHECK: movt r[[ADDR]], :upper16:var8
1250; CHECK: strb r0, [r[[ADDR]]]
1251
1252 ret void
1253}
1254
1255define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
1256; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
1257
1258 %addr_int = add i64 %base, %off
1259 %addr = inttoptr i64 %addr_int to i8*
1260
1261 store atomic i8 %val, i8* %addr monotonic, align 1
1262; CHECK: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp]
1263; CHECK: strb [[VAL]], [r0, r2]
1264
1265 ret void
1266}
1267
1268define void @test_atomic_store_release_i8(i8 %val) nounwind {
1269; CHECK-LABEL: test_atomic_store_release_i8:
1270 store atomic i8 %val, i8* @var8 release, align 1
1271; CHECK-NOT: dmb
1272; CHECK-NOT: mcr
1273; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1274; CHECK-NOT: dmb
1275; CHECK-NOT: mcr
1276; CHECK: movt r[[ADDR]], :upper16:var8
1277; CHECK-NOT: dmb
1278; CHECK-NOT: mcr
1279; CHECK: stlb r0, [r[[ADDR]]]
1280; CHECK-NOT: dmb
1281; CHECK-NOT: mcr
1282 ret void
1283}
1284
1285define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
1286; CHECK-LABEL: test_atomic_store_seq_cst_i8:
1287 store atomic i8 %val, i8* @var8 seq_cst, align 1
1288; CHECK-NOT: dmb
1289; CHECK-NOT: mcr
1290; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1291; CHECK-NOT: dmb
1292; CHECK-NOT: mcr
1293; CHECK: movt r[[ADDR]], :upper16:var8
1294; CHECK-NOT: dmb
1295; CHECK-NOT: mcr
1296; CHECK: stlb r0, [r[[ADDR]]]
1297; CHECK-NOT: dmb
1298; CHECK-NOT: mcr
1299 ret void
1300}
1301
1302define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
1303; CHECK-LABEL: test_atomic_store_monotonic_i16:
1304 store atomic i16 %val, i16* @var16 monotonic, align 2
1305; CHECK-NOT: dmb
1306; CHECK-NOT: mcr
1307; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1308; CHECK-NOT: dmb
1309; CHECK-NOT: mcr
1310; CHECK: movt r[[ADDR]], :upper16:var16
1311; CHECK-NOT: dmb
1312; CHECK-NOT: mcr
1313; CHECK: strh r0, [r[[ADDR]]]
1314; CHECK-NOT: dmb
1315; CHECK-NOT: mcr
1316 ret void
1317}
1318
1319define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
1320; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
1321
1322 %addr_int = add i64 %base, %off
1323 %addr = inttoptr i64 %addr_int to i32*
1324
1325 store atomic i32 %val, i32* %addr monotonic, align 4
1326; CHECK-NOT: dmb
1327; CHECK-NOT: mcr
1328; CHECK: ldr [[VAL:r[0-9]+]], [sp]
1329; CHECK-NOT: dmb
1330; CHECK-NOT: mcr
1331; CHECK: str [[VAL]], [r0, r2]
1332; CHECK-NOT: dmb
1333; CHECK-NOT: mcr
1334
1335 ret void
1336}
1337
1338define void @test_atomic_store_release_i64(i64 %val) nounwind {
1339; CHECK-LABEL: test_atomic_store_release_i64:
1340 store atomic i64 %val, i64* @var64 release, align 8
1341; CHECK-NOT: dmb
1342; CHECK-NOT: mcr
Tim Northoverc882eb02014-04-03 11:44:58 +00001343; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var64
1344; CHECK: movt [[ADDR]], :upper16:var64
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001345
1346; CHECK: .LBB{{[0-9]+}}_1:
1347 ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1348 ; function there.
Tim Northoverc882eb02014-04-03 11:44:58 +00001349; CHECK: stlexd [[STATUS:r[0-9]+]], r0, r1, {{.*}}[[ADDR]]
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001350; CHECK-NEXT: cmp [[STATUS]], #0
1351; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1352; CHECK-NOT: dmb
1353; CHECK-NOT: mcr
1354
1355 ret void
1356}
1357
1358define i32 @not.barriers(i32* %var, i1 %cond) {
1359; CHECK-LABEL: not.barriers:
1360 br i1 %cond, label %atomic_ver, label %simple_ver
1361simple_ver:
1362 %oldval = load i32* %var
1363 %newval = add nsw i32 %oldval, -1
1364 store i32 %newval, i32* %var
1365 br label %somewhere
1366atomic_ver:
1367 fence seq_cst
1368 %val = atomicrmw add i32* %var, i32 -1 monotonic
1369 fence seq_cst
1370 br label %somewhere
1371; CHECK: dmb
1372; CHECK: ldrex
1373; CHECK: dmb
1374 ; The key point here is that the second dmb isn't immediately followed by the
1375 ; simple_ver basic block, which LLVM attempted to do when DMB had been marked
1376 ; with isBarrier. For now, look for something that looks like "somewhere".
Tim Northoverc882eb02014-04-03 11:44:58 +00001377; CHECK-NEXT: {{mov|bx}}
Amara Emersonb4ad2f32013-09-26 12:22:36 +00001378somewhere:
1379 %combined = phi i32 [ %val, %atomic_ver ], [ %newval, %simple_ver]
1380 ret i32 %combined
1381}