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