1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s -check-prefixes=ARM
3; RUN: llc < %s -mtriple=armv7-apple-ios -O0 | FileCheck %s -check-prefix=ARMOPTNONE
4; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s -check-prefix=THUMBTWO
5; RUN: llc < %s -mtriple=thumbv6 | FileCheck %s -check-prefix=THUMBONE
6; RUN: llc < %s -mtriple=armv4 | FileCheck %s -check-prefix=ARMV4
7; RUN: llc < %s -mtriple=armv6 | FileCheck %s -check-prefix=ARMV6
8; RUN: llc < %s -mtriple=thumbv7m | FileCheck %s -check-prefix=THUMBM
9
10define void @test1(i32* %ptr, i32 %val1) {
11; ARM-LABEL: test1:
12; ARM:       @ %bb.0:
13; ARM-NEXT:    dmb ish
14; ARM-NEXT:    str r1, [r0]
15; ARM-NEXT:    dmb ish
16; ARM-NEXT:    bx lr
17;
18; ARMOPTNONE-LABEL: test1:
19; ARMOPTNONE:       @ %bb.0:
20; ARMOPTNONE-NEXT:    dmb ish
21; ARMOPTNONE-NEXT:    str r1, [r0]
22; ARMOPTNONE-NEXT:    dmb ish
23; ARMOPTNONE-NEXT:    bx lr
24;
25; THUMBTWO-LABEL: test1:
26; THUMBTWO:       @ %bb.0:
27; THUMBTWO-NEXT:    dmb ish
28; THUMBTWO-NEXT:    str r1, [r0]
29; THUMBTWO-NEXT:    dmb ish
30; THUMBTWO-NEXT:    bx lr
31;
32; THUMBONE-LABEL: test1:
33; THUMBONE:       @ %bb.0:
34; THUMBONE-NEXT:    push {r7, lr}
35; THUMBONE-NEXT:    bl __sync_lock_test_and_set_4
36; THUMBONE-NEXT:    pop {r7, pc}
37;
38; ARMV4-LABEL: test1:
39; ARMV4:       @ %bb.0:
40; ARMV4-NEXT:    push {r11, lr}
41; ARMV4-NEXT:    mov r2, #5
42; ARMV4-NEXT:    bl __atomic_store_4
43; ARMV4-NEXT:    pop {r11, lr}
44; ARMV4-NEXT:    mov pc, lr
45;
46; ARMV6-LABEL: test1:
47; ARMV6:       @ %bb.0:
48; ARMV6-NEXT:    mov r2, #0
49; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
50; ARMV6-NEXT:    str r1, [r0]
51; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
52; ARMV6-NEXT:    bx lr
53;
54; THUMBM-LABEL: test1:
55; THUMBM:       @ %bb.0:
56; THUMBM-NEXT:    dmb sy
57; THUMBM-NEXT:    str r1, [r0]
58; THUMBM-NEXT:    dmb sy
59; THUMBM-NEXT:    bx lr
60  store atomic i32 %val1, i32* %ptr seq_cst, align 4
61  ret void
62}
63
64define i32 @test2(i32* %ptr) {
65; ARM-LABEL: test2:
66; ARM:       @ %bb.0:
67; ARM-NEXT:    ldr r0, [r0]
68; ARM-NEXT:    dmb ish
69; ARM-NEXT:    bx lr
70;
71; ARMOPTNONE-LABEL: test2:
72; ARMOPTNONE:       @ %bb.0:
73; ARMOPTNONE-NEXT:    ldr r0, [r0]
74; ARMOPTNONE-NEXT:    dmb ish
75; ARMOPTNONE-NEXT:    bx lr
76;
77; THUMBTWO-LABEL: test2:
78; THUMBTWO:       @ %bb.0:
79; THUMBTWO-NEXT:    ldr r0, [r0]
80; THUMBTWO-NEXT:    dmb ish
81; THUMBTWO-NEXT:    bx lr
82;
83; THUMBONE-LABEL: test2:
84; THUMBONE:       @ %bb.0:
85; THUMBONE-NEXT:    push {r7, lr}
86; THUMBONE-NEXT:    movs r1, #0
87; THUMBONE-NEXT:    mov r2, r1
88; THUMBONE-NEXT:    bl __sync_val_compare_and_swap_4
89; THUMBONE-NEXT:    pop {r7, pc}
90;
91; ARMV4-LABEL: test2:
92; ARMV4:       @ %bb.0:
93; ARMV4-NEXT:    push {r11, lr}
94; ARMV4-NEXT:    mov r1, #5
95; ARMV4-NEXT:    bl __atomic_load_4
96; ARMV4-NEXT:    pop {r11, lr}
97; ARMV4-NEXT:    mov pc, lr
98;
99; ARMV6-LABEL: test2:
100; ARMV6:       @ %bb.0:
101; ARMV6-NEXT:    ldr r0, [r0]
102; ARMV6-NEXT:    mov r1, #0
103; ARMV6-NEXT:    mcr p15, #0, r1, c7, c10, #5
104; ARMV6-NEXT:    bx lr
105;
106; THUMBM-LABEL: test2:
107; THUMBM:       @ %bb.0:
108; THUMBM-NEXT:    ldr r0, [r0]
109; THUMBM-NEXT:    dmb sy
110; THUMBM-NEXT:    bx lr
111  %val = load atomic i32, i32* %ptr seq_cst, align 4
112  ret i32 %val
113}
114
115define void @test3(i8* %ptr1, i8* %ptr2) {
116; ARM-LABEL: test3:
117; ARM:       @ %bb.0:
118; ARM-NEXT:    ldrb r0, [r0]
119; ARM-NEXT:    strb r0, [r1]
120; ARM-NEXT:    bx lr
121;
122; ARMOPTNONE-LABEL: test3:
123; ARMOPTNONE:       @ %bb.0:
124; ARMOPTNONE-NEXT:    ldrb r0, [r0]
125; ARMOPTNONE-NEXT:    strb r0, [r1]
126; ARMOPTNONE-NEXT:    bx lr
127;
128; THUMBTWO-LABEL: test3:
129; THUMBTWO:       @ %bb.0:
130; THUMBTWO-NEXT:    ldrb r0, [r0]
131; THUMBTWO-NEXT:    strb r0, [r1]
132; THUMBTWO-NEXT:    bx lr
133;
134; THUMBONE-LABEL: test3:
135; THUMBONE:       @ %bb.0:
136; THUMBONE-NEXT:    ldrb r0, [r0]
137; THUMBONE-NEXT:    strb r0, [r1]
138; THUMBONE-NEXT:    bx lr
139;
140; ARMV4-LABEL: test3:
141; ARMV4:       @ %bb.0:
142; ARMV4-NEXT:    push {r4, lr}
143; ARMV4-NEXT:    mov r4, r1
144; ARMV4-NEXT:    mov r1, #0
145; ARMV4-NEXT:    bl __atomic_load_1
146; ARMV4-NEXT:    mov r1, r0
147; ARMV4-NEXT:    mov r0, r4
148; ARMV4-NEXT:    mov r2, #0
149; ARMV4-NEXT:    bl __atomic_store_1
150; ARMV4-NEXT:    pop {r4, lr}
151; ARMV4-NEXT:    mov pc, lr
152;
153; ARMV6-LABEL: test3:
154; ARMV6:       @ %bb.0:
155; ARMV6-NEXT:    ldrb r0, [r0]
156; ARMV6-NEXT:    strb r0, [r1]
157; ARMV6-NEXT:    bx lr
158;
159; THUMBM-LABEL: test3:
160; THUMBM:       @ %bb.0:
161; THUMBM-NEXT:    ldrb r0, [r0]
162; THUMBM-NEXT:    strb r0, [r1]
163; THUMBM-NEXT:    bx lr
164
165
166
167  %val = load atomic i8, i8* %ptr1 unordered, align 1
168  store atomic i8 %val, i8* %ptr2 unordered, align 1
169  ret void
170}
171
172define void @test4(i8* %ptr1, i8* %ptr2) {
173; ARM-LABEL: test4:
174; ARM:       @ %bb.0:
175; ARM-NEXT:    ldrb r0, [r0]
176; ARM-NEXT:    dmb ish
177; ARM-NEXT:    strb r0, [r1]
178; ARM-NEXT:    dmb ish
179; ARM-NEXT:    bx lr
180;
181; ARMOPTNONE-LABEL: test4:
182; ARMOPTNONE:       @ %bb.0:
183; ARMOPTNONE-NEXT:    ldrb r0, [r0]
184; ARMOPTNONE-NEXT:    dmb ish
185; ARMOPTNONE-NEXT:    dmb ish
186; ARMOPTNONE-NEXT:    strb r0, [r1]
187; ARMOPTNONE-NEXT:    dmb ish
188; ARMOPTNONE-NEXT:    bx lr
189;
190; THUMBTWO-LABEL: test4:
191; THUMBTWO:       @ %bb.0:
192; THUMBTWO-NEXT:    ldrb r0, [r0]
193; THUMBTWO-NEXT:    dmb ish
194; THUMBTWO-NEXT:    dmb ish
195; THUMBTWO-NEXT:    strb r0, [r1]
196; THUMBTWO-NEXT:    dmb ish
197; THUMBTWO-NEXT:    bx lr
198;
199; THUMBONE-LABEL: test4:
200; THUMBONE:       @ %bb.0:
201; THUMBONE-NEXT:    push {r4, lr}
202; THUMBONE-NEXT:    mov r4, r1
203; THUMBONE-NEXT:    movs r1, #0
204; THUMBONE-NEXT:    mov r2, r1
205; THUMBONE-NEXT:    bl __sync_val_compare_and_swap_1
206; THUMBONE-NEXT:    mov r1, r0
207; THUMBONE-NEXT:    mov r0, r4
208; THUMBONE-NEXT:    bl __sync_lock_test_and_set_1
209; THUMBONE-NEXT:    pop {r4, pc}
210;
211; ARMV4-LABEL: test4:
212; ARMV4:       @ %bb.0:
213; ARMV4-NEXT:    push {r4, lr}
214; ARMV4-NEXT:    mov r4, r1
215; ARMV4-NEXT:    mov r1, #5
216; ARMV4-NEXT:    bl __atomic_load_1
217; ARMV4-NEXT:    mov r1, r0
218; ARMV4-NEXT:    mov r0, r4
219; ARMV4-NEXT:    mov r2, #5
220; ARMV4-NEXT:    bl __atomic_store_1
221; ARMV4-NEXT:    pop {r4, lr}
222; ARMV4-NEXT:    mov pc, lr
223;
224; ARMV6-LABEL: test4:
225; ARMV6:       @ %bb.0:
226; ARMV6-NEXT:    mov r2, #0
227; ARMV6-NEXT:    ldrb r0, [r0]
228; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
229; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
230; ARMV6-NEXT:    strb r0, [r1]
231; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
232; ARMV6-NEXT:    bx lr
233;
234; THUMBM-LABEL: test4:
235; THUMBM:       @ %bb.0:
236; THUMBM-NEXT:    ldrb r0, [r0]
237; THUMBM-NEXT:    dmb sy
238; THUMBM-NEXT:    dmb sy
239; THUMBM-NEXT:    strb r0, [r1]
240; THUMBM-NEXT:    dmb sy
241; THUMBM-NEXT:    bx lr
242  %val = load atomic i8, i8* %ptr1 seq_cst, align 1
243  store atomic i8 %val, i8* %ptr2 seq_cst, align 1
244  ret void
245}
246
247define i64 @test_old_load_64bit(i64* %p) {
248; ARM-LABEL: test_old_load_64bit:
249; ARM:       @ %bb.0:
250; ARM-NEXT:    ldrexd r0, r1, [r0]
251; ARM-NEXT:    clrex
252; ARM-NEXT:    dmb ish
253; ARM-NEXT:    bx lr
254;
255; ARMOPTNONE-LABEL: test_old_load_64bit:
256; ARMOPTNONE:       @ %bb.0:
257; ARMOPTNONE-NEXT:    ldrexd r2, r3, [r0]
258; ARMOPTNONE-NEXT:    mov r0, r2
259; ARMOPTNONE-NEXT:    mov r1, r3
260; ARMOPTNONE-NEXT:    clrex
261; ARMOPTNONE-NEXT:    dmb ish
262; ARMOPTNONE-NEXT:    bx lr
263;
264; THUMBTWO-LABEL: test_old_load_64bit:
265; THUMBTWO:       @ %bb.0:
266; THUMBTWO-NEXT:    ldrexd r0, r1, [r0]
267; THUMBTWO-NEXT:    clrex
268; THUMBTWO-NEXT:    dmb ish
269; THUMBTWO-NEXT:    bx lr
270;
271; THUMBONE-LABEL: test_old_load_64bit:
272; THUMBONE:       @ %bb.0:
273; THUMBONE-NEXT:    push {r7, lr}
274; THUMBONE-NEXT:    sub sp, #8
275; THUMBONE-NEXT:    movs r2, #0
276; THUMBONE-NEXT:    str r2, [sp]
277; THUMBONE-NEXT:    str r2, [sp, #4]
278; THUMBONE-NEXT:    mov r3, r2
279; THUMBONE-NEXT:    bl __sync_val_compare_and_swap_8
280; THUMBONE-NEXT:    add sp, #8
281; THUMBONE-NEXT:    pop {r7, pc}
282;
283; ARMV4-LABEL: test_old_load_64bit:
284; ARMV4:       @ %bb.0:
285; ARMV4-NEXT:    push {r11, lr}
286; ARMV4-NEXT:    mov r1, #5
287; ARMV4-NEXT:    bl __atomic_load_8
288; ARMV4-NEXT:    pop {r11, lr}
289; ARMV4-NEXT:    mov pc, lr
290;
291; ARMV6-LABEL: test_old_load_64bit:
292; ARMV6:       @ %bb.0:
293; ARMV6-NEXT:    ldrexd r0, r1, [r0]
294; ARMV6-NEXT:    mov r2, #0
295; ARMV6-NEXT:    mcr p15, #0, r2, c7, c10, #5
296; ARMV6-NEXT:    bx lr
297;
298; THUMBM-LABEL: test_old_load_64bit:
299; THUMBM:       @ %bb.0:
300; THUMBM-NEXT:    push {r7, lr}
301; THUMBM-NEXT:    movs r1, #5
302; THUMBM-NEXT:    bl __atomic_load_8
303; THUMBM-NEXT:    pop {r7, pc}
304  %1 = load atomic i64, i64* %p seq_cst, align 8
305  ret i64 %1
306}
307
308define void @test_old_store_64bit(i64* %p, i64 %v) {
309; ARM-LABEL: test_old_store_64bit:
310; ARM:       @ %bb.0:
311; ARM-NEXT:    push {r4, r5, lr}
312; ARM-NEXT:    mov r3, r2
313; ARM-NEXT:    dmb ish
314; ARM-NEXT:    mov r2, r1
315; ARM-NEXT:  LBB5_1: @ %atomicrmw.start
316; ARM-NEXT:    @ =>This Inner Loop Header: Depth=1
317; ARM-NEXT:    ldrexd r4, r5, [r0]
318; ARM-NEXT:    strexd r1, r2, r3, [r0]
319; ARM-NEXT:    cmp r1, #0
320; ARM-NEXT:    bne LBB5_1
321; ARM-NEXT:  @ %bb.2: @ %atomicrmw.end
322; ARM-NEXT:    dmb ish
323; ARM-NEXT:    pop {r4, r5, pc}
324;
325; ARMOPTNONE-LABEL: test_old_store_64bit:
326; ARMOPTNONE:       @ %bb.0:
327; ARMOPTNONE-NEXT:    push {r4, r5, r7, lr}
328; ARMOPTNONE-NEXT:    add r7, sp, #8
329; ARMOPTNONE-NEXT:    push {r8, r10, r11}
330; ARMOPTNONE-NEXT:    sub sp, sp, #20
331; ARMOPTNONE-NEXT:    str r0, [sp] @ 4-byte Spill
332; ARMOPTNONE-NEXT:    str r2, [sp, #4] @ 4-byte Spill
333; ARMOPTNONE-NEXT:    str r1, [sp, #8] @ 4-byte Spill
334; ARMOPTNONE-NEXT:    dmb ish
335; ARMOPTNONE-NEXT:    ldr r1, [r0]
336; ARMOPTNONE-NEXT:    ldr r0, [r0, #4]
337; ARMOPTNONE-NEXT:    str r1, [sp, #12] @ 4-byte Spill
338; ARMOPTNONE-NEXT:    str r0, [sp, #16] @ 4-byte Spill
339; ARMOPTNONE-NEXT:    b LBB5_1
340; ARMOPTNONE-NEXT:  LBB5_1: @ %atomicrmw.start
341; ARMOPTNONE-NEXT:    @ =>This Loop Header: Depth=1
342; ARMOPTNONE-NEXT:    @ Child Loop BB5_2 Depth 2
343; ARMOPTNONE-NEXT:    ldr r1, [sp, #16] @ 4-byte Reload
344; ARMOPTNONE-NEXT:    ldr r2, [sp, #12] @ 4-byte Reload
345; ARMOPTNONE-NEXT:    ldr r3, [sp] @ 4-byte Reload
346; ARMOPTNONE-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
347; ARMOPTNONE-NEXT:    ldr r10, [sp, #8] @ 4-byte Reload
348; ARMOPTNONE-NEXT:    @ kill: def $r10 killed $r10 def $r10_r11
349; ARMOPTNONE-NEXT:    mov r11, r0
350; ARMOPTNONE-NEXT:    mov r8, r2
351; ARMOPTNONE-NEXT:    mov r9, r1
352; ARMOPTNONE-NEXT:  LBB5_2: @ %atomicrmw.start
353; ARMOPTNONE-NEXT:    @ Parent Loop BB5_1 Depth=1
354; ARMOPTNONE-NEXT:    @ => This Inner Loop Header: Depth=2
355; ARMOPTNONE-NEXT:    ldrexd r4, r5, [r3]
356; ARMOPTNONE-NEXT:    cmp r4, r8
357; ARMOPTNONE-NEXT:    cmpeq r5, r9
358; ARMOPTNONE-NEXT:    bne LBB5_4
359; ARMOPTNONE-NEXT:  @ %bb.3: @ %atomicrmw.start
360; ARMOPTNONE-NEXT:    @ in Loop: Header=BB5_2 Depth=2
361; ARMOPTNONE-NEXT:    strexd r0, r10, r11, [r3]
362; ARMOPTNONE-NEXT:    cmp r0, #0
363; ARMOPTNONE-NEXT:    bne LBB5_2
364; ARMOPTNONE-NEXT:  LBB5_4: @ %atomicrmw.start
365; ARMOPTNONE-NEXT:    @ in Loop: Header=BB5_1 Depth=1
366; ARMOPTNONE-NEXT:    mov r0, r5
367; ARMOPTNONE-NEXT:    eor r3, r0, r1
368; ARMOPTNONE-NEXT:    mov r1, r4
369; ARMOPTNONE-NEXT:    eor r2, r1, r2
370; ARMOPTNONE-NEXT:    orr r2, r2, r3
371; ARMOPTNONE-NEXT:    cmp r2, #0
372; ARMOPTNONE-NEXT:    str r1, [sp, #12] @ 4-byte Spill
373; ARMOPTNONE-NEXT:    str r0, [sp, #16] @ 4-byte Spill
374; ARMOPTNONE-NEXT:    bne LBB5_1
375; ARMOPTNONE-NEXT:    b LBB5_5
376; ARMOPTNONE-NEXT:  LBB5_5: @ %atomicrmw.end
377; ARMOPTNONE-NEXT:    dmb ish
378; ARMOPTNONE-NEXT:    sub sp, r7, #20
379; ARMOPTNONE-NEXT:    pop {r8, r10, r11}
380; ARMOPTNONE-NEXT:    pop {r4, r5, r7, pc}
381;
382; THUMBTWO-LABEL: test_old_store_64bit:
383; THUMBTWO:       @ %bb.0:
384; THUMBTWO-NEXT:    dmb ish
385; THUMBTWO-NEXT:  LBB5_1: @ %atomicrmw.start
386; THUMBTWO-NEXT:    @ =>This Inner Loop Header: Depth=1
387; THUMBTWO-NEXT:    ldrexd r3, r9, [r0]
388; THUMBTWO-NEXT:    strexd r3, r1, r2, [r0]
389; THUMBTWO-NEXT:    cmp r3, #0
390; THUMBTWO-NEXT:    bne LBB5_1
391; THUMBTWO-NEXT:  @ %bb.2: @ %atomicrmw.end
392; THUMBTWO-NEXT:    dmb ish
393; THUMBTWO-NEXT:    bx lr
394;
395; THUMBONE-LABEL: test_old_store_64bit:
396; THUMBONE:       @ %bb.0:
397; THUMBONE-NEXT:    push {r7, lr}
398; THUMBONE-NEXT:    bl __sync_lock_test_and_set_8
399; THUMBONE-NEXT:    pop {r7, pc}
400;
401; ARMV4-LABEL: test_old_store_64bit:
402; ARMV4:       @ %bb.0:
403; ARMV4-NEXT:    push {r11, lr}
404; ARMV4-NEXT:    sub sp, sp, #8
405; ARMV4-NEXT:    mov r1, #5
406; ARMV4-NEXT:    str r1, [sp]
407; ARMV4-NEXT:    bl __atomic_store_8
408; ARMV4-NEXT:    add sp, sp, #8
409; ARMV4-NEXT:    pop {r11, lr}
410; ARMV4-NEXT:    mov pc, lr
411;
412; ARMV6-LABEL: test_old_store_64bit:
413; ARMV6:       @ %bb.0:
414; ARMV6-NEXT:    push {r4, r5, r11, lr}
415; ARMV6-NEXT:    @ kill: def $r3 killed $r3 killed $r2_r3 def $r2_r3
416; ARMV6-NEXT:    mov r1, #0
417; ARMV6-NEXT:    @ kill: def $r2 killed $r2 killed $r2_r3 def $r2_r3
418; ARMV6-NEXT:    mcr p15, #0, r1, c7, c10, #5
419; ARMV6-NEXT:  .LBB5_1: @ %atomicrmw.start
420; ARMV6-NEXT:    @ =>This Inner Loop Header: Depth=1
421; ARMV6-NEXT:    ldrexd r4, r5, [r0]
422; ARMV6-NEXT:    strexd r1, r2, r3, [r0]
423; ARMV6-NEXT:    cmp r1, #0
424; ARMV6-NEXT:    bne .LBB5_1
425; ARMV6-NEXT:  @ %bb.2: @ %atomicrmw.end
426; ARMV6-NEXT:    mov r0, #0
427; ARMV6-NEXT:    mcr p15, #0, r0, c7, c10, #5
428; ARMV6-NEXT:    pop {r4, r5, r11, pc}
429;
430; THUMBM-LABEL: test_old_store_64bit:
431; THUMBM:       @ %bb.0:
432; THUMBM-NEXT:    push {r7, lr}
433; THUMBM-NEXT:    sub sp, #8
434; THUMBM-NEXT:    movs r1, #5
435; THUMBM-NEXT:    str r1, [sp]
436; THUMBM-NEXT:    bl __atomic_store_8
437; THUMBM-NEXT:    add sp, #8
438; THUMBM-NEXT:    pop {r7, pc}
439  store atomic i64 %v, i64* %p seq_cst, align 8
440  ret void
441}
442