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