1; Test 32-bit compare and swap.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5; Check the low end of the CS range.
6define i32 @f1(i32 %cmp, i32 %swap, i32 *%src) {
7; CHECK-LABEL: f1:
8; CHECK: cs %r2, %r3, 0(%r4)
9; CHECK: br %r14
10  %pair = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst
11  %val = extractvalue { i32, i1 } %pair, 0
12  ret i32 %val
13}
14
15; Check the high end of the aligned CS range.
16define i32 @f2(i32 %cmp, i32 %swap, i32 *%src) {
17; CHECK-LABEL: f2:
18; CHECK: cs %r2, %r3, 4092(%r4)
19; CHECK: br %r14
20  %ptr = getelementptr i32 *%src, i64 1023
21  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
22  %val = extractvalue { i32, i1 } %pair, 0
23  ret i32 %val
24}
25
26; Check the next word up, which should use CSY instead of CS.
27define i32 @f3(i32 %cmp, i32 %swap, i32 *%src) {
28; CHECK-LABEL: f3:
29; CHECK: csy %r2, %r3, 4096(%r4)
30; CHECK: br %r14
31  %ptr = getelementptr i32 *%src, i64 1024
32  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
33  %val = extractvalue { i32, i1 } %pair, 0
34  ret i32 %val
35}
36
37; Check the high end of the aligned CSY range.
38define i32 @f4(i32 %cmp, i32 %swap, i32 *%src) {
39; CHECK-LABEL: f4:
40; CHECK: csy %r2, %r3, 524284(%r4)
41; CHECK: br %r14
42  %ptr = getelementptr i32 *%src, i64 131071
43  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
44  %val = extractvalue { i32, i1 } %pair, 0
45  ret i32 %val
46}
47
48; Check the next word up, which needs separate address logic.
49; Other sequences besides this one would be OK.
50define i32 @f5(i32 %cmp, i32 %swap, i32 *%src) {
51; CHECK-LABEL: f5:
52; CHECK: agfi %r4, 524288
53; CHECK: cs %r2, %r3, 0(%r4)
54; CHECK: br %r14
55  %ptr = getelementptr i32 *%src, i64 131072
56  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
57  %val = extractvalue { i32, i1 } %pair, 0
58  ret i32 %val
59}
60
61; Check the high end of the negative aligned CSY range.
62define i32 @f6(i32 %cmp, i32 %swap, i32 *%src) {
63; CHECK-LABEL: f6:
64; CHECK: csy %r2, %r3, -4(%r4)
65; CHECK: br %r14
66  %ptr = getelementptr i32 *%src, i64 -1
67  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
68  %val = extractvalue { i32, i1 } %pair, 0
69  ret i32 %val
70}
71
72; Check the low end of the CSY range.
73define i32 @f7(i32 %cmp, i32 %swap, i32 *%src) {
74; CHECK-LABEL: f7:
75; CHECK: csy %r2, %r3, -524288(%r4)
76; CHECK: br %r14
77  %ptr = getelementptr i32 *%src, i64 -131072
78  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
79  %val = extractvalue { i32, i1 } %pair, 0
80  ret i32 %val
81}
82
83; Check the next word down, which needs separate address logic.
84; Other sequences besides this one would be OK.
85define i32 @f8(i32 %cmp, i32 %swap, i32 *%src) {
86; CHECK-LABEL: f8:
87; CHECK: agfi %r4, -524292
88; CHECK: cs %r2, %r3, 0(%r4)
89; CHECK: br %r14
90  %ptr = getelementptr i32 *%src, i64 -131073
91  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
92  %val = extractvalue { i32, i1 } %pair, 0
93  ret i32 %val
94}
95
96; Check that CS does not allow an index.
97define i32 @f9(i32 %cmp, i32 %swap, i64 %src, i64 %index) {
98; CHECK-LABEL: f9:
99; CHECK: agr %r4, %r5
100; CHECK: cs %r2, %r3, 0(%r4)
101; CHECK: br %r14
102  %add1 = add i64 %src, %index
103  %ptr = inttoptr i64 %add1 to i32 *
104  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
105  %val = extractvalue { i32, i1 } %pair, 0
106  ret i32 %val
107}
108
109; Check that CSY does not allow an index.
110define i32 @f10(i32 %cmp, i32 %swap, i64 %src, i64 %index) {
111; CHECK-LABEL: f10:
112; CHECK: agr %r4, %r5
113; CHECK: csy %r2, %r3, 4096(%r4)
114; CHECK: br %r14
115  %add1 = add i64 %src, %index
116  %add2 = add i64 %add1, 4096
117  %ptr = inttoptr i64 %add2 to i32 *
118  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst
119  %val = extractvalue { i32, i1 } %pair, 0
120  ret i32 %val
121}
122
123; Check that a constant %cmp value is loaded into a register first.
124define i32 @f11(i32 %dummy, i32 %swap, i32 *%ptr) {
125; CHECK-LABEL: f11:
126; CHECK: lhi %r2, 1001
127; CHECK: cs %r2, %r3, 0(%r4)
128; CHECK: br %r14
129  %pair = cmpxchg i32 *%ptr, i32 1001, i32 %swap seq_cst seq_cst
130  %val = extractvalue { i32, i1 } %pair, 0
131  ret i32 %val
132}
133
134; Check that a constant %swap value is loaded into a register first.
135define i32 @f12(i32 %cmp, i32 *%ptr) {
136; CHECK-LABEL: f12:
137; CHECK: lhi [[SWAP:%r[0-9]+]], 1002
138; CHECK: cs %r2, [[SWAP]], 0(%r3)
139; CHECK: br %r14
140  %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 1002 seq_cst seq_cst
141  %val = extractvalue { i32, i1 } %pair, 0
142  ret i32 %val
143}
144