xref: /llvm-project/llvm/test/CodeGen/SPARC/atomics.ll (revision 728490257ecc09ada707a0390303bd3c61027a53)
1; RUN: llc < %s -mtriple=sparc -mcpu=v9 -verify-machineinstrs | FileCheck %s --check-prefixes=SPARC
2; RUN: llc < %s -mtriple=sparcv9 -verify-machineinstrs | FileCheck %s --check-prefixes=SPARC64
3
4; SPARC-LABEL: test_atomic_i8
5; SPARC:       ldub [%o0]
6; SPARC:       membar
7; SPARC:       ldub [%o1]
8; SPARC:       membar
9; SPARC:       membar
10; SPARC:       stb {{.+}}, [%o2]
11; SPARC64-LABEL: test_atomic_i8
12; SPARC64:       ldub [%o0]
13; SPARC64:       membar
14; SPARC64:       ldub [%o1]
15; SPARC64:       membar
16; SPARC64:       membar
17; SPARC64:       stb {{.+}}, [%o2]
18define i8 @test_atomic_i8(ptr %ptr1, ptr %ptr2, ptr %ptr3) {
19entry:
20  %0 = load atomic i8, ptr %ptr1 acquire, align 1
21  %1 = load atomic i8, ptr %ptr2 acquire, align 1
22  %2 = add i8 %0, %1
23  store atomic i8 %2, ptr %ptr3 release, align 1
24  ret i8 %2
25}
26
27; SPARC-LABEL: test_atomic_i16
28; SPARC:       lduh [%o0]
29; SPARC:       membar
30; SPARC:       lduh [%o1]
31; SPARC:       membar
32; SPARC:       membar
33; SPARC:       sth {{.+}}, [%o2]
34; SPARC64-LABEL: test_atomic_i16
35; SPARC64:       lduh [%o0]
36; SPARC64:       membar
37; SPARC64:       lduh [%o1]
38; SPARC64:       membar
39; SPARC64:       membar
40; SPARC64:       sth {{.+}}, [%o2]
41define i16 @test_atomic_i16(ptr %ptr1, ptr %ptr2, ptr %ptr3) {
42entry:
43  %0 = load atomic i16, ptr %ptr1 acquire, align 2
44  %1 = load atomic i16, ptr %ptr2 acquire, align 2
45  %2 = add i16 %0, %1
46  store atomic i16 %2, ptr %ptr3 release, align 2
47  ret i16 %2
48}
49
50; SPARC-LABEL: test_atomic_i32
51; SPARC:       ld [%o0]
52; SPARC:       membar
53; SPARC:       ld [%o1]
54; SPARC:       membar
55; SPARC:       membar
56; SPARC:       st {{.+}}, [%o2]
57; SPARC64-LABEL: test_atomic_i32
58; SPARC64:       ld [%o0]
59; SPARC64:       membar
60; SPARC64:       ld [%o1]
61; SPARC64:       membar
62; SPARC64:       membar
63; SPARC64:       st {{.+}}, [%o2]
64define i32 @test_atomic_i32(ptr %ptr1, ptr %ptr2, ptr %ptr3) {
65entry:
66  %0 = load atomic i32, ptr %ptr1 acquire, align 4
67  %1 = load atomic i32, ptr %ptr2 acquire, align 4
68  %2 = add i32 %0, %1
69  store atomic i32 %2, ptr %ptr3 release, align 4
70  ret i32 %2
71}
72
73;; TODO: the "move %icc" and related instructions are totally
74;; redundant here. There's something weird happening in optimization
75;; of the success value of cmpxchg.
76
77; SPARC-LABEL: test_cmpxchg_i8
78; SPARC:       and %o1, -4, %o2
79; SPARC:       mov  3, %o3
80; SPARC:       andn %o3, %o1, %o1
81; SPARC:       sll %o1, 3, %o1
82; SPARC:       mov  255, %o3
83; SPARC:       sll %o3, %o1, %o5
84; SPARC:       xor %o5, -1, %o3
85; SPARC:       mov  123, %o4
86; SPARC:       ld [%o2], %g2
87; SPARC:       sll %o4, %o1, %o4
88; SPARC:       and %o0, 255, %o0
89; SPARC:       sll %o0, %o1, %o0
90; SPARC:       andn %g2, %o5, %o5
91; SPARC:      [[LABEL1:\.L.*]]:
92; SPARC:       or %o5, %o4, %g2
93; SPARC:       or %o5, %o0, %g3
94; SPARC:       cas [%o2], %g3, %g2
95; SPARC:       mov %g0, %g4
96; SPARC:       cmp %g2, %g3
97; SPARC:       move %icc, 1, %g4
98; SPARC:       cmp %g4, 0
99; SPARC:       bne %icc, [[LABEL2:\.L.*]]
100; SPARC:       nop
101; SPARC:       and %g2, %o3, %g3
102; SPARC:       cmp %o5, %g3
103; SPARC:       bne %icc, [[LABEL1]]
104; SPARC:       mov  %g3, %o5
105; SPARC:      [[LABEL2]]:
106; SPARC:       retl
107; SPARC:       srl %g2, %o1, %o0
108; SPARC64-LABEL: test_cmpxchg_i8
109; SPARC64:       and %o1, -4, %o2
110; SPARC64:       mov  3, %o3
111; SPARC64:       andn %o3, %o1, %o1
112; SPARC64:       sll %o1, 3, %o1
113; SPARC64:       mov  255, %o3
114; SPARC64:       sll %o3, %o1, %o5
115; SPARC64:       xor %o5, -1, %o3
116; SPARC64:       mov  123, %o4
117; SPARC64:       ld [%o2], %g2
118; SPARC64:       sll %o4, %o1, %o4
119; SPARC64:       and %o0, 255, %o0
120; SPARC64:       sll %o0, %o1, %o0
121; SPARC64:       andn %g2, %o5, %o5
122; SPARC64:      [[LABEL1:\.L.*]]:
123; SPARC64:       or %o5, %o4, %g2
124; SPARC64:       or %o5, %o0, %g3
125; SPARC64:       cas [%o2], %g3, %g2
126; SPARC64:       mov %g0, %g4
127; SPARC64:       cmp %g2, %g3
128; SPARC64:       move %icc, 1, %g4
129; SPARC64:       cmp %g4, 0
130; SPARC64:       bne %icc, [[LABEL2:\.L.*]]
131; SPARC64:       nop
132; SPARC64:       and %g2, %o3, %g3
133; SPARC64:       cmp %o5, %g3
134; SPARC64:       bne %icc, [[LABEL1]]
135; SPARC64:       mov  %g3, %o5
136; SPARC64:      [[LABEL2]]:
137; SPARC64:       retl
138; SPARC64:       srl %g2, %o1, %o0
139define i8 @test_cmpxchg_i8(i8 %a, ptr %ptr) {
140entry:
141  %pair = cmpxchg ptr %ptr, i8 %a, i8 123 monotonic monotonic
142  %b = extractvalue { i8, i1 } %pair, 0
143  ret i8 %b
144}
145
146; SPARC-LABEL: test_cmpxchg_i16
147; SPARC:       and %o1, -4, %o2
148; SPARC:       and %o1, 3, %o1
149; SPARC:       xor %o1, 2, %o1
150; SPARC:       sll %o1, 3, %o1
151; SPARC:       sethi 63, %o3
152; SPARC:       or %o3, 1023, %o4
153; SPARC:       sll %o4, %o1, %o5
154; SPARC:       xor %o5, -1, %o3
155; SPARC:       and %o0, %o4, %o4
156; SPARC:       ld [%o2], %g2
157; SPARC:       mov  123, %o0
158; SPARC:       sll %o0, %o1, %o0
159; SPARC:       sll %o4, %o1, %o4
160; SPARC:       andn %g2, %o5, %o5
161; SPARC:      [[LABEL1:\.L.*]]:
162; SPARC:       or %o5, %o0, %g2
163; SPARC:       or %o5, %o4, %g3
164; SPARC:       cas [%o2], %g3, %g2
165; SPARC:       mov %g0, %g4
166; SPARC:       cmp %g2, %g3
167; SPARC:       move %icc, 1, %g4
168; SPARC:       cmp %g4, 0
169; SPARC:       bne %icc, [[LABEL2:\.L.*]]
170; SPARC:       nop
171; SPARC:       and %g2, %o3, %g3
172; SPARC:       cmp %o5, %g3
173; SPARC:       bne %icc, [[LABEL1]]
174; SPARC:       mov  %g3, %o5
175; SPARC:      [[LABEL2]]:
176; SPARC:       retl
177; SPARC:       srl %g2, %o1, %o0
178; SPARC64-LABEL: test_cmpxchg_i16
179; SPARC64:       and %o1, -4, %o2
180; SPARC64:       and %o1, 3, %o1
181; SPARC64:       xor %o1, 2, %o1
182; SPARC64:       sll %o1, 3, %o1
183; SPARC64:       sethi 63, %o3
184; SPARC64:       or %o3, 1023, %o4
185; SPARC64:       sll %o4, %o1, %o5
186; SPARC64:       xor %o5, -1, %o3
187; SPARC64:       and %o0, %o4, %o4
188; SPARC64:       ld [%o2], %g2
189; SPARC64:       mov  123, %o0
190; SPARC64:       sll %o0, %o1, %o0
191; SPARC64:       sll %o4, %o1, %o4
192; SPARC64:       andn %g2, %o5, %o5
193; SPARC64:      [[LABEL1:\.L.*]]:
194; SPARC64:       or %o5, %o0, %g2
195; SPARC64:       or %o5, %o4, %g3
196; SPARC64:       cas [%o2], %g3, %g2
197; SPARC64:       mov %g0, %g4
198; SPARC64:       cmp %g2, %g3
199; SPARC64:       move %icc, 1, %g4
200; SPARC64:       cmp %g4, 0
201; SPARC64:       bne %icc, [[LABEL2:\.L.*]]
202; SPARC64:       nop
203; SPARC64:       and %g2, %o3, %g3
204; SPARC64:       cmp %o5, %g3
205; SPARC64:       bne %icc, [[LABEL1]]
206; SPARC64:       mov  %g3, %o5
207; SPARC64:      [[LABEL2]]:
208; SPARC64:       retl
209; SPARC64:       srl %g2, %o1, %o0
210define i16 @test_cmpxchg_i16(i16 %a, ptr %ptr) {
211entry:
212  %pair = cmpxchg ptr %ptr, i16 %a, i16 123 monotonic monotonic
213  %b = extractvalue { i16, i1 } %pair, 0
214  ret i16 %b
215}
216
217; SPARC-LABEL: test_cmpxchg_i32
218; SPARC:       mov 123, [[R:%[gilo][0-7]]]
219; SPARC:       cas [%o1], %o0, [[R]]
220; SPARC64-LABEL: test_cmpxchg_i32
221; SPARC64:       mov 123, [[R:%[gilo][0-7]]]
222; SPARC64:       cas [%o1], %o0, [[R]]
223define i32 @test_cmpxchg_i32(i32 %a, ptr %ptr) {
224entry:
225  %pair = cmpxchg ptr %ptr, i32 %a, i32 123 monotonic monotonic
226  %b = extractvalue { i32, i1 } %pair, 0
227  ret i32 %b
228}
229
230; SPARC-LABEL: test_swap_i8
231; SPARC:       mov 42, [[R:%[gilo][0-7]]]
232; SPARC:       cas
233; SPARC64-LABEL: test_swap_i8
234; SPARC64:       mov 42, [[R:%[gilo][0-7]]]
235; SPARC64:       cas
236define i8 @test_swap_i8(i8 %a, ptr %ptr) {
237entry:
238  %b = atomicrmw xchg ptr %ptr, i8 42 monotonic
239  ret i8 %b
240}
241
242; SPARC-LABEL: test_swap_i16
243; SPARC:       mov 42, [[R:%[gilo][0-7]]]
244; SPARC:       cas
245; SPARC64-LABEL: test_swap_i16
246; SPARC64:       mov 42, [[R:%[gilo][0-7]]]
247; SPARC64:       cas
248define i16 @test_swap_i16(i16 %a, ptr %ptr) {
249entry:
250  %b = atomicrmw xchg ptr %ptr, i16 42 monotonic
251  ret i16 %b
252}
253
254; SPARC-LABEL: test_swap_i32
255; SPARC:       mov 42, [[R:%[gilo][0-7]]]
256; SPARC:       swap [%o1], [[R]]
257; SPARC64-LABEL: test_swap_i32
258; SPARC64:       mov 42, [[R:%[gilo][0-7]]]
259; SPARC64:       swap [%o1], [[R]]
260define i32 @test_swap_i32(i32 %a, ptr %ptr) {
261entry:
262  %b = atomicrmw xchg ptr %ptr, i32 42 monotonic
263  ret i32 %b
264}
265
266; SPARC-LABEL: test_load_sub_i8
267; SPARC: membar
268; SPARC: .L{{.*}}:
269; SPARC: sub
270; SPARC: cas [{{%[gilo][0-7]}}]
271; SPARC: membar
272; SPARC64-LABEL: test_load_sub_i8
273; SPARC64: membar
274; SPARC64: .L{{.*}}:
275; SPARC64: sub
276; SPARC64: cas [{{%[gilo][0-7]}}]
277; SPARC64: membar
278define zeroext i8 @test_load_sub_i8(ptr %p, i8 zeroext %v) {
279entry:
280  %0 = atomicrmw sub ptr %p, i8 %v seq_cst
281  ret i8 %0
282}
283
284; SPARC-LABEL: test_load_sub_i16
285; SPARC: membar
286; SPARC: .L{{.*}}:
287; SPARC: sub
288; SPARC: cas [{{%[gilo][0-7]}}]
289; SPARC: membar
290; SPARC64-LABEL: test_load_sub_i16
291; SPARC64: membar
292; SPARC64: .L{{.*}}:
293; SPARC64: sub
294; SPARC64: cas [{{%[gilo][0-7]}}]
295; SPARC64: membar
296define zeroext i16 @test_load_sub_i16(ptr %p, i16 zeroext %v) {
297entry:
298  %0 = atomicrmw sub ptr %p, i16 %v seq_cst
299  ret i16 %0
300}
301
302; SPARC-LABEL: test_load_add_i32
303; SPARC: membar
304; SPARC: mov [[U:%[gilo][0-7]]], [[V:%[gilo][0-7]]]
305; SPARC: add [[U:%[gilo][0-7]]], %o1, [[V2:%[gilo][0-7]]]
306; SPARC: cas [%o0], [[V]], [[V2]]
307; SPARC: membar
308; SPARC64-LABEL: test_load_add_i32
309; SPARC64: membar
310; SPARC64: mov [[U:%[gilo][0-7]]], [[V:%[gilo][0-7]]]
311; SPARC64: add [[U:%[gilo][0-7]]], %o1, [[V2:%[gilo][0-7]]]
312; SPARC64: cas [%o0], [[V]], [[V2]]
313; SPARC64: membar
314define zeroext i32 @test_load_add_i32(ptr %p, i32 zeroext %v) {
315entry:
316  %0 = atomicrmw add ptr %p, i32 %v seq_cst
317  ret i32 %0
318}
319
320; SPARC-LABEL: test_load_xor_32
321; SPARC: membar
322; SPARC: xor
323; SPARC: cas [%o0]
324; SPARC: membar
325; SPARC64-LABEL: test_load_xor_32
326; SPARC64: membar
327; SPARC64: xor
328; SPARC64: cas [%o0]
329; SPARC64: membar
330define zeroext i32 @test_load_xor_32(ptr %p, i32 zeroext %v) {
331entry:
332  %0 = atomicrmw xor ptr %p, i32 %v seq_cst
333  ret i32 %0
334}
335
336; SPARC-LABEL: test_load_and_32
337; SPARC: membar
338; SPARC: and
339; SPARC-NOT: xor
340; SPARC: cas [%o0]
341; SPARC: membar
342; SPARC64-LABEL: test_load_and_32
343; SPARC64: membar
344; SPARC64: and
345; SPARC64-NOT: xor
346; SPARC64: cas [%o0]
347; SPARC64: membar
348define zeroext i32 @test_load_and_32(ptr %p, i32 zeroext %v) {
349entry:
350  %0 = atomicrmw and ptr %p, i32 %v seq_cst
351  ret i32 %0
352}
353
354; SPARC-LABEL: test_load_nand_32
355; SPARC: membar
356; SPARC: and
357; SPARC: xor
358; SPARC: cas [%o0]
359; SPARC: membar
360; SPARC64-LABEL: test_load_nand_32
361; SPARC64: membar
362; SPARC64: and
363; SPARC64: xor
364; SPARC64: cas [%o0]
365; SPARC64: membar
366define zeroext i32 @test_load_nand_32(ptr %p, i32 zeroext %v) {
367entry:
368  %0 = atomicrmw nand ptr %p, i32 %v seq_cst
369  ret i32 %0
370}
371
372; SPARC-LABEL: test_load_umin_32
373; SPARC: membar
374; SPARC: cmp
375; SPARC: movleu %icc
376; SPARC: cas [%o0]
377; SPARC: membar
378; SPARC64-LABEL: test_load_umin_32
379; SPARC64: membar
380; SPARC64: cmp
381; SPARC64: movleu %icc
382; SPARC64: cas [%o0]
383; SPARC64: membar
384define zeroext i32 @test_load_umin_32(ptr %p, i32 zeroext %v) {
385entry:
386  %0 = atomicrmw umin ptr %p, i32 %v seq_cst
387  ret i32 %0
388}
389