AArch64/ARM64: remove AArch64 from tree prior to renaming ARM64.
[oota-llvm.git] / test / CodeGen / ARM64 / atomic-128.ll
1 ; RUN: llc < %s -march=arm64 -mtriple=arm64-linux-gnu -verify-machineinstrs -mcpu=cyclone | FileCheck %s
2
3 @var = global i128 0
4
5 define i128 @val_compare_and_swap(i128* %p, i128 %oldval, i128 %newval) {
6 ; CHECK-LABEL: val_compare_and_swap:
7 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
8 ; CHECK: ldaxp   [[RESULTLO:x[0-9]+]], [[RESULTHI:x[0-9]+]], [x[[ADDR:[0-9]+]]]
9 ; CHECK-DAG: eor     [[MISMATCH_LO:x[0-9]+]], [[RESULTLO]], x2
10 ; CHECK-DAG: eor     [[MISMATCH_HI:x[0-9]+]], [[RESULTHI]], x3
11 ; CHECK: orr [[MISMATCH:x[0-9]+]], [[MISMATCH_LO]], [[MISMATCH_HI]]
12 ; CHECK: cbnz    [[MISMATCH]], [[DONE:.LBB[0-9]+_[0-9]+]]
13 ; CHECK: stxp   [[SCRATCH_RES:w[0-9]+]], x4, x5, [x[[ADDR]]]
14 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
15 ; CHECK: [[DONE]]:
16   %val = cmpxchg i128* %p, i128 %oldval, i128 %newval acquire acquire
17   ret i128 %val
18 }
19
20 define void @fetch_and_nand(i128* %p, i128 %bits) {
21 ; CHECK-LABEL: fetch_and_nand:
22 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
23 ; CHECK: ldxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
24 ; CHECK-DAG: bic    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
25 ; CHECK-DAG: bic    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
26 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
27 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
28
29 ; CHECK-DAG: str    [[DEST_REGHI]]
30 ; CHECK-DAG: str    [[DEST_REGLO]]
31   %val = atomicrmw nand i128* %p, i128 %bits release
32   store i128 %val, i128* @var, align 16
33   ret void
34 }
35
36 define void @fetch_and_or(i128* %p, i128 %bits) {
37 ; CHECK-LABEL: fetch_and_or:
38 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
39 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
40 ; CHECK-DAG: orr    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
41 ; CHECK-DAG: orr    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
42 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
43 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
44
45 ; CHECK-DAG: str    [[DEST_REGHI]]
46 ; CHECK-DAG: str    [[DEST_REGLO]]
47   %val = atomicrmw or i128* %p, i128 %bits seq_cst
48   store i128 %val, i128* @var, align 16
49   ret void
50 }
51
52 define void @fetch_and_add(i128* %p, i128 %bits) {
53 ; CHECK-LABEL: fetch_and_add:
54 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
55 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
56 ; CHECK: adds   [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
57 ; CHECK: adcs   [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
58 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
59 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
60
61 ; CHECK-DAG: str    [[DEST_REGHI]]
62 ; CHECK-DAG: str    [[DEST_REGLO]]
63   %val = atomicrmw add i128* %p, i128 %bits seq_cst
64   store i128 %val, i128* @var, align 16
65   ret void
66 }
67
68 define void @fetch_and_sub(i128* %p, i128 %bits) {
69 ; CHECK-LABEL: fetch_and_sub:
70 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
71 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
72 ; CHECK: subs   [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
73 ; CHECK: sbcs    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
74 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
75 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
76
77 ; CHECK-DAG: str    [[DEST_REGHI]]
78 ; CHECK-DAG: str    [[DEST_REGLO]]
79   %val = atomicrmw sub i128* %p, i128 %bits seq_cst
80   store i128 %val, i128* @var, align 16
81   ret void
82 }
83
84 define void @fetch_and_min(i128* %p, i128 %bits) {
85 ; CHECK-LABEL: fetch_and_min:
86 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
87 ; CHECK: ldaxp   [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
88 ; CHECK: cmp     [[DEST_REGLO]], x2
89 ; CHECK: cset    [[LOCMP:w[0-9]+]], ls
90 ; CHECK: cmp     [[DEST_REGHI:x[0-9]+]], x3
91 ; CHECK: cset    [[HICMP:w[0-9]+]], le
92 ; CHECK: csel    [[CMP:w[0-9]+]], [[LOCMP]], [[HICMP]], eq
93 ; CHECK: cmp     [[CMP]], #0
94 ; CHECK-DAG: csel    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, ne
95 ; CHECK-DAG: csel    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, ne
96 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
97 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
98
99 ; CHECK-DAG: str    [[DEST_REGHI]]
100 ; CHECK-DAG: str    [[DEST_REGLO]]
101   %val = atomicrmw min i128* %p, i128 %bits seq_cst
102   store i128 %val, i128* @var, align 16
103   ret void
104 }
105
106 define void @fetch_and_max(i128* %p, i128 %bits) {
107 ; CHECK-LABEL: fetch_and_max:
108 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
109 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
110 ; CHECK: cmp     [[DEST_REGLO]], x2
111 ; CHECK: cset    [[LOCMP:w[0-9]+]], hi
112 ; CHECK: cmp     [[DEST_REGHI:x[0-9]+]], x3
113 ; CHECK: cset    [[HICMP:w[0-9]+]], gt
114 ; CHECK: csel    [[CMP:w[0-9]+]], [[LOCMP]], [[HICMP]], eq
115 ; CHECK: cmp     [[CMP]], #0
116 ; CHECK-DAG: csel    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, ne
117 ; CHECK-DAG: csel    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, ne
118 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
119 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
120
121 ; CHECK-DAG: str    [[DEST_REGHI]]
122 ; CHECK-DAG: str    [[DEST_REGLO]]
123   %val = atomicrmw max i128* %p, i128 %bits seq_cst
124   store i128 %val, i128* @var, align 16
125   ret void
126 }
127
128 define void @fetch_and_umin(i128* %p, i128 %bits) {
129 ; CHECK-LABEL: fetch_and_umin:
130 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
131 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
132 ; CHECK: cmp     [[DEST_REGLO]], x2
133 ; CHECK: cset    [[LOCMP:w[0-9]+]], ls
134 ; CHECK: cmp     [[DEST_REGHI:x[0-9]+]], x3
135 ; CHECK: cset    [[HICMP:w[0-9]+]], ls
136 ; CHECK: csel    [[CMP:w[0-9]+]], [[LOCMP]], [[HICMP]], eq
137 ; CHECK: cmp     [[CMP]], #0
138 ; CHECK-DAG: csel    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, ne
139 ; CHECK-DAG: csel    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, ne
140 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
141 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
142
143 ; CHECK-DAG: str    [[DEST_REGHI]]
144 ; CHECK-DAG: str    [[DEST_REGLO]]
145   %val = atomicrmw umin i128* %p, i128 %bits seq_cst
146   store i128 %val, i128* @var, align 16
147   ret void
148 }
149
150 define void @fetch_and_umax(i128* %p, i128 %bits) {
151 ; CHECK-LABEL: fetch_and_umax:
152 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
153 ; CHECK: ldaxp  [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
154 ; CHECK: cmp     [[DEST_REGLO]], x2
155 ; CHECK: cset    [[LOCMP:w[0-9]+]], hi
156 ; CHECK: cmp     [[DEST_REGHI:x[0-9]+]], x3
157 ; CHECK: cset    [[HICMP:w[0-9]+]], hi
158 ; CHECK: csel    [[CMP:w[0-9]+]], [[LOCMP]], [[HICMP]], eq
159 ; CHECK: cmp     [[CMP]], #0
160 ; CHECK-DAG: csel    [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, ne
161 ; CHECK-DAG: csel    [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, ne
162 ; CHECK: stlxp  [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
163 ; CHECK: cbnz   [[SCRATCH_RES]], [[LABEL]]
164
165 ; CHECK-DAG: str    [[DEST_REGHI]]
166 ; CHECK-DAG: str    [[DEST_REGLO]]
167   %val = atomicrmw umax i128* %p, i128 %bits seq_cst
168   store i128 %val, i128* @var, align 16
169   ret void
170 }
171
172 define i128 @atomic_load_seq_cst(i128* %p) {
173 ; CHECK-LABEL: atomic_load_seq_cst:
174 ; CHECK-NOT: dmb
175 ; CHECK-LABEL: ldaxp
176 ; CHECK-NOT: dmb
177    %r = load atomic i128* %p seq_cst, align 16
178    ret i128 %r
179 }
180
181 define i128 @atomic_load_relaxed(i128* %p) {
182 ; CHECK-LABEL: atomic_load_relaxed:
183 ; CHECK-NOT: dmb
184 ; CHECK: ldxp [[LO:x[0-9]+]], [[HI:x[0-9]+]], [x0]
185 ; CHECK-NOT: dmb
186    %r = load atomic i128* %p monotonic, align 16
187    ret i128 %r
188 }
189
190
191 define void @atomic_store_seq_cst(i128 %in, i128* %p) {
192 ; CHECK-LABEL: atomic_store_seq_cst:
193 ; CHECK-NOT: dmb
194 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
195 ; CHECK: ldaxp xzr, xzr, [x2]
196 ; CHECK: stlxp [[SUCCESS:w[0-9]+]], x0, x1, [x2]
197 ; CHECK: cbnz [[SUCCESS]], [[LABEL]]
198 ; CHECK-NOT: dmb
199    store atomic i128 %in, i128* %p seq_cst, align 16
200    ret void
201 }
202
203 define void @atomic_store_release(i128 %in, i128* %p) {
204 ; CHECK-LABEL: atomic_store_release:
205 ; CHECK-NOT: dmb
206 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
207 ; CHECK: ldxp xzr, xzr, [x2]
208 ; CHECK: stlxp [[SUCCESS:w[0-9]+]], x0, x1, [x2]
209 ; CHECK: cbnz [[SUCCESS]], [[LABEL]]
210 ; CHECK-NOT: dmb
211    store atomic i128 %in, i128* %p release, align 16
212    ret void
213 }
214
215 define void @atomic_store_relaxed(i128 %in, i128* %p) {
216 ; CHECK-LABEL: atomic_store_relaxed:
217 ; CHECK-NOT: dmb
218 ; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
219 ; CHECK: ldxp xzr, xzr, [x2]
220 ; CHECK: stxp [[SUCCESS:w[0-9]+]], x0, x1, [x2]
221 ; CHECK: cbnz [[SUCCESS]], [[LABEL]]
222 ; CHECK-NOT: dmb
223    store atomic i128 %in, i128* %p unordered, align 16
224    ret void
225 }