1; Test 32-bit atomic minimum and maximum.  Here we match the z10 versions,
2; which can't use LOCR.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
5
6; Check signed minium.
7define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
8; CHECK-LABEL: f1:
9; CHECK: l %r2, 0(%r3)
10; CHECK: j [[LOOP:\.[^:]*]]
11; CHECK: [[BB1:\.[^:]*]]:
12; CHECK: cs %r2, [[NEW:%r[0-9]+]], 0(%r3)
13; CHECK: ber %r14
14; CHECK: [[LOOP]]:
15; CHECK: lr [[NEW]], %r2
16; CHECK: crjle %r2, %r4, [[KEEP:\..*]]
17; CHECK: lr [[NEW]], %r4
18; CHECK: j [[BB1]]
19  %res = atomicrmw min i32 *%src, i32 %b seq_cst
20  ret i32 %res
21}
22
23; Check signed maximum.
24define i32 @f2(i32 %dummy, i32 *%src, i32 %b) {
25; CHECK-LABEL: f2:
26; CHECK: l %r2, 0(%r3)
27; CHECK: j [[LOOP:\.[^:]*]]
28; CHECK: [[BB1:\.[^:]*]]:
29; CHECK: cs %r2, [[NEW:%r[0-9]+]], 0(%r3)
30; CHECK: ber %r14
31; CHECK: [[LOOP]]:
32; CHECK: lr [[NEW]], %r2
33; CHECK: crjhe %r2, %r4, [[KEEP:\..*]]
34; CHECK: lr [[NEW]], %r4
35; CHECK: j [[BB1]]
36  %res = atomicrmw max i32 *%src, i32 %b seq_cst
37  ret i32 %res
38}
39
40; Check unsigned minimum.
41define i32 @f3(i32 %dummy, i32 *%src, i32 %b) {
42; CHECK-LABEL: f3:
43; CHECK: l %r2, 0(%r3)
44; CHECK: j [[LOOP:\.[^:]*]]
45; CHECK: [[BB1:\.[^:]*]]:
46; CHECK: cs %r2, [[NEW:%r[0-9]+]], 0(%r3)
47; CHECK: ber %r14
48; CHECK: [[LOOP]]:
49; CHECK: lr [[NEW]], %r2
50; CHECK: clrjle %r2, %r4, [[KEEP:\..*]]
51; CHECK: lr [[NEW]], %r4
52; CHECK: j [[BB1]]
53  %res = atomicrmw umin i32 *%src, i32 %b seq_cst
54  ret i32 %res
55}
56
57; Check unsigned maximum.
58define i32 @f4(i32 %dummy, i32 *%src, i32 %b) {
59; CHECK-LABEL: f4:
60; CHECK: l %r2, 0(%r3)
61; CHECK: j [[LOOP:\.[^:]*]]
62; CHECK: [[BB1:\.[^:]*]]:
63; CHECK: cs %r2, [[NEW:%r[0-9]+]], 0(%r3)
64; CHECK: ber %r14
65; CHECK: [[LOOP]]:
66; CHECK: lr [[NEW]], %r2
67; CHECK: clrjhe %r2, %r4, [[KEEP:\..*]]
68; CHECK: lr [[NEW]], %r4
69; CHECK: j [[BB1]]
70  %res = atomicrmw umax i32 *%src, i32 %b seq_cst
71  ret i32 %res
72}
73
74; Check the high end of the aligned CS range.
75define i32 @f5(i32 %dummy, i32 *%src, i32 %b) {
76; CHECK-LABEL: f5:
77; CHECK: l %r2, 4092(%r3)
78; CHECK: cs %r2, {{%r[0-9]+}}, 4092(%r3)
79; CHECK: ber %r14
80  %ptr = getelementptr i32, i32 *%src, i64 1023
81  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
82  ret i32 %res
83}
84
85; Check the next word up, which requires CSY.
86define i32 @f6(i32 %dummy, i32 *%src, i32 %b) {
87; CHECK-LABEL: f6:
88; CHECK: ly %r2, 4096(%r3)
89; CHECK: csy %r2, {{%r[0-9]+}}, 4096(%r3)
90; CHECK: ber %r14
91  %ptr = getelementptr i32, i32 *%src, i64 1024
92  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
93  ret i32 %res
94}
95
96; Check the high end of the aligned CSY range.
97define i32 @f7(i32 %dummy, i32 *%src, i32 %b) {
98; CHECK-LABEL: f7:
99; CHECK: ly %r2, 524284(%r3)
100; CHECK: csy %r2, {{%r[0-9]+}}, 524284(%r3)
101; CHECK: ber %r14
102  %ptr = getelementptr i32, i32 *%src, i64 131071
103  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
104  ret i32 %res
105}
106
107; Check the next word up, which needs separate address logic.
108define i32 @f8(i32 %dummy, i32 *%src, i32 %b) {
109; CHECK-LABEL: f8:
110; CHECK: agfi %r3, 524288
111; CHECK: l %r2, 0(%r3)
112; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
113; CHECK: ber %r14
114  %ptr = getelementptr i32, i32 *%src, i64 131072
115  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
116  ret i32 %res
117}
118
119; Check the high end of the negative aligned CSY range.
120define i32 @f9(i32 %dummy, i32 *%src, i32 %b) {
121; CHECK-LABEL: f9:
122; CHECK: ly %r2, -4(%r3)
123; CHECK: csy %r2, {{%r[0-9]+}}, -4(%r3)
124; CHECK: ber %r14
125  %ptr = getelementptr i32, i32 *%src, i64 -1
126  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
127  ret i32 %res
128}
129
130; Check the low end of the CSY range.
131define i32 @f10(i32 %dummy, i32 *%src, i32 %b) {
132; CHECK-LABEL: f10:
133; CHECK: ly %r2, -524288(%r3)
134; CHECK: csy %r2, {{%r[0-9]+}}, -524288(%r3)
135; CHECK: ber %r14
136  %ptr = getelementptr i32, i32 *%src, i64 -131072
137  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
138  ret i32 %res
139}
140
141; Check the next word down, which needs separate address logic.
142define i32 @f11(i32 %dummy, i32 *%src, i32 %b) {
143; CHECK-LABEL: f11:
144; CHECK: agfi %r3, -524292
145; CHECK: l %r2, 0(%r3)
146; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
147; CHECK: ber %r14
148  %ptr = getelementptr i32, i32 *%src, i64 -131073
149  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
150  ret i32 %res
151}
152
153; Check that indexed addresses are not allowed.
154define i32 @f12(i32 %dummy, i64 %base, i64 %index, i32 %b) {
155; CHECK-LABEL: f12:
156; CHECK: agr %r3, %r4
157; CHECK: l %r2, 0(%r3)
158; CHECK: cs %r2, {{%r[0-9]+}}, 0(%r3)
159; CHECK: ber %r14
160  %add = add i64 %base, %index
161  %ptr = inttoptr i64 %add to i32 *
162  %res = atomicrmw min i32 *%ptr, i32 %b seq_cst
163  ret i32 %res
164}
165
166; Check that constants are handled.
167define i32 @f13(i32 %dummy, i32 *%ptr) {
168; CHECK-LABEL: f13:
169; CHECK: lhi [[LIMIT:%r[0-9]+]], 42
170; CHECK: j [[LOOP:\.[^:]*]]
171; CHECK: [[BB1:\.[^:]*]]:
172; CHECK: cs %r2, [[NEW:%r[0-9]+]], 0(%r3)
173; CHECK: ber %r14
174; CHECK: [[LOOP]]:
175; CHECK: lr [[NEW]], %r2
176; CHECK: crjle %r2, [[LIMIT]], [[KEEP:\..*]]
177; CHECK: lhi [[NEW]], 42
178; CHECK: j [[BB1]]
179  %res = atomicrmw min i32 *%ptr, i32 42 seq_cst
180  ret i32 %res
181}
182