blob: a0039a323778941be7460dfafcf8493074790a92 [file] [log] [blame]
Tim Northover00ed9962014-03-29 10:18:08 +00001; RUN: llc < %s -march=arm64 -mtriple=arm64-linux-gnu -verify-machineinstrs | 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; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
8; CHECK: ldaxp [[RESULTLO:x[0-9]+]], [[RESULTHI:x[0-9]+]], [x0]
9; CHECK: cmp [[RESULTLO]], x2
10; CHECK: sbc xzr, [[RESULTHI]], x3
11; CHECK: b.ne [[LABEL2:.?LBB[0-9]+_[0-9]+]]
12; CHECK: stxp [[SCRATCH_RES:w[0-9]+]], x4, x5, [x0]
13; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
14; CHECK: [[LABEL2]]:
15 %val = cmpxchg i128* %p, i128 %oldval, i128 %newval acquire acquire
16 ret i128 %val
17}
18
19define void @fetch_and_nand(i128* %p, i128 %bits) {
20; CHECK-LABEL: fetch_and_nand:
21; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
22; CHECK: ldxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
23; CHECK: bic [[SCRATCH_REGLO:x[0-9]+]], x2, [[DEST_REGLO]]
24; CHECK: bic [[SCRATCH_REGHI:x[0-9]+]], x3, [[DEST_REGHI]]
25; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
26; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
27
28; CHECK: str [[DEST_REGHI]]
29; CHECK: str [[DEST_REGLO]]
30 %val = atomicrmw nand i128* %p, i128 %bits release
31 store i128 %val, i128* @var, align 16
32 ret void
33}
34
35define void @fetch_and_or(i128* %p, i128 %bits) {
36; CHECK-LABEL: fetch_and_or:
37; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
38; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
39; CHECK: orr [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
40; CHECK: orr [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
41; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
42; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
43
44; CHECK: str [[DEST_REGHI]]
45; CHECK: str [[DEST_REGLO]]
46 %val = atomicrmw or i128* %p, i128 %bits seq_cst
47 store i128 %val, i128* @var, align 16
48 ret void
49}
50
51define void @fetch_and_add(i128* %p, i128 %bits) {
52; CHECK-LABEL: fetch_and_add:
53; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
54; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
55; CHECK: adds [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
56; CHECK: adc [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
57; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
58; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
59
60; CHECK: str [[DEST_REGHI]]
61; CHECK: str [[DEST_REGLO]]
62 %val = atomicrmw add i128* %p, i128 %bits seq_cst
63 store i128 %val, i128* @var, align 16
64 ret void
65}
66
67define void @fetch_and_sub(i128* %p, i128 %bits) {
68; CHECK-LABEL: fetch_and_sub:
69; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
70; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
71; CHECK: subs [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2
72; CHECK: sbc [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3
73; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
74; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
75
76; CHECK: str [[DEST_REGHI]]
77; CHECK: str [[DEST_REGLO]]
78 %val = atomicrmw sub i128* %p, i128 %bits seq_cst
79 store i128 %val, i128* @var, align 16
80 ret void
81}
82
83define void @fetch_and_min(i128* %p, i128 %bits) {
84; CHECK-LABEL: fetch_and_min:
85; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
86; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
87; CHECK: cmp [[DEST_REGLO]], x2
88; CHECK: sbc xzr, [[DEST_REGHI]], x3
89; CHECK: csel [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, lt
90; CHECK: csel [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, lt
91; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
92; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
93
94; CHECK: str [[DEST_REGHI]]
95; CHECK: str [[DEST_REGLO]]
96 %val = atomicrmw min i128* %p, i128 %bits seq_cst
97 store i128 %val, i128* @var, align 16
98 ret void
99}
100
101define void @fetch_and_max(i128* %p, i128 %bits) {
102; CHECK-LABEL: fetch_and_max:
103; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
104; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
105; CHECK: cmp [[DEST_REGLO]], x2
106; CHECK: sbc xzr, [[DEST_REGHI]], x3
107; CHECK: csel [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, gt
108; CHECK: csel [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, gt
109; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
110; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
111
112; CHECK: str [[DEST_REGHI]]
113; CHECK: str [[DEST_REGLO]]
114 %val = atomicrmw max i128* %p, i128 %bits seq_cst
115 store i128 %val, i128* @var, align 16
116 ret void
117}
118
119define void @fetch_and_umin(i128* %p, i128 %bits) {
120; CHECK-LABEL: fetch_and_umin:
121; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
122; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
123; CHECK: cmp [[DEST_REGLO]], x2
124; CHECK: sbc xzr, [[DEST_REGHI]], x3
125; CHECK: csel [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, cc
126; CHECK: csel [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, cc
127; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
128; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
129
130; CHECK: str [[DEST_REGHI]]
131; CHECK: str [[DEST_REGLO]]
132 %val = atomicrmw umin i128* %p, i128 %bits seq_cst
133 store i128 %val, i128* @var, align 16
134 ret void
135}
136
137define void @fetch_and_umax(i128* %p, i128 %bits) {
138; CHECK-LABEL: fetch_and_umax:
139; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
140; CHECK: ldaxp [[DEST_REGLO:x[0-9]+]], [[DEST_REGHI:x[0-9]+]], [x0]
141; CHECK: cmp [[DEST_REGLO]], x2
142; CHECK: sbc xzr, [[DEST_REGHI]], x3
143; CHECK: csel [[SCRATCH_REGLO:x[0-9]+]], [[DEST_REGLO]], x2, hi
144; CHECK: csel [[SCRATCH_REGHI:x[0-9]+]], [[DEST_REGHI]], x3, hi
145; CHECK: stlxp [[SCRATCH_RES:w[0-9]+]], [[SCRATCH_REGLO]], [[SCRATCH_REGHI]], [x0]
146; CHECK: cbnz [[SCRATCH_RES]], [[LABEL]]
147
148; CHECK: str [[DEST_REGHI]]
149; CHECK: str [[DEST_REGLO]]
150 %val = atomicrmw umax i128* %p, i128 %bits seq_cst
151 store i128 %val, i128* @var, align 16
152 ret void
153}
154
155define i128 @atomic_load_seq_cst(i128* %p) {
156; CHECK-LABEL: atomic_load_seq_cst:
157; CHECK-NOT: dmb
158; CHECK-LABEL: ldaxp
159; CHECK-NOT: dmb
160 %r = load atomic i128* %p seq_cst, align 16
161 ret i128 %r
162}
163
164define i128 @atomic_load_relaxed(i128* %p) {
165; CHECK-LABEL: atomic_load_relaxed:
166; CHECK-NOT: dmb
167; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
168; CHECK: ldxp [[LO:x[0-9]+]], [[HI:x[0-9]+]], [x0]
169; CHECK: orr [[SAMELO:x[0-9]+]], [[LO]], xzr
170; CHECK: orr [[SAMEHI:x[0-9]+]], [[HI]], xzr
171; CHECK: stxp [[SUCCESS:w[0-9]+]], [[SAMELO]], [[SAMEHI]], [x0]
172; CHECK: cbnz [[SUCCESS]], [[LABEL]]
173; CHECK-NOT: dmb
174 %r = load atomic i128* %p monotonic, align 16
175 ret i128 %r
176}
177
178
179define void @atomic_store_seq_cst(i128 %in, i128* %p) {
180; CHECK-LABEL: atomic_store_seq_cst:
181; CHECK-NOT: dmb
182; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
183; CHECK: ldaxp xzr, xzr, [x2]
184; CHECK: stlxp [[SUCCESS:w[0-9]+]], x0, x1, [x2]
185; CHECK: cbnz [[SUCCESS]], [[LABEL]]
186; CHECK-NOT: dmb
187 store atomic i128 %in, i128* %p seq_cst, align 16
188 ret void
189}
190
191define void @atomic_store_release(i128 %in, i128* %p) {
192; CHECK-LABEL: atomic_store_release:
193; CHECK-NOT: dmb
194; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
195; CHECK: ldxp 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 release, align 16
200 ret void
201}
202
203define void @atomic_store_relaxed(i128 %in, i128* %p) {
204; CHECK-LABEL: atomic_store_relaxed:
205; CHECK-NOT: dmb
206; CHECK: [[LABEL:.?LBB[0-9]+_[0-9]+]]:
207; CHECK: ldxp xzr, xzr, [x2]
208; CHECK: stxp [[SUCCESS:w[0-9]+]], x0, x1, [x2]
209; CHECK: cbnz [[SUCCESS]], [[LABEL]]
210; CHECK-NOT: dmb
211 store atomic i128 %in, i128* %p unordered, align 16
212 ret void
213}