• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, 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, 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, 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, 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, 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, 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, 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
145; Check generating the comparison result.
146; CHECK-LABEL: f13
147; CHECK: cs %r2, %r3, 0(%r4)
148; CHECK-NEXT: ipm %r2
149; CHECK-NEXT: afi %r2, -268435456
150; CHECK-NEXT: srl %r2, 31
151; CHECK: br %r14
152define i32 @f13(i32 %cmp, i32 %swap, i32 *%src) {
153  %pairval = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst
154  %val = extractvalue { i32, i1 } %pairval, 1
155  %res = zext i1 %val to i32
156  ret i32 %res
157}
158
159declare void @g()
160
161; Check using the comparison result for a branch.
162; CHECK-LABEL: f14
163; CHECK: cs %r2, %r3, 0(%r4)
164; CHECK-NEXT: jge g
165; CHECK: br %r14
166define void @f14(i32 %cmp, i32 %swap, i32 *%src) {
167  %pairval = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst
168  %cond = extractvalue { i32, i1 } %pairval, 1
169  br i1 %cond, label %call, label %exit
170
171call:
172  tail call void @g()
173  br label %exit
174
175exit:
176  ret void
177}
178
179; ... and the same with the inverted direction.
180; CHECK-LABEL: f15
181; CHECK: cs %r2, %r3, 0(%r4)
182; CHECK-NEXT: jgl g
183; CHECK: br %r14
184define void @f15(i32 %cmp, i32 %swap, i32 *%src) {
185  %pairval = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst
186  %cond = extractvalue { i32, i1 } %pairval, 1
187  br i1 %cond, label %exit, label %call
188
189call:
190  tail call void @g()
191  br label %exit
192
193exit:
194  ret void
195}
196
197