• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16 | FileCheck %s
2
3@var = global i128 0
4
5define i128 @val_compare_and_swap(i128* %p, i128 %oldval, i128 %newval) {
6; CHECK-LABEL: val_compare_and_swap:
7; Due to the scheduling right after isel for cmpxchg and given the
8; machine scheduler and copy coalescer do not mess up with physical
9; register live-ranges, we end up with a useless copy.
10;
11; CHECK: movq %rcx, [[TMP:%r[0-9a-z]+]]
12; CHECK: movq %rsi, %rax
13; CHECK: movq %r8, %rcx
14; CHECK: movq [[TMP]], %rbx
15; CHECK: lock
16; CHECK: cmpxchg16b (%rdi)
17
18  %pair = cmpxchg i128* %p, i128 %oldval, i128 %newval acquire acquire
19  %val = extractvalue { i128, i1 } %pair, 0
20  ret i128 %val
21}
22
23define void @fetch_and_nand(i128* %p, i128 %bits) {
24; CHECK-LABEL: fetch_and_nand:
25; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
26; CHECK-DAG:     movq (%rdi), %rax
27; CHECK-DAG:     movq 8(%rdi), %rdx
28
29; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
30; CHECK:         movq %rdx, %rcx
31; CHECK:         andq [[INCHI]], %rcx
32; CHECK:         movq %rax, %rbx
33  ; INCLO equivalent comes in in %rsi, so it makes sense it stays there.
34; CHECK:         andq %rsi, %rbx
35; CHECK:         notq %rbx
36; CHECK:         notq %rcx
37; CHECK:         lock
38; CHECK:         cmpxchg16b (%rdi)
39; CHECK:         jne [[LOOP]]
40
41; CHECK:         movq %rax, _var
42; CHECK:         movq %rdx, _var+8
43  %val = atomicrmw nand i128* %p, i128 %bits release
44  store i128 %val, i128* @var, align 16
45  ret void
46}
47
48define void @fetch_and_or(i128* %p, i128 %bits) {
49; CHECK-LABEL: fetch_and_or:
50; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
51; CHECK-DAG:     movq (%rdi), %rax
52; CHECK-DAG:     movq 8(%rdi), %rdx
53
54; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
55; CHECK:         movq %rax, %rbx
56  ; INCLO equivalent comes in in %rsi, so it makes sense it stays there.
57; CHECK:         orq %rsi, %rbx
58; CHECK:         movq %rdx, %rcx
59; CHECK:         orq [[INCHI]], %rcx
60; CHECK:         lock
61; CHECK:         cmpxchg16b (%rdi)
62; CHECK:         jne [[LOOP]]
63
64; CHECK:         movq %rax, _var
65; CHECK:         movq %rdx, _var+8
66
67  %val = atomicrmw or i128* %p, i128 %bits seq_cst
68  store i128 %val, i128* @var, align 16
69  ret void
70}
71
72define void @fetch_and_add(i128* %p, i128 %bits) {
73; CHECK-LABEL: fetch_and_add:
74; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
75; CHECK-DAG:     movq (%rdi), %rax
76; CHECK-DAG:     movq 8(%rdi), %rdx
77
78; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
79; CHECK:         movq %rax, %rbx
80  ; INCLO equivalent comes in in %rsi, so it makes sense it stays there.
81; CHECK:         addq %rsi, %rbx
82; CHECK:         movq %rdx, %rcx
83; CHECK:         adcq [[INCHI]], %rcx
84; CHECK:         lock
85; CHECK:         cmpxchg16b (%rdi)
86; CHECK:         jne [[LOOP]]
87
88; CHECK:         movq %rax, _var
89; CHECK:         movq %rdx, _var+8
90
91  %val = atomicrmw add i128* %p, i128 %bits seq_cst
92  store i128 %val, i128* @var, align 16
93  ret void
94}
95
96define void @fetch_and_sub(i128* %p, i128 %bits) {
97; CHECK-LABEL: fetch_and_sub:
98; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
99; CHECK-DAG:     movq (%rdi), %rax
100; CHECK-DAG:     movq 8(%rdi), %rdx
101
102; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
103; CHECK:         movq %rax, %rbx
104  ; INCLO equivalent comes in in %rsi, so it makes sense it stays there.
105; CHECK:         subq %rsi, %rbx
106; CHECK:         movq %rdx, %rcx
107; CHECK:         sbbq [[INCHI]], %rcx
108; CHECK:         lock
109; CHECK:         cmpxchg16b (%rdi)
110; CHECK:         jne [[LOOP]]
111
112; CHECK:         movq %rax, _var
113; CHECK:         movq %rdx, _var+8
114
115  %val = atomicrmw sub i128* %p, i128 %bits seq_cst
116  store i128 %val, i128* @var, align 16
117  ret void
118}
119
120define void @fetch_and_min(i128* %p, i128 %bits) {
121; CHECK-LABEL: fetch_and_min:
122; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
123; CHECK-DAG:     movq (%rdi), %rax
124; CHECK-DAG:     movq 8(%rdi), %rdx
125
126; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
127; CHECK:         cmpq
128; CHECK:         sbbq
129; CHECK:         setg
130; CHECK:         cmovneq %rax, %rbx
131; CHECK:         movq [[INCHI]], %rcx
132; CHECK:         cmovneq %rdx, %rcx
133; CHECK:         lock
134; CHECK:         cmpxchg16b (%rdi)
135; CHECK:         jne [[LOOP]]
136
137; CHECK:         movq %rax, _var
138; CHECK:         movq %rdx, _var+8
139
140  %val = atomicrmw min i128* %p, i128 %bits seq_cst
141  store i128 %val, i128* @var, align 16
142  ret void
143}
144
145define void @fetch_and_max(i128* %p, i128 %bits) {
146; CHECK-LABEL: fetch_and_max:
147; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
148; CHECK-DAG:     movq (%rdi), %rax
149; CHECK-DAG:     movq 8(%rdi), %rdx
150
151; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
152; CHECK:         cmpq
153; CHECK:         sbbq
154; CHECK:         setge
155; CHECK:         cmovneq %rax, %rbx
156; CHECK:         movq [[INCHI]], %rcx
157; CHECK:         cmovneq %rdx, %rcx
158; CHECK:         lock
159; CHECK:         cmpxchg16b (%rdi)
160; CHECK:         jne [[LOOP]]
161
162; CHECK:         movq %rax, _var
163; CHECK:         movq %rdx, _var+8
164
165  %val = atomicrmw max i128* %p, i128 %bits seq_cst
166  store i128 %val, i128* @var, align 16
167  ret void
168}
169
170define void @fetch_and_umin(i128* %p, i128 %bits) {
171; CHECK-LABEL: fetch_and_umin:
172; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
173; CHECK-DAG:     movq (%rdi), %rax
174; CHECK-DAG:     movq 8(%rdi), %rdx
175
176; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
177; CHECK:         cmpq
178; CHECK:         sbbq
179; CHECK:         seta
180; CHECK:         cmovneq %rax, %rbx
181; CHECK:         movq [[INCHI]], %rcx
182; CHECK:         cmovneq %rdx, %rcx
183; CHECK:         lock
184; CHECK:         cmpxchg16b (%rdi)
185; CHECK:         jne [[LOOP]]
186
187; CHECK:         movq %rax, _var
188; CHECK:         movq %rdx, _var+8
189
190  %val = atomicrmw umin i128* %p, i128 %bits seq_cst
191  store i128 %val, i128* @var, align 16
192  ret void
193}
194
195define void @fetch_and_umax(i128* %p, i128 %bits) {
196; CHECK-LABEL: fetch_and_umax:
197; CHECK-DAG:     movq %rdx, [[INCHI:%[a-z0-9]+]]
198; CHECK-DAG:     movq (%rdi), %rax
199; CHECK-DAG:     movq 8(%rdi), %rdx
200
201; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
202; CHECK:         cmpq
203; CHECK:         sbbq
204; CHECK:         setb
205; CHECK:         cmovneq %rax, %rbx
206; CHECK:         movq [[INCHI]], %rcx
207; CHECK:         cmovneq %rdx, %rcx
208; CHECK:         lock
209; CHECK:         cmpxchg16b (%rdi)
210; CHECK:         jne [[LOOP]]
211
212; CHECK:         movq %rax, _var
213; CHECK:         movq %rdx, _var+8
214
215  %val = atomicrmw umax i128* %p, i128 %bits seq_cst
216  store i128 %val, i128* @var, align 16
217  ret void
218}
219
220define i128 @atomic_load_seq_cst(i128* %p) {
221; CHECK-LABEL: atomic_load_seq_cst:
222; CHECK: xorl %eax, %eax
223; CHECK: xorl %edx, %edx
224; CHECK: xorl %ecx, %ecx
225; CHECK: xorl %ebx, %ebx
226; CHECK: lock
227; CHECK: cmpxchg16b (%rdi)
228
229   %r = load atomic i128, i128* %p seq_cst, align 16
230   ret i128 %r
231}
232
233define i128 @atomic_load_relaxed(i128* %p) {
234; CHECK: atomic_load_relaxed:
235; CHECK: xorl %eax, %eax
236; CHECK: xorl %edx, %edx
237; CHECK: xorl %ecx, %ecx
238; CHECK: xorl %ebx, %ebx
239; CHECK: lock
240; CHECK: cmpxchg16b (%rdi)
241
242   %r = load atomic i128, i128* %p monotonic, align 16
243   ret i128 %r
244}
245
246define void @atomic_store_seq_cst(i128* %p, i128 %in) {
247; CHECK-LABEL: atomic_store_seq_cst:
248; CHECK:         movq %rdx, %rcx
249; CHECK:         movq %rsi, %rbx
250; CHECK:         movq (%rdi), %rax
251; CHECK:         movq 8(%rdi), %rdx
252
253; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
254; CHECK:         lock
255; CHECK:         cmpxchg16b (%rdi)
256; CHECK:         jne [[LOOP]]
257; CHECK-NOT:     callq ___sync_lock_test_and_set_16
258
259   store atomic i128 %in, i128* %p seq_cst, align 16
260   ret void
261}
262
263define void @atomic_store_release(i128* %p, i128 %in) {
264; CHECK-LABEL: atomic_store_release:
265; CHECK:         movq %rdx, %rcx
266; CHECK:         movq %rsi, %rbx
267; CHECK:         movq (%rdi), %rax
268; CHECK:         movq 8(%rdi), %rdx
269
270; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
271; CHECK:         lock
272; CHECK:         cmpxchg16b (%rdi)
273; CHECK:         jne [[LOOP]]
274
275   store atomic i128 %in, i128* %p release, align 16
276   ret void
277}
278
279define void @atomic_store_relaxed(i128* %p, i128 %in) {
280; CHECK-LABEL: atomic_store_relaxed:
281; CHECK:         movq %rdx, %rcx
282; CHECK:         movq %rsi, %rbx
283; CHECK:         movq (%rdi), %rax
284; CHECK:         movq 8(%rdi), %rdx
285
286; CHECK: [[LOOP:.?LBB[0-9]+_[0-9]+]]:
287; CHECK:         lock
288; CHECK:         cmpxchg16b (%rdi)
289; CHECK:         jne [[LOOP]]
290
291   store atomic i128 %in, i128* %p unordered, align 16
292   ret void
293}
294