1; 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}
114
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}
132
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
183