blob: b3168e2a6b08e0d03e08343568a30c75b96ebeef [file] [log] [blame]
Ulrich Weiganda11f63a2017-08-04 18:57:58 +00001; Test 64-bit compare and swap.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5; Check CDSG without a displacement.
6define i128 @f1(i128 %cmp, i128 %swap, i128 *%src) {
7; CHECK-LABEL: f1:
8; CHECK-DAG: lg %r1, 8(%r4)
9; CHECK-DAG: lg %r0, 0(%r4)
10; CHECK-DAG: lg %r13, 8(%r3)
11; CHECK-DAG: lg %r12, 0(%r3)
12; CHECK: cdsg %r12, %r0, 0(%r5)
13; CHECK-DAG: stg %r13, 8(%r2)
14; CHECK-DAG: stg %r12, 0(%r2)
15; CHECK: br %r14
16 %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
17 %val = extractvalue { i128, i1 } %pairval, 0
18 ret i128 %val
19}
20
21; Check the high end of the aligned CDSG range.
22define i128 @f2(i128 %cmp, i128 %swap, i128 *%src) {
23; CHECK-LABEL: f2:
24; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 524272(%r5)
25; CHECK: br %r14
26 %ptr = getelementptr i128, i128 *%src, i128 32767
27 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
28 %val = extractvalue { i128, i1 } %pairval, 0
29 ret i128 %val
30}
31
32; Check the next doubleword up, which needs separate address logic.
33; Other sequences besides this one would be OK.
34define i128 @f3(i128 %cmp, i128 %swap, i128 *%src) {
35; CHECK-LABEL: f3:
36; CHECK: agfi %r5, 524288
37; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
38; CHECK: br %r14
39 %ptr = getelementptr i128, i128 *%src, i128 32768
40 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
41 %val = extractvalue { i128, i1 } %pairval, 0
42 ret i128 %val
43}
44
45; Check the high end of the negative aligned CDSG range.
46define i128 @f4(i128 %cmp, i128 %swap, i128 *%src) {
47; CHECK-LABEL: f4:
48; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -16(%r5)
49; CHECK: br %r14
50 %ptr = getelementptr i128, i128 *%src, i128 -1
51 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
52 %val = extractvalue { i128, i1 } %pairval, 0
53 ret i128 %val
54}
55
56; Check the low end of the CDSG range.
57define i128 @f5(i128 %cmp, i128 %swap, i128 *%src) {
58; CHECK-LABEL: f5:
59; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -524288(%r5)
60; CHECK: br %r14
61 %ptr = getelementptr i128, i128 *%src, i128 -32768
62 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
63 %val = extractvalue { i128, i1 } %pairval, 0
64 ret i128 %val
65}
66
67; Check the next doubleword down, which needs separate address logic.
68; Other sequences besides this one would be OK.
69define i128 @f6(i128 %cmp, i128 %swap, i128 *%src) {
70; CHECK-LABEL: f6:
71; CHECK: agfi %r5, -524304
72; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
73; CHECK: br %r14
74 %ptr = getelementptr i128, i128 *%src, i128 -32769
75 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
76 %val = extractvalue { i128, i1 } %pairval, 0
77 ret i128 %val
78}
79
80; Check that CDSG does not allow an index.
81define i128 @f7(i128 %cmp, i128 %swap, i64 %src, i64 %index) {
82; CHECK-LABEL: f7:
83; CHECK: agr %r5, %r6
84; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
85; CHECK: br %r14
86 %add1 = add i64 %src, %index
87 %ptr = inttoptr i64 %add1 to i128 *
88 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
89 %val = extractvalue { i128, i1 } %pairval, 0
90 ret i128 %val
91}
92
93; Check that a constant %cmp value is loaded into a register first.
94define i128 @f8(i128 %swap, i128 *%ptr) {
95; CHECK-LABEL: f8:
96; CHECK: lghi {{%r[0-9]+}}, 1001
97; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
98; CHECK: br %r14
99 %pairval = cmpxchg i128 *%ptr, i128 1001, i128 %swap seq_cst seq_cst
100 %val = extractvalue { i128, i1 } %pairval, 0
101 ret i128 %val
102}
103
104; Check that a constant %swap value is loaded into a register first.
105define i128 @f9(i128 %cmp, i128 *%ptr) {
106; CHECK-LABEL: f9:
107; CHECK: lghi {{%r[0-9]+}}, 1002
108; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
109; CHECK: br %r14
110 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 1002 seq_cst seq_cst
111 %val = extractvalue { i128, i1 } %pairval, 0
112 ret i128 %val
113}
Ulrich Weigand0f1de042017-09-28 16:22:54 +0000114
115; Check generating the comparison result.
116; CHECK-LABEL: f10
117; CHECK-DAG: lg %r1, 8(%r3)
118; CHECK-DAG: lg %r0, 0(%r3)
119; CHECK-DAG: lg %r13, 8(%r2)
120; CHECK-DAG: lg %r12, 0(%r2)
121; CHECK: cdsg %r12, %r0, 0(%r4)
122; CHECK-NEXT: ipm %r2
123; CHECK-NEXT: afi %r2, -268435456
124; CHECK-NEXT: srl %r2, 31
125; CHECK: br %r14
126define i32 @f10(i128 %cmp, i128 %swap, i128 *%src) {
127 %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
128 %val = extractvalue { i128, i1 } %pairval, 1
129 %res = zext i1 %val to i32
130 ret i32 %res
131}
Ulrich Weigand31112892018-01-19 20:54:18 +0000132
133declare void @g()
134
135; Check using the comparison result for a branch.
136; CHECK-LABEL: f11
137; CHECK-DAG: lg %r1, 8(%r3)
138; CHECK-DAG: lg %r0, 0(%r3)
139; CHECK-DAG: lg %r13, 8(%r2)
140; CHECK-DAG: lg %r12, 0(%r2)
141; CHECK: cdsg %r12, %r0, 0(%r4)
142; CHECK-NEXT: jl [[LABEL:\.[^ ]*]]
143; CHECK: jg g
144; CHECK: [[LABEL]]:
145; CHECK: br %r14
146define void @f11(i128 %cmp, i128 %swap, i128 *%src) {
147 %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
148 %cond = extractvalue { i128, i1 } %pairval, 1
149 br i1 %cond, label %call, label %exit
150
151call:
152 tail call void @g()
153 br label %exit
154
155exit:
156 ret void
157}
158
159; ... and the same with the inverted direction.
160; CHECK-LABEL: f12
161; CHECK-DAG: lg %r1, 8(%r3)
162; CHECK-DAG: lg %r0, 0(%r3)
163; CHECK-DAG: lg %r13, 8(%r2)
164; CHECK-DAG: lg %r12, 0(%r2)
165; CHECK: cdsg %r12, %r0, 0(%r4)
166; CHECK-NEXT: jl [[LABEL:\.[^ ]*]]
167; CHECK: br %r14
168; CHECK: [[LABEL]]:
169; CHECK: jg g
170define void @f12(i128 %cmp, i128 %swap, i128 *%src) {
171 %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
172 %cond = extractvalue { i128, i1 } %pairval, 1
173 br i1 %cond, label %exit, label %call
174
175call:
176 tail call void @g()
177 br label %exit
178
179exit:
180 ret void
181}
182