xref: /llvm-project/llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll (revision dc84eeb62bf31b195beff823ace563e7fc95d00f)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s --check-prefixes=CHECK,NO-ATOMIC32
3; RUN: llc -mtriple=thumbv6m-none-eabi -mattr=+atomics-32 < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC32
4
5define i8 @load8(ptr %p) {
6; NO-ATOMIC32-LABEL: load8:
7; NO-ATOMIC32:       @ %bb.0:
8; NO-ATOMIC32-NEXT:    .save {r7, lr}
9; NO-ATOMIC32-NEXT:    push {r7, lr}
10; NO-ATOMIC32-NEXT:    movs r1, #5
11; NO-ATOMIC32-NEXT:    bl __atomic_load_1
12; NO-ATOMIC32-NEXT:    pop {r7, pc}
13;
14; ATOMIC32-LABEL: load8:
15; ATOMIC32:       @ %bb.0:
16; ATOMIC32-NEXT:    ldrb r0, [r0]
17; ATOMIC32-NEXT:    dmb sy
18; ATOMIC32-NEXT:    bx lr
19  %v = load atomic i8, ptr %p seq_cst, align 1
20  ret i8 %v
21}
22
23define void @store8(ptr %p) {
24; NO-ATOMIC32-LABEL: store8:
25; NO-ATOMIC32:       @ %bb.0:
26; NO-ATOMIC32-NEXT:    .save {r7, lr}
27; NO-ATOMIC32-NEXT:    push {r7, lr}
28; NO-ATOMIC32-NEXT:    movs r1, #0
29; NO-ATOMIC32-NEXT:    movs r2, #5
30; NO-ATOMIC32-NEXT:    bl __atomic_store_1
31; NO-ATOMIC32-NEXT:    pop {r7, pc}
32;
33; ATOMIC32-LABEL: store8:
34; ATOMIC32:       @ %bb.0:
35; ATOMIC32-NEXT:    dmb sy
36; ATOMIC32-NEXT:    movs r1, #0
37; ATOMIC32-NEXT:    strb r1, [r0]
38; ATOMIC32-NEXT:    dmb sy
39; ATOMIC32-NEXT:    bx lr
40  store atomic i8 0, ptr %p seq_cst, align 1
41  ret void
42}
43
44define i8 @rmw8(ptr %p) {
45; NO-ATOMIC32-LABEL: rmw8:
46; NO-ATOMIC32:       @ %bb.0:
47; NO-ATOMIC32-NEXT:    .save {r7, lr}
48; NO-ATOMIC32-NEXT:    push {r7, lr}
49; NO-ATOMIC32-NEXT:    movs r1, #1
50; NO-ATOMIC32-NEXT:    movs r2, #5
51; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_1
52; NO-ATOMIC32-NEXT:    pop {r7, pc}
53;
54; ATOMIC32-LABEL: rmw8:
55; ATOMIC32:       @ %bb.0:
56; ATOMIC32-NEXT:    .save {r7, lr}
57; ATOMIC32-NEXT:    push {r7, lr}
58; ATOMIC32-NEXT:    dmb sy
59; ATOMIC32-NEXT:    movs r1, #1
60; ATOMIC32-NEXT:    bl __sync_fetch_and_add_1
61; ATOMIC32-NEXT:    dmb sy
62; ATOMIC32-NEXT:    pop {r7, pc}
63  %v = atomicrmw add ptr %p, i8 1 seq_cst, align 1
64  ret i8 %v
65}
66
67define i8 @cmpxchg8(ptr %p) {
68; NO-ATOMIC32-LABEL: cmpxchg8:
69; NO-ATOMIC32:       @ %bb.0:
70; NO-ATOMIC32-NEXT:    .save {r7, lr}
71; NO-ATOMIC32-NEXT:    push {r7, lr}
72; NO-ATOMIC32-NEXT:    .pad #8
73; NO-ATOMIC32-NEXT:    sub sp, #8
74; NO-ATOMIC32-NEXT:    add r1, sp, #4
75; NO-ATOMIC32-NEXT:    movs r2, #0
76; NO-ATOMIC32-NEXT:    strb r2, [r1]
77; NO-ATOMIC32-NEXT:    movs r3, #5
78; NO-ATOMIC32-NEXT:    str r3, [sp]
79; NO-ATOMIC32-NEXT:    movs r2, #1
80; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_1
81; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
82; NO-ATOMIC32-NEXT:    add sp, #8
83; NO-ATOMIC32-NEXT:    pop {r7, pc}
84;
85; ATOMIC32-LABEL: cmpxchg8:
86; ATOMIC32:       @ %bb.0:
87; ATOMIC32-NEXT:    .save {r7, lr}
88; ATOMIC32-NEXT:    push {r7, lr}
89; ATOMIC32-NEXT:    dmb sy
90; ATOMIC32-NEXT:    movs r1, #0
91; ATOMIC32-NEXT:    movs r2, #1
92; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_1
93; ATOMIC32-NEXT:    dmb sy
94; ATOMIC32-NEXT:    pop {r7, pc}
95  %res = cmpxchg ptr %p, i8 0, i8 1 seq_cst seq_cst
96  %res.0 = extractvalue { i8, i1 } %res, 0
97  ret i8 %res.0
98}
99
100define i16 @load16(ptr %p) {
101; NO-ATOMIC32-LABEL: load16:
102; NO-ATOMIC32:       @ %bb.0:
103; NO-ATOMIC32-NEXT:    .save {r7, lr}
104; NO-ATOMIC32-NEXT:    push {r7, lr}
105; NO-ATOMIC32-NEXT:    movs r1, #5
106; NO-ATOMIC32-NEXT:    bl __atomic_load_2
107; NO-ATOMIC32-NEXT:    pop {r7, pc}
108;
109; ATOMIC32-LABEL: load16:
110; ATOMIC32:       @ %bb.0:
111; ATOMIC32-NEXT:    ldrh r0, [r0]
112; ATOMIC32-NEXT:    dmb sy
113; ATOMIC32-NEXT:    bx lr
114  %v = load atomic i16, ptr %p seq_cst, align 2
115  ret i16 %v
116}
117
118define void @store16(ptr %p) {
119; NO-ATOMIC32-LABEL: store16:
120; NO-ATOMIC32:       @ %bb.0:
121; NO-ATOMIC32-NEXT:    .save {r7, lr}
122; NO-ATOMIC32-NEXT:    push {r7, lr}
123; NO-ATOMIC32-NEXT:    movs r1, #0
124; NO-ATOMIC32-NEXT:    movs r2, #5
125; NO-ATOMIC32-NEXT:    bl __atomic_store_2
126; NO-ATOMIC32-NEXT:    pop {r7, pc}
127;
128; ATOMIC32-LABEL: store16:
129; ATOMIC32:       @ %bb.0:
130; ATOMIC32-NEXT:    dmb sy
131; ATOMIC32-NEXT:    movs r1, #0
132; ATOMIC32-NEXT:    strh r1, [r0]
133; ATOMIC32-NEXT:    dmb sy
134; ATOMIC32-NEXT:    bx lr
135  store atomic i16 0, ptr %p seq_cst, align 2
136  ret void
137}
138
139define i16 @rmw16(ptr %p) {
140; NO-ATOMIC32-LABEL: rmw16:
141; NO-ATOMIC32:       @ %bb.0:
142; NO-ATOMIC32-NEXT:    .save {r7, lr}
143; NO-ATOMIC32-NEXT:    push {r7, lr}
144; NO-ATOMIC32-NEXT:    movs r1, #1
145; NO-ATOMIC32-NEXT:    movs r2, #5
146; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_2
147; NO-ATOMIC32-NEXT:    pop {r7, pc}
148;
149; ATOMIC32-LABEL: rmw16:
150; ATOMIC32:       @ %bb.0:
151; ATOMIC32-NEXT:    .save {r7, lr}
152; ATOMIC32-NEXT:    push {r7, lr}
153; ATOMIC32-NEXT:    dmb sy
154; ATOMIC32-NEXT:    movs r1, #1
155; ATOMIC32-NEXT:    bl __sync_fetch_and_add_2
156; ATOMIC32-NEXT:    dmb sy
157; ATOMIC32-NEXT:    pop {r7, pc}
158  %v = atomicrmw add ptr %p, i16 1 seq_cst, align 2
159  ret i16 %v
160}
161
162define i16 @cmpxchg16(ptr %p) {
163; NO-ATOMIC32-LABEL: cmpxchg16:
164; NO-ATOMIC32:       @ %bb.0:
165; NO-ATOMIC32-NEXT:    .save {r7, lr}
166; NO-ATOMIC32-NEXT:    push {r7, lr}
167; NO-ATOMIC32-NEXT:    .pad #8
168; NO-ATOMIC32-NEXT:    sub sp, #8
169; NO-ATOMIC32-NEXT:    add r1, sp, #4
170; NO-ATOMIC32-NEXT:    movs r2, #0
171; NO-ATOMIC32-NEXT:    strh r2, [r1]
172; NO-ATOMIC32-NEXT:    movs r3, #5
173; NO-ATOMIC32-NEXT:    str r3, [sp]
174; NO-ATOMIC32-NEXT:    movs r2, #1
175; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_2
176; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
177; NO-ATOMIC32-NEXT:    add sp, #8
178; NO-ATOMIC32-NEXT:    pop {r7, pc}
179;
180; ATOMIC32-LABEL: cmpxchg16:
181; ATOMIC32:       @ %bb.0:
182; ATOMIC32-NEXT:    .save {r7, lr}
183; ATOMIC32-NEXT:    push {r7, lr}
184; ATOMIC32-NEXT:    dmb sy
185; ATOMIC32-NEXT:    movs r1, #0
186; ATOMIC32-NEXT:    movs r2, #1
187; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_2
188; ATOMIC32-NEXT:    dmb sy
189; ATOMIC32-NEXT:    pop {r7, pc}
190  %res = cmpxchg ptr %p, i16 0, i16 1 seq_cst seq_cst
191  %res.0 = extractvalue { i16, i1 } %res, 0
192  ret i16 %res.0
193}
194
195define i32 @load32(ptr %p) {
196; NO-ATOMIC32-LABEL: load32:
197; NO-ATOMIC32:       @ %bb.0:
198; NO-ATOMIC32-NEXT:    .save {r7, lr}
199; NO-ATOMIC32-NEXT:    push {r7, lr}
200; NO-ATOMIC32-NEXT:    movs r1, #5
201; NO-ATOMIC32-NEXT:    bl __atomic_load_4
202; NO-ATOMIC32-NEXT:    pop {r7, pc}
203;
204; ATOMIC32-LABEL: load32:
205; ATOMIC32:       @ %bb.0:
206; ATOMIC32-NEXT:    ldr r0, [r0]
207; ATOMIC32-NEXT:    dmb sy
208; ATOMIC32-NEXT:    bx lr
209  %v = load atomic i32, ptr %p seq_cst, align 4
210  ret i32 %v
211}
212
213define void @store32(ptr %p) {
214; NO-ATOMIC32-LABEL: store32:
215; NO-ATOMIC32:       @ %bb.0:
216; NO-ATOMIC32-NEXT:    .save {r7, lr}
217; NO-ATOMIC32-NEXT:    push {r7, lr}
218; NO-ATOMIC32-NEXT:    movs r1, #0
219; NO-ATOMIC32-NEXT:    movs r2, #5
220; NO-ATOMIC32-NEXT:    bl __atomic_store_4
221; NO-ATOMIC32-NEXT:    pop {r7, pc}
222;
223; ATOMIC32-LABEL: store32:
224; ATOMIC32:       @ %bb.0:
225; ATOMIC32-NEXT:    dmb sy
226; ATOMIC32-NEXT:    movs r1, #0
227; ATOMIC32-NEXT:    str r1, [r0]
228; ATOMIC32-NEXT:    dmb sy
229; ATOMIC32-NEXT:    bx lr
230  store atomic i32 0, ptr %p seq_cst, align 4
231  ret void
232}
233
234define i32 @rmw32(ptr %p) {
235; NO-ATOMIC32-LABEL: rmw32:
236; NO-ATOMIC32:       @ %bb.0:
237; NO-ATOMIC32-NEXT:    .save {r7, lr}
238; NO-ATOMIC32-NEXT:    push {r7, lr}
239; NO-ATOMIC32-NEXT:    movs r1, #1
240; NO-ATOMIC32-NEXT:    movs r2, #5
241; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_4
242; NO-ATOMIC32-NEXT:    pop {r7, pc}
243;
244; ATOMIC32-LABEL: rmw32:
245; ATOMIC32:       @ %bb.0:
246; ATOMIC32-NEXT:    .save {r7, lr}
247; ATOMIC32-NEXT:    push {r7, lr}
248; ATOMIC32-NEXT:    dmb sy
249; ATOMIC32-NEXT:    movs r1, #1
250; ATOMIC32-NEXT:    bl __sync_fetch_and_add_4
251; ATOMIC32-NEXT:    dmb sy
252; ATOMIC32-NEXT:    pop {r7, pc}
253  %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4
254  ret i32 %v
255}
256
257define i32 @cmpxchg32(ptr %p) {
258; NO-ATOMIC32-LABEL: cmpxchg32:
259; NO-ATOMIC32:       @ %bb.0:
260; NO-ATOMIC32-NEXT:    .save {r7, lr}
261; NO-ATOMIC32-NEXT:    push {r7, lr}
262; NO-ATOMIC32-NEXT:    .pad #8
263; NO-ATOMIC32-NEXT:    sub sp, #8
264; NO-ATOMIC32-NEXT:    movs r1, #0
265; NO-ATOMIC32-NEXT:    str r1, [sp, #4]
266; NO-ATOMIC32-NEXT:    movs r3, #5
267; NO-ATOMIC32-NEXT:    str r3, [sp]
268; NO-ATOMIC32-NEXT:    add r1, sp, #4
269; NO-ATOMIC32-NEXT:    movs r2, #1
270; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_4
271; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
272; NO-ATOMIC32-NEXT:    add sp, #8
273; NO-ATOMIC32-NEXT:    pop {r7, pc}
274;
275; ATOMIC32-LABEL: cmpxchg32:
276; ATOMIC32:       @ %bb.0:
277; ATOMIC32-NEXT:    .save {r7, lr}
278; ATOMIC32-NEXT:    push {r7, lr}
279; ATOMIC32-NEXT:    dmb sy
280; ATOMIC32-NEXT:    movs r1, #0
281; ATOMIC32-NEXT:    movs r2, #1
282; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_4
283; ATOMIC32-NEXT:    dmb sy
284; ATOMIC32-NEXT:    pop {r7, pc}
285  %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst
286  %res.0 = extractvalue { i32, i1 } %res, 0
287  ret i32 %res.0
288}
289
290define i64 @load64(ptr %p) {
291; CHECK-LABEL: load64:
292; CHECK:       @ %bb.0:
293; CHECK-NEXT:    .save {r7, lr}
294; CHECK-NEXT:    push {r7, lr}
295; CHECK-NEXT:    movs r1, #5
296; CHECK-NEXT:    bl __atomic_load_8
297; CHECK-NEXT:    pop {r7, pc}
298  %v = load atomic i64, ptr %p seq_cst, align 8
299  ret i64 %v
300}
301
302define void @store64(ptr %p) {
303; CHECK-LABEL: store64:
304; CHECK:       @ %bb.0:
305; CHECK-NEXT:    .save {r7, lr}
306; CHECK-NEXT:    push {r7, lr}
307; CHECK-NEXT:    .pad #8
308; CHECK-NEXT:    sub sp, #8
309; CHECK-NEXT:    movs r1, #5
310; CHECK-NEXT:    str r1, [sp]
311; CHECK-NEXT:    movs r2, #0
312; CHECK-NEXT:    mov r3, r2
313; CHECK-NEXT:    bl __atomic_store_8
314; CHECK-NEXT:    add sp, #8
315; CHECK-NEXT:    pop {r7, pc}
316  store atomic i64 0, ptr %p seq_cst, align 8
317  ret void
318}
319
320define i64 @rmw64(ptr %p) {
321; CHECK-LABEL: rmw64:
322; CHECK:       @ %bb.0:
323; CHECK-NEXT:    .save {r7, lr}
324; CHECK-NEXT:    push {r7, lr}
325; CHECK-NEXT:    .pad #8
326; CHECK-NEXT:    sub sp, #8
327; CHECK-NEXT:    movs r1, #5
328; CHECK-NEXT:    str r1, [sp]
329; CHECK-NEXT:    movs r2, #1
330; CHECK-NEXT:    movs r3, #0
331; CHECK-NEXT:    bl __atomic_fetch_add_8
332; CHECK-NEXT:    add sp, #8
333; CHECK-NEXT:    pop {r7, pc}
334  %v = atomicrmw add ptr %p, i64 1 seq_cst, align 8
335  ret i64 %v
336}
337
338define i64 @cmpxchg64(ptr %p) {
339; CHECK-LABEL: cmpxchg64:
340; CHECK:       @ %bb.0:
341; CHECK-NEXT:    .save {r7, lr}
342; CHECK-NEXT:    push {r7, lr}
343; CHECK-NEXT:    .pad #16
344; CHECK-NEXT:    sub sp, #16
345; CHECK-NEXT:    movs r3, #0
346; CHECK-NEXT:    str r3, [sp, #12]
347; CHECK-NEXT:    str r3, [sp, #8]
348; CHECK-NEXT:    movs r1, #5
349; CHECK-NEXT:    str r1, [sp]
350; CHECK-NEXT:    str r1, [sp, #4]
351; CHECK-NEXT:    add r1, sp, #8
352; CHECK-NEXT:    movs r2, #1
353; CHECK-NEXT:    bl __atomic_compare_exchange_8
354; CHECK-NEXT:    ldr r1, [sp, #12]
355; CHECK-NEXT:    ldr r0, [sp, #8]
356; CHECK-NEXT:    add sp, #16
357; CHECK-NEXT:    pop {r7, pc}
358  %res = cmpxchg ptr %p, i64 0, i64 1 seq_cst seq_cst
359  %res.0 = extractvalue { i64, i1 } %res, 0
360  ret i64 %res.0
361}
362