1; RUN: llc < %s -march=sparc -mcpu=v9 -verify-machineinstrs | FileCheck %s
2; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s
3
4; CHECK-LABEL: test_atomic_i8
5; CHECK:       ldub [%o0]
6; CHECK:       membar
7; CHECK:       ldub [%o1]
8; CHECK:       membar
9; CHECK:       membar
10; CHECK:       stb {{.+}}, [%o2]
11define i8 @test_atomic_i8(i8* %ptr1, i8* %ptr2, i8* %ptr3) {
12entry:
13  %0 = load atomic i8, i8* %ptr1 acquire, align 1
14  %1 = load atomic i8, i8* %ptr2 acquire, align 1
15  %2 = add i8 %0, %1
16  store atomic i8 %2, i8* %ptr3 release, align 1
17  ret i8 %2
18}
19
20; CHECK-LABEL: test_atomic_i16
21; CHECK:       lduh [%o0]
22; CHECK:       membar
23; CHECK:       lduh [%o1]
24; CHECK:       membar
25; CHECK:       membar
26; CHECK:       sth {{.+}}, [%o2]
27define i16 @test_atomic_i16(i16* %ptr1, i16* %ptr2, i16* %ptr3) {
28entry:
29  %0 = load atomic i16, i16* %ptr1 acquire, align 2
30  %1 = load atomic i16, i16* %ptr2 acquire, align 2
31  %2 = add i16 %0, %1
32  store atomic i16 %2, i16* %ptr3 release, align 2
33  ret i16 %2
34}
35
36; CHECK-LABEL: test_atomic_i32
37; CHECK:       ld [%o0]
38; CHECK:       membar
39; CHECK:       ld [%o1]
40; CHECK:       membar
41; CHECK:       membar
42; CHECK:       st {{.+}}, [%o2]
43define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) {
44entry:
45  %0 = load atomic i32, i32* %ptr1 acquire, align 4
46  %1 = load atomic i32, i32* %ptr2 acquire, align 4
47  %2 = add i32 %0, %1
48  store atomic i32 %2, i32* %ptr3 release, align 4
49  ret i32 %2
50}
51
52;; TODO: the "move %icc" and related instructions are totally
53;; redundant here. There's something weird happening in optimization
54;; of the success value of cmpxchg.
55
56; CHECK-LABEL: test_cmpxchg_i8
57; CHECK:       and %o1, -4, %o2
58; CHECK:       mov  3, %o3
59; CHECK:       andn %o3, %o1, %o1
60; CHECK:       sll %o1, 3, %o1
61; CHECK:       mov  255, %o3
62; CHECK:       sll %o3, %o1, %o5
63; CHECK:       xor %o5, -1, %o3
64; CHECK:       mov  123, %o4
65; CHECK:       ld [%o2], %g2
66; CHECK:       sll %o4, %o1, %o4
67; CHECK:       and %o0, 255, %o0
68; CHECK:       sll %o0, %o1, %o0
69; CHECK:       andn %g2, %o5, %g2
70; CHECK:       mov %g0, %o5
71; CHECK:      [[LABEL1:\.L.*]]:
72; CHECK:       or %g2, %o4, %g3
73; CHECK:       or %g2, %o0, %g4
74; CHECK:       cas [%o2], %g4, %g3
75; CHECK:       cmp %g3, %g4
76; CHECK:       mov  %o5, %g4
77; CHECK:       move %icc, 1, %g4
78; CHECK:       cmp %g4, 0
79; CHECK:       bne  [[LABEL2:\.L.*]]
80; CHECK:       nop
81; CHECK:       and %g3, %o3, %g4
82; CHECK:       cmp %g2, %g4
83; CHECK:       bne  [[LABEL1]]
84; CHECK:       mov  %g4, %g2
85; CHECK:      [[LABEL2]]:
86; CHECK:       retl
87; CHECK:       srl %g3, %o1, %o0
88define i8 @test_cmpxchg_i8(i8 %a, i8* %ptr) {
89entry:
90  %pair = cmpxchg i8* %ptr, i8 %a, i8 123 monotonic monotonic
91  %b = extractvalue { i8, i1 } %pair, 0
92  ret i8 %b
93}
94
95; CHECK-LABEL: test_cmpxchg_i16
96
97; CHECK:       and %o1, -4, %o2
98; CHECK:       and %o1, 3, %o1
99; CHECK:       xor %o1, 2, %o1
100; CHECK:       sll %o1, 3, %o1
101; CHECK:       sethi 63, %o3
102; CHECK:       or %o3, 1023, %o4
103; CHECK:       sll %o4, %o1, %o5
104; CHECK:       xor %o5, -1, %o3
105; CHECK:       and %o0, %o4, %o4
106; CHECK:       ld [%o2], %g2
107; CHECK:       mov  123, %o0
108; CHECK:       sll %o0, %o1, %o0
109; CHECK:       sll %o4, %o1, %o4
110; CHECK:       andn %g2, %o5, %g2
111; CHECK:       mov %g0, %o5
112; CHECK:      [[LABEL1:\.L.*]]:
113; CHECK:       or %g2, %o0, %g3
114; CHECK:       or %g2, %o4, %g4
115; CHECK:       cas [%o2], %g4, %g3
116; CHECK:       cmp %g3, %g4
117; CHECK:       mov  %o5, %g4
118; CHECK:       move %icc, 1, %g4
119; CHECK:       cmp %g4, 0
120; CHECK:       bne  [[LABEL2:\.L.*]]
121; CHECK:       nop
122; CHECK:       and %g3, %o3, %g4
123; CHECK:       cmp %g2, %g4
124; CHECK:       bne  [[LABEL1]]
125; CHECK:       mov  %g4, %g2
126; CHECK:      [[LABEL2]]:
127; CHECK:       retl
128; CHECK:       srl %g3, %o1, %o0
129define i16 @test_cmpxchg_i16(i16 %a, i16* %ptr) {
130entry:
131  %pair = cmpxchg i16* %ptr, i16 %a, i16 123 monotonic monotonic
132  %b = extractvalue { i16, i1 } %pair, 0
133  ret i16 %b
134}
135
136; CHECK-LABEL: test_cmpxchg_i32
137; CHECK:       mov 123, [[R:%[gilo][0-7]]]
138; CHECK:       cas [%o1], %o0, [[R]]
139
140define i32 @test_cmpxchg_i32(i32 %a, i32* %ptr) {
141entry:
142  %pair = cmpxchg i32* %ptr, i32 %a, i32 123 monotonic monotonic
143  %b = extractvalue { i32, i1 } %pair, 0
144  ret i32 %b
145}
146
147; CHECK-LABEL: test_swap_i8
148; CHECK:       mov 42, [[R:%[gilo][0-7]]]
149; CHECK:       cas
150
151define i8 @test_swap_i8(i8 %a, i8* %ptr) {
152entry:
153  %b = atomicrmw xchg i8* %ptr, i8 42 monotonic
154  ret i8 %b
155}
156
157; CHECK-LABEL: test_swap_i16
158; CHECK:       mov 42, [[R:%[gilo][0-7]]]
159; CHECK:       cas
160
161define i16 @test_swap_i16(i16 %a, i16* %ptr) {
162entry:
163  %b = atomicrmw xchg i16* %ptr, i16 42 monotonic
164  ret i16 %b
165}
166
167; CHECK-LABEL: test_swap_i32
168; CHECK:       mov 42, [[R:%[gilo][0-7]]]
169; CHECK:       swap [%o1], [[R]]
170
171define i32 @test_swap_i32(i32 %a, i32* %ptr) {
172entry:
173  %b = atomicrmw xchg i32* %ptr, i32 42 monotonic
174  ret i32 %b
175}
176
177; CHECK-LABEL: test_load_sub_i8
178; CHECK: membar
179; CHECK: .L{{.*}}:
180; CHECK: sub
181; CHECK: cas [{{%[gilo][0-7]}}]
182; CHECK: membar
183define zeroext i8 @test_load_sub_i8(i8* %p, i8 zeroext %v) {
184entry:
185  %0 = atomicrmw sub i8* %p, i8 %v seq_cst
186  ret i8 %0
187}
188
189; CHECK-LABEL: test_load_sub_i16
190; CHECK: membar
191; CHECK: .L{{.*}}:
192; CHECK: sub
193; CHECK: cas [{{%[gilo][0-7]}}]
194; CHECK: membar
195define zeroext i16 @test_load_sub_i16(i16* %p, i16 zeroext %v) {
196entry:
197  %0 = atomicrmw sub i16* %p, i16 %v seq_cst
198  ret i16 %0
199}
200
201; CHECK-LABEL: test_load_add_i32
202; CHECK: membar
203; CHECK: mov %g0
204; CHECK: mov [[U:%[gilo][0-7]]], [[V:%[gilo][0-7]]]
205; CHECK: add [[U:%[gilo][0-7]]], %o1, [[V2:%[gilo][0-7]]]
206; CHECK: cas [%o0], [[V]], [[V2]]
207; CHECK: membar
208define zeroext i32 @test_load_add_i32(i32* %p, i32 zeroext %v) {
209entry:
210  %0 = atomicrmw add i32* %p, i32 %v seq_cst
211  ret i32 %0
212}
213
214; CHECK-LABEL: test_load_xor_32
215; CHECK: membar
216; CHECK: xor
217; CHECK: cas [%o0]
218; CHECK: membar
219define zeroext i32 @test_load_xor_32(i32* %p, i32 zeroext %v) {
220entry:
221  %0 = atomicrmw xor i32* %p, i32 %v seq_cst
222  ret i32 %0
223}
224
225; CHECK-LABEL: test_load_and_32
226; CHECK: membar
227; CHECK: and
228; CHECK-NOT: xor
229; CHECK: cas [%o0]
230; CHECK: membar
231define zeroext i32 @test_load_and_32(i32* %p, i32 zeroext %v) {
232entry:
233  %0 = atomicrmw and i32* %p, i32 %v seq_cst
234  ret i32 %0
235}
236
237; CHECK-LABEL: test_load_nand_32
238; CHECK: membar
239; CHECK: and
240; CHECK: xor
241; CHECK: cas [%o0]
242; CHECK: membar
243define zeroext i32 @test_load_nand_32(i32* %p, i32 zeroext %v) {
244entry:
245  %0 = atomicrmw nand i32* %p, i32 %v seq_cst
246  ret i32 %0
247}
248
249; CHECK-LABEL: test_load_umin_32
250; CHECK: membar
251; CHECK: cmp
252; CHECK: movleu %icc
253; CHECK: cas [%o0]
254; CHECK: membar
255define zeroext i32 @test_load_umin_32(i32* %p, i32 zeroext %v) {
256entry:
257  %0 = atomicrmw umin i32* %p, i32 %v seq_cst
258  ret i32 %0
259}
260