1; Test 8-bit atomic min/max operations.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK
4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1
5; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2
6
7; Check signed minimum.
8; - CHECK is for the main loop.
9; - CHECK-SHIFT1 makes sure that the negated shift count used by the second
10;   RLL is set up correctly.  The negation is independent of the NILL and L
11;   tested in CHECK.
12; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word
13;   before being used, and that the low bits are set to 1.  This sequence is
14;   independent of the other loop prologue instructions.
15define i8 @f1(i8 *%src, i8 %b) {
16; CHECK-LABEL: f1:
17; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
18; CHECK: nill %r2, 65532
19; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
20; CHECK: [[LOOP:\.[^:]*]]:
21; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
22; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
23; CHECK: risbg [[ROT]], %r3, 32, 39, 0
24; CHECK: [[KEEP]]:
25; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
26; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
27; CHECK: jl [[LOOP]]
28; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
29; CHECK: br %r14
30;
31; CHECK-SHIFT1-LABEL: f1:
32; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
33; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
34; CHECK-SHIFT1: rll
35; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
36; CHECK-SHIFT1: rll
37; CHECK-SHIFT1: br %r14
38;
39; CHECK-SHIFT2-LABEL: f1:
40; CHECK-SHIFT2: sll %r3, 24
41; CHECK-SHIFT2: rll
42; CHECK-SHIFT2: crjle {{%r[0-9]+}}, %r3
43; CHECK-SHIFT2: rll
44; CHECK-SHIFT2: rll
45; CHECK-SHIFT2: br %r14
46  %res = atomicrmw min i8 *%src, i8 %b seq_cst
47  ret i8 %res
48}
49
50; Check signed maximum.
51define i8 @f2(i8 *%src, i8 %b) {
52; CHECK-LABEL: f2:
53; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
54; CHECK: nill %r2, 65532
55; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
56; CHECK: [[LOOP:\.[^:]*]]:
57; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
58; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
59; CHECK: risbg [[ROT]], %r3, 32, 39, 0
60; CHECK: [[KEEP]]:
61; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
62; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
63; CHECK: jl [[LOOP]]
64; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
65; CHECK: br %r14
66;
67; CHECK-SHIFT1-LABEL: f2:
68; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
69; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
70; CHECK-SHIFT1: rll
71; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
72; CHECK-SHIFT1: rll
73; CHECK-SHIFT1: br %r14
74;
75; CHECK-SHIFT2-LABEL: f2:
76; CHECK-SHIFT2: sll %r3, 24
77; CHECK-SHIFT2: rll
78; CHECK-SHIFT2: crjhe {{%r[0-9]+}}, %r3
79; CHECK-SHIFT2: rll
80; CHECK-SHIFT2: rll
81; CHECK-SHIFT2: br %r14
82  %res = atomicrmw max i8 *%src, i8 %b seq_cst
83  ret i8 %res
84}
85
86; Check unsigned minimum.
87define i8 @f3(i8 *%src, i8 %b) {
88; CHECK-LABEL: f3:
89; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
90; CHECK: nill %r2, 65532
91; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
92; CHECK: [[LOOP:\.[^:]*]]:
93; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
94; CHECK: clrjle [[ROT]], %r3, [[KEEP:\..*]]
95; CHECK: risbg [[ROT]], %r3, 32, 39, 0
96; CHECK: [[KEEP]]:
97; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
98; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
99; CHECK: jl [[LOOP]]
100; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
101; CHECK: br %r14
102;
103; CHECK-SHIFT1-LABEL: f3:
104; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
105; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
106; CHECK-SHIFT1: rll
107; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
108; CHECK-SHIFT1: rll
109; CHECK-SHIFT1: br %r14
110;
111; CHECK-SHIFT2-LABEL: f3:
112; CHECK-SHIFT2: sll %r3, 24
113; CHECK-SHIFT2: rll
114; CHECK-SHIFT2: clrjle {{%r[0-9]+}}, %r3,
115; CHECK-SHIFT2: rll
116; CHECK-SHIFT2: rll
117; CHECK-SHIFT2: br %r14
118  %res = atomicrmw umin i8 *%src, i8 %b seq_cst
119  ret i8 %res
120}
121
122; Check unsigned maximum.
123define i8 @f4(i8 *%src, i8 %b) {
124; CHECK-LABEL: f4:
125; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
126; CHECK: nill %r2, 65532
127; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
128; CHECK: [[LOOP:\.[^:]*]]:
129; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
130; CHECK: clrjhe [[ROT]], %r3, [[KEEP:\..*]]
131; CHECK: risbg [[ROT]], %r3, 32, 39, 0
132; CHECK: [[KEEP]]:
133; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
134; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
135; CHECK: jl [[LOOP]]
136; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
137; CHECK: br %r14
138;
139; CHECK-SHIFT1-LABEL: f4:
140; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3
141; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]]
142; CHECK-SHIFT1: rll
143; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]])
144; CHECK-SHIFT1: rll
145; CHECK-SHIFT1: br %r14
146;
147; CHECK-SHIFT2-LABEL: f4:
148; CHECK-SHIFT2: sll %r3, 24
149; CHECK-SHIFT2: rll
150; CHECK-SHIFT2: clrjhe {{%r[0-9]+}}, %r3,
151; CHECK-SHIFT2: rll
152; CHECK-SHIFT2: rll
153; CHECK-SHIFT2: br %r14
154  %res = atomicrmw umax i8 *%src, i8 %b seq_cst
155  ret i8 %res
156}
157
158; Check the lowest useful signed minimum value.  We need to load 0x81000000
159; into the source register.
160define i8 @f5(i8 *%src) {
161; CHECK-LABEL: f5:
162; CHECK: llilh [[SRC2:%r[0-9]+]], 33024
163; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]]
164; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
165; CHECK: br %r14
166;
167; CHECK-SHIFT1-LABEL: f5:
168; CHECK-SHIFT1: br %r14
169; CHECK-SHIFT2-LABEL: f5:
170; CHECK-SHIFT2: br %r14
171  %res = atomicrmw min i8 *%src, i8 -127 seq_cst
172  ret i8 %res
173}
174
175; Check the highest useful signed maximum value.  We need to load 0x7e000000
176; into the source register.
177define i8 @f6(i8 *%src) {
178; CHECK-LABEL: f6:
179; CHECK: llilh [[SRC2:%r[0-9]+]], 32256
180; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]]
181; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
182; CHECK: br %r14
183;
184; CHECK-SHIFT1-LABEL: f6:
185; CHECK-SHIFT1: br %r14
186; CHECK-SHIFT2-LABEL: f6:
187; CHECK-SHIFT2: br %r14
188  %res = atomicrmw max i8 *%src, i8 126 seq_cst
189  ret i8 %res
190}
191
192; Check the lowest useful unsigned minimum value.  We need to load 0x01000000
193; into the source register.
194define i8 @f7(i8 *%src) {
195; CHECK-LABEL: f7:
196; CHECK: llilh [[SRC2:%r[0-9]+]], 256
197; CHECK: clrjle [[ROT:%r[0-9]+]], [[SRC2]],
198; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
199; CHECK: br %r14
200;
201; CHECK-SHIFT1-LABEL: f7:
202; CHECK-SHIFT1: br %r14
203; CHECK-SHIFT2-LABEL: f7:
204; CHECK-SHIFT2: br %r14
205  %res = atomicrmw umin i8 *%src, i8 1 seq_cst
206  ret i8 %res
207}
208
209; Check the highest useful unsigned maximum value.  We need to load 0xfe000000
210; into the source register.
211define i8 @f8(i8 *%src) {
212; CHECK-LABEL: f8:
213; CHECK: llilh [[SRC2:%r[0-9]+]], 65024
214; CHECK: clrjhe [[ROT:%r[0-9]+]], [[SRC2]],
215; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
216; CHECK: br %r14
217;
218; CHECK-SHIFT1-LABEL: f8:
219; CHECK-SHIFT1: br %r14
220; CHECK-SHIFT2-LABEL: f8:
221; CHECK-SHIFT2: br %r14
222  %res = atomicrmw umax i8 *%src, i8 254 seq_cst
223  ret i8 %res
224}
225