1 ; Test 64-bit compare and swap.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5 ; Check CDSG without a displacement.
6 define i128 @f1(i128 %cmp, i128 %swap, i128 *%src) {
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)
16 %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
17 %val = extractvalue { i128, i1 } %pairval, 0
21 ; Check the high end of the aligned CDSG range.
22 define i128 @f2(i128 %cmp, i128 %swap, i128 *%src) {
24 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 524272(%r5)
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
32 ; Check the next doubleword up, which needs separate address logic.
33 ; Other sequences besides this one would be OK.
34 define i128 @f3(i128 %cmp, i128 %swap, i128 *%src) {
36 ; CHECK: agfi %r5, 524288
37 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
45 ; Check the high end of the negative aligned CDSG range.
46 define i128 @f4(i128 %cmp, i128 %swap, i128 *%src) {
48 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -16(%r5)
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
56 ; Check the low end of the CDSG range.
57 define i128 @f5(i128 %cmp, i128 %swap, i128 *%src) {
59 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -524288(%r5)
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
67 ; Check the next doubleword down, which needs separate address logic.
68 ; Other sequences besides this one would be OK.
69 define i128 @f6(i128 %cmp, i128 %swap, i128 *%src) {
71 ; CHECK: agfi %r5, -524304
72 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
80 ; Check that CDSG does not allow an index.
81 define i128 @f7(i128 %cmp, i128 %swap, i64 %src, i64 %index) {
84 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
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
93 ; Check that a constant %cmp value is loaded into a register first.
94 define i128 @f8(i128 %swap, i128 *%ptr) {
96 ; CHECK: lghi {{%r[0-9]+}}, 1001
97 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
99 %pairval = cmpxchg i128 *%ptr, i128 1001, i128 %swap seq_cst seq_cst
100 %val = extractvalue { i128, i1 } %pairval, 0
104 ; Check that a constant %swap value is loaded into a register first.
105 define i128 @f9(i128 %cmp, i128 *%ptr) {
107 ; CHECK: lghi {{%r[0-9]+}}, 1002
108 ; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
110 %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 1002 seq_cst seq_cst
111 %val = extractvalue { i128, i1 } %pairval, 0
115 ; Check generating the comparison result.
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
126 define 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
135 ; Check using the comparison result for a branch.
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:\.[^ ]*]]
146 define 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
159 ; ... and the same with the inverted direction.
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:\.[^ ]*]]
170 define 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