1 ; Test 128-bit compare and swap.
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
6 ; Check CDSG without a displacement.
7 define i128 @f1(i128 %cmp, i128 %swap, ptr %src) {
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)
17 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst
18 %val = extractvalue { i128, i1 } %pairval, 0
22 ; Check the high end of the aligned CDSG range.
23 define i128 @f2(i128 %cmp, i128 %swap, ptr %src) {
25 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 524272(%r5)
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
33 ; Check the next doubleword up, which needs separate address logic.
34 ; Other sequences besides this one would be OK.
35 define i128 @f3(i128 %cmp, i128 %swap, ptr %src) {
37 ; CHECK: agfi %r5, 524288
38 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
46 ; Check the high end of the negative aligned CDSG range.
47 define i128 @f4(i128 %cmp, i128 %swap, ptr %src) {
49 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -16(%r5)
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
57 ; Check the low end of the CDSG range.
58 define i128 @f5(i128 %cmp, i128 %swap, ptr %src) {
60 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -524288(%r5)
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
68 ; Check the next doubleword down, which needs separate address logic.
69 ; Other sequences besides this one would be OK.
70 define i128 @f6(i128 %cmp, i128 %swap, ptr %src) {
72 ; CHECK: agfi %r5, -524304
73 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
81 ; Check that CDSG does not allow an index.
82 define i128 @f7(i128 %cmp, i128 %swap, i64 %src, i64 %index) {
85 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
94 ; Check that a constant %cmp value is loaded into a register first.
95 define i128 @f8(i128 %swap, ptr %ptr) {
97 ; CHECK: lghi {{%r[0-9]+}}, 1001
98 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
100 %pairval = cmpxchg ptr %ptr, i128 1001, i128 %swap seq_cst seq_cst
101 %val = extractvalue { i128, i1 } %pairval, 0
105 ; Check that a constant %swap value is loaded into a register first.
106 define i128 @f9(i128 %cmp, ptr %ptr) {
108 ; CHECK: lghi {{%r[0-9]+}}, 1002
109 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
111 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 1002 seq_cst seq_cst
112 %val = extractvalue { i128, i1 } %pairval, 0
116 ; Check generating the comparison result.
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
129 define 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
138 ; Check using the comparison result for a branch.
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:\.[^ ]*]]
149 define 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
162 ; ... and the same with the inverted direction.
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:\.[^ ]*]]
173 define 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