xref: /llvm-project/llvm/test/CodeGen/SystemZ/atomicrmw-minmax-03.ll (revision 435ba72afda756183a1ddc7a3a160152ad630951)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2; Test 32-bit atomic minimum and maximum.  Here we match the z10 versions,
3; which can't use LOCR.
4;
5; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
6
7; Todo: If-converter no longer producing CondReturns (with AtomicExpand pass).
8
9; Check signed minimum.
10define i32 @f1(i32 %dummy, ptr %src, i32 %b) {
11; CHECK-LABEL: f1:
12; CHECK:       # %bb.0:
13; CHECK-NEXT:    l %r2, 0(%r3)
14; CHECK-NEXT:    j .LBB0_2
15; CHECK-NEXT:  .LBB0_1: # %atomicrmw.start
16; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
17; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
18; CHECK-NEXT:    je .LBB0_4
19; CHECK-NEXT:  .LBB0_2: # %atomicrmw.start
20; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
21; CHECK-NEXT:    lr %r0, %r2
22; CHECK-NEXT:    crjle %r2, %r4, .LBB0_1
23; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
24; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
25; CHECK-NEXT:    lr %r0, %r4
26; CHECK-NEXT:    j .LBB0_1
27; CHECK-NEXT:  .LBB0_4: # %atomicrmw.end
28; CHECK-NEXT:    br %r14
29  %res = atomicrmw min ptr %src, i32 %b seq_cst
30  ret i32 %res
31}
32
33; Check signed maximum.
34define i32 @f2(i32 %dummy, ptr %src, i32 %b) {
35; CHECK-LABEL: f2:
36; CHECK:       # %bb.0:
37; CHECK-NEXT:    l %r2, 0(%r3)
38; CHECK-NEXT:    j .LBB1_2
39; CHECK-NEXT:  .LBB1_1: # %atomicrmw.start
40; CHECK-NEXT:    # in Loop: Header=BB1_2 Depth=1
41; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
42; CHECK-NEXT:    je .LBB1_4
43; CHECK-NEXT:  .LBB1_2: # %atomicrmw.start
44; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
45; CHECK-NEXT:    lr %r0, %r2
46; CHECK-NEXT:    crjh %r2, %r4, .LBB1_1
47; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
48; CHECK-NEXT:    # in Loop: Header=BB1_2 Depth=1
49; CHECK-NEXT:    lr %r0, %r4
50; CHECK-NEXT:    j .LBB1_1
51; CHECK-NEXT:  .LBB1_4: # %atomicrmw.end
52; CHECK-NEXT:    br %r14
53  %res = atomicrmw max ptr %src, i32 %b seq_cst
54  ret i32 %res
55}
56
57; Check unsigned minimum.
58define i32 @f3(i32 %dummy, ptr %src, i32 %b) {
59; CHECK-LABEL: f3:
60; CHECK:       # %bb.0:
61; CHECK-NEXT:    l %r2, 0(%r3)
62; CHECK-NEXT:    j .LBB2_2
63; CHECK-NEXT:  .LBB2_1: # %atomicrmw.start
64; CHECK-NEXT:    # in Loop: Header=BB2_2 Depth=1
65; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
66; CHECK-NEXT:    je .LBB2_4
67; CHECK-NEXT:  .LBB2_2: # %atomicrmw.start
68; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
69; CHECK-NEXT:    lr %r0, %r2
70; CHECK-NEXT:    clrjle %r2, %r4, .LBB2_1
71; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
72; CHECK-NEXT:    # in Loop: Header=BB2_2 Depth=1
73; CHECK-NEXT:    lr %r0, %r4
74; CHECK-NEXT:    j .LBB2_1
75; CHECK-NEXT:  .LBB2_4: # %atomicrmw.end
76; CHECK-NEXT:    br %r14
77  %res = atomicrmw umin ptr %src, i32 %b seq_cst
78  ret i32 %res
79}
80
81; Check unsigned maximum.
82define i32 @f4(i32 %dummy, ptr %src, i32 %b) {
83; CHECK-LABEL: f4:
84; CHECK:       # %bb.0:
85; CHECK-NEXT:    l %r2, 0(%r3)
86; CHECK-NEXT:    j .LBB3_2
87; CHECK-NEXT:  .LBB3_1: # %atomicrmw.start
88; CHECK-NEXT:    # in Loop: Header=BB3_2 Depth=1
89; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
90; CHECK-NEXT:    je .LBB3_4
91; CHECK-NEXT:  .LBB3_2: # %atomicrmw.start
92; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
93; CHECK-NEXT:    lr %r0, %r2
94; CHECK-NEXT:    clrjh %r2, %r4, .LBB3_1
95; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
96; CHECK-NEXT:    # in Loop: Header=BB3_2 Depth=1
97; CHECK-NEXT:    lr %r0, %r4
98; CHECK-NEXT:    j .LBB3_1
99; CHECK-NEXT:  .LBB3_4: # %atomicrmw.end
100; CHECK-NEXT:    br %r14
101  %res = atomicrmw umax ptr %src, i32 %b seq_cst
102  ret i32 %res
103}
104
105; Check the high end of the aligned CS range.
106define i32 @f5(i32 %dummy, ptr %src, i32 %b) {
107; CHECK-LABEL: f5:
108; CHECK:       # %bb.0:
109; CHECK-NEXT:    l %r2, 4092(%r3)
110; CHECK-NEXT:    j .LBB4_2
111; CHECK-NEXT:  .LBB4_1: # %atomicrmw.start
112; CHECK-NEXT:    # in Loop: Header=BB4_2 Depth=1
113; CHECK-NEXT:    cs %r2, %r0, 4092(%r3)
114; CHECK-NEXT:    je .LBB4_4
115; CHECK-NEXT:  .LBB4_2: # %atomicrmw.start
116; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
117; CHECK-NEXT:    lr %r0, %r2
118; CHECK-NEXT:    crjle %r2, %r4, .LBB4_1
119; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
120; CHECK-NEXT:    # in Loop: Header=BB4_2 Depth=1
121; CHECK-NEXT:    lr %r0, %r4
122; CHECK-NEXT:    j .LBB4_1
123; CHECK-NEXT:  .LBB4_4: # %atomicrmw.end
124; CHECK-NEXT:    br %r14
125  %ptr = getelementptr i32, ptr %src, i64 1023
126  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
127  ret i32 %res
128}
129
130; Check the next word up, which requires CSY.
131define i32 @f6(i32 %dummy, ptr %src, i32 %b) {
132; CHECK-LABEL: f6:
133; CHECK:       # %bb.0:
134; CHECK-NEXT:    ly %r2, 4096(%r3)
135; CHECK-NEXT:    j .LBB5_2
136; CHECK-NEXT:  .LBB5_1: # %atomicrmw.start
137; CHECK-NEXT:    # in Loop: Header=BB5_2 Depth=1
138; CHECK-NEXT:    csy %r2, %r0, 4096(%r3)
139; CHECK-NEXT:    je .LBB5_4
140; CHECK-NEXT:  .LBB5_2: # %atomicrmw.start
141; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
142; CHECK-NEXT:    lr %r0, %r2
143; CHECK-NEXT:    crjle %r2, %r4, .LBB5_1
144; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
145; CHECK-NEXT:    # in Loop: Header=BB5_2 Depth=1
146; CHECK-NEXT:    lr %r0, %r4
147; CHECK-NEXT:    j .LBB5_1
148; CHECK-NEXT:  .LBB5_4: # %atomicrmw.end
149; CHECK-NEXT:    br %r14
150  %ptr = getelementptr i32, ptr %src, i64 1024
151  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
152  ret i32 %res
153}
154
155; Check the high end of the aligned CSY range.
156define i32 @f7(i32 %dummy, ptr %src, i32 %b) {
157; CHECK-LABEL: f7:
158; CHECK:       # %bb.0:
159; CHECK-NEXT:    ly %r2, 524284(%r3)
160; CHECK-NEXT:    j .LBB6_2
161; CHECK-NEXT:  .LBB6_1: # %atomicrmw.start
162; CHECK-NEXT:    # in Loop: Header=BB6_2 Depth=1
163; CHECK-NEXT:    csy %r2, %r0, 524284(%r3)
164; CHECK-NEXT:    je .LBB6_4
165; CHECK-NEXT:  .LBB6_2: # %atomicrmw.start
166; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
167; CHECK-NEXT:    lr %r0, %r2
168; CHECK-NEXT:    crjle %r2, %r4, .LBB6_1
169; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
170; CHECK-NEXT:    # in Loop: Header=BB6_2 Depth=1
171; CHECK-NEXT:    lr %r0, %r4
172; CHECK-NEXT:    j .LBB6_1
173; CHECK-NEXT:  .LBB6_4: # %atomicrmw.end
174; CHECK-NEXT:    br %r14
175  %ptr = getelementptr i32, ptr %src, i64 131071
176  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
177  ret i32 %res
178}
179
180; Check the next word up, which needs separate address logic.
181define i32 @f8(i32 %dummy, ptr %src, i32 %b) {
182; CHECK-LABEL: f8:
183; CHECK:       # %bb.0:
184; CHECK-NEXT:    agfi %r3, 524288
185; CHECK-NEXT:    l %r2, 0(%r3)
186; CHECK-NEXT:    j .LBB7_2
187; CHECK-NEXT:  .LBB7_1: # %atomicrmw.start
188; CHECK-NEXT:    # in Loop: Header=BB7_2 Depth=1
189; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
190; CHECK-NEXT:    je .LBB7_4
191; CHECK-NEXT:  .LBB7_2: # %atomicrmw.start
192; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
193; CHECK-NEXT:    lr %r0, %r2
194; CHECK-NEXT:    crjle %r2, %r4, .LBB7_1
195; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
196; CHECK-NEXT:    # in Loop: Header=BB7_2 Depth=1
197; CHECK-NEXT:    lr %r0, %r4
198; CHECK-NEXT:    j .LBB7_1
199; CHECK-NEXT:  .LBB7_4: # %atomicrmw.end
200; CHECK-NEXT:    br %r14
201  %ptr = getelementptr i32, ptr %src, i64 131072
202  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
203  ret i32 %res
204}
205
206; Check the high end of the negative aligned CSY range.
207define i32 @f9(i32 %dummy, ptr %src, i32 %b) {
208; CHECK-LABEL: f9:
209; CHECK:       # %bb.0:
210; CHECK-NEXT:    ly %r2, -4(%r3)
211; CHECK-NEXT:    j .LBB8_2
212; CHECK-NEXT:  .LBB8_1: # %atomicrmw.start
213; CHECK-NEXT:    # in Loop: Header=BB8_2 Depth=1
214; CHECK-NEXT:    csy %r2, %r0, -4(%r3)
215; CHECK-NEXT:    je .LBB8_4
216; CHECK-NEXT:  .LBB8_2: # %atomicrmw.start
217; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
218; CHECK-NEXT:    lr %r0, %r2
219; CHECK-NEXT:    crjle %r2, %r4, .LBB8_1
220; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
221; CHECK-NEXT:    # in Loop: Header=BB8_2 Depth=1
222; CHECK-NEXT:    lr %r0, %r4
223; CHECK-NEXT:    j .LBB8_1
224; CHECK-NEXT:  .LBB8_4: # %atomicrmw.end
225; CHECK-NEXT:    br %r14
226  %ptr = getelementptr i32, ptr %src, i64 -1
227  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
228  ret i32 %res
229}
230
231; Check the low end of the CSY range.
232define i32 @f10(i32 %dummy, ptr %src, i32 %b) {
233; CHECK-LABEL: f10:
234; CHECK:       # %bb.0:
235; CHECK-NEXT:    ly %r2, -524288(%r3)
236; CHECK-NEXT:    j .LBB9_2
237; CHECK-NEXT:  .LBB9_1: # %atomicrmw.start
238; CHECK-NEXT:    # in Loop: Header=BB9_2 Depth=1
239; CHECK-NEXT:    csy %r2, %r0, -524288(%r3)
240; CHECK-NEXT:    je .LBB9_4
241; CHECK-NEXT:  .LBB9_2: # %atomicrmw.start
242; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
243; CHECK-NEXT:    lr %r0, %r2
244; CHECK-NEXT:    crjle %r2, %r4, .LBB9_1
245; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
246; CHECK-NEXT:    # in Loop: Header=BB9_2 Depth=1
247; CHECK-NEXT:    lr %r0, %r4
248; CHECK-NEXT:    j .LBB9_1
249; CHECK-NEXT:  .LBB9_4: # %atomicrmw.end
250; CHECK-NEXT:    br %r14
251  %ptr = getelementptr i32, ptr %src, i64 -131072
252  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
253  ret i32 %res
254}
255
256; Check the next word down, which needs separate address logic.
257define i32 @f11(i32 %dummy, ptr %src, i32 %b) {
258; CHECK-LABEL: f11:
259; CHECK:       # %bb.0:
260; CHECK-NEXT:    agfi %r3, -524292
261; CHECK-NEXT:    l %r2, 0(%r3)
262; CHECK-NEXT:    j .LBB10_2
263; CHECK-NEXT:  .LBB10_1: # %atomicrmw.start
264; CHECK-NEXT:    # in Loop: Header=BB10_2 Depth=1
265; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
266; CHECK-NEXT:    je .LBB10_4
267; CHECK-NEXT:  .LBB10_2: # %atomicrmw.start
268; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
269; CHECK-NEXT:    lr %r0, %r2
270; CHECK-NEXT:    crjle %r2, %r4, .LBB10_1
271; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
272; CHECK-NEXT:    # in Loop: Header=BB10_2 Depth=1
273; CHECK-NEXT:    lr %r0, %r4
274; CHECK-NEXT:    j .LBB10_1
275; CHECK-NEXT:  .LBB10_4: # %atomicrmw.end
276; CHECK-NEXT:    br %r14
277  %ptr = getelementptr i32, ptr %src, i64 -131073
278  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
279  ret i32 %res
280}
281
282; Check that indexed addresses are not allowed.
283define i32 @f12(i32 %dummy, i64 %base, i64 %index, i32 %b) {
284; CHECK-LABEL: f12:
285; CHECK:       # %bb.0:
286; CHECK-NEXT:    l %r2, 0(%r4,%r3)
287; CHECK-NEXT:    agr %r3, %r4
288; CHECK-NEXT:    j .LBB11_2
289; CHECK-NEXT:  .LBB11_1: # %atomicrmw.start
290; CHECK-NEXT:    # in Loop: Header=BB11_2 Depth=1
291; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
292; CHECK-NEXT:    je .LBB11_4
293; CHECK-NEXT:  .LBB11_2: # %atomicrmw.start
294; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
295; CHECK-NEXT:    lr %r0, %r2
296; CHECK-NEXT:    crjle %r2, %r5, .LBB11_1
297; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
298; CHECK-NEXT:    # in Loop: Header=BB11_2 Depth=1
299; CHECK-NEXT:    lr %r0, %r5
300; CHECK-NEXT:    j .LBB11_1
301; CHECK-NEXT:  .LBB11_4: # %atomicrmw.end
302; CHECK-NEXT:    br %r14
303  %add = add i64 %base, %index
304  %ptr = inttoptr i64 %add to ptr
305  %res = atomicrmw min ptr %ptr, i32 %b seq_cst
306  ret i32 %res
307}
308
309; Check that constants are handled.
310define i32 @f13(i32 %dummy, ptr %ptr) {
311; CHECK-LABEL: f13:
312; CHECK:       # %bb.0:
313; CHECK-NEXT:    l %r2, 0(%r3)
314; CHECK-NEXT:    j .LBB12_2
315; CHECK-NEXT:  .LBB12_1: # %atomicrmw.start
316; CHECK-NEXT:    # in Loop: Header=BB12_2 Depth=1
317; CHECK-NEXT:    cs %r2, %r0, 0(%r3)
318; CHECK-NEXT:    je .LBB12_4
319; CHECK-NEXT:  .LBB12_2: # %atomicrmw.start
320; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
321; CHECK-NEXT:    lr %r0, %r2
322; CHECK-NEXT:    cijl %r2, 43, .LBB12_1
323; CHECK-NEXT:  # %bb.3: # %atomicrmw.start
324; CHECK-NEXT:    # in Loop: Header=BB12_2 Depth=1
325; CHECK-NEXT:    lhi %r0, 42
326; CHECK-NEXT:    j .LBB12_1
327; CHECK-NEXT:  .LBB12_4: # %atomicrmw.end
328; CHECK-NEXT:    br %r14
329  %res = atomicrmw min ptr %ptr, i32 42 seq_cst
330  ret i32 %res
331}
332