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