1; Test 8-bit atomic min/max operations.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck %s
4; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | FileCheck %s -check-prefix=CHECK-SHIFT1
5; RUN: llc < %s -mtriple=s390x-linux-gnu -disable-block-placement | 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 i16 @f1(i16 *%src, i16 %b) {
16; CHECK-LABEL: f1:
17; CHECK: risbg [[RISBG:%r[1-9]+]], %r2, 0, 189, 0{{$}}
18; CHECK-DAG: sll %r2, 3
19; CHECK-DAG: l [[OLD:%r[0-9]+]], 0([[RISBG]])
20; CHECK: [[LOOP:\.[^:]*]]:
21; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0(%r2)
22; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
23; CHECK: risbg [[ROT]], %r3, 32, 47, 0
24; CHECK: [[KEEP]]:
25; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
26; CHECK: cs [[OLD]], [[NEW]], 0([[RISBG]])
27; CHECK: jl [[LOOP]]
28; CHECK: rll %r2, [[OLD]], 16(%r2)
29; CHECK: br %r14
30;
31; CHECK-SHIFT1-LABEL: f1:
32; CHECK-SHIFT1: sll %r2, 3
33; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], %r2
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, 16
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 i16 *%src, i16 %b seq_cst
47  ret i16 %res
48}
49
50; Check signed maximum.
51define i16 @f2(i16 *%src, i16 %b) {
52; CHECK-LABEL: f2:
53; CHECK: risbg [[RISBG:%r[1-9]+]], %r2, 0, 189, 0{{$}}
54; CHECK-DAG: sll %r2, 3
55; CHECK-DAG: l [[OLD:%r[0-9]+]], 0([[RISBG]])
56; CHECK: [[LOOP:\.[^:]*]]:
57; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0(%r2)
58; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
59; CHECK: risbg [[ROT]], %r3, 32, 47, 0
60; CHECK: [[KEEP]]:
61; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
62; CHECK: cs [[OLD]], [[NEW]], 0([[RISBG]])
63; CHECK: jl [[LOOP]]
64; CHECK: rll %r2, [[OLD]], 16(%r2)
65; CHECK: br %r14
66;
67; CHECK-SHIFT1-LABEL: f2:
68; CHECK-SHIFT1: sll %r2, 3
69; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], %r2
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, 16
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 i16 *%src, i16 %b seq_cst
83  ret i16 %res
84}
85
86; Check unsigned minimum.
87define i16 @f3(i16 *%src, i16 %b) {
88; CHECK-LABEL: f3:
89; CHECK: risbg [[RISBG:%r[1-9]+]], %r2, 0, 189, 0{{$}}
90; CHECK-DAG: sll %r2, 3
91; CHECK-DAG: l [[OLD:%r[0-9]+]], 0([[RISBG]])
92; CHECK: [[LOOP:\.[^:]*]]:
93; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0(%r2)
94; CHECK: clrjle [[ROT]], %r3, [[KEEP:\..*]]
95; CHECK: risbg [[ROT]], %r3, 32, 47, 0
96; CHECK: [[KEEP]]:
97; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
98; CHECK: cs [[OLD]], [[NEW]], 0([[RISBG]])
99; CHECK: jl [[LOOP]]
100; CHECK: rll %r2, [[OLD]], 16(%r2)
101; CHECK: br %r14
102;
103; CHECK-SHIFT1-LABEL: f3:
104; CHECK-SHIFT1: sll %r2, 3
105; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], %r2
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, 16
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 i16 *%src, i16 %b seq_cst
119  ret i16 %res
120}
121
122; Check unsigned maximum.
123define i16 @f4(i16 *%src, i16 %b) {
124; CHECK-LABEL: f4:
125; CHECK: risbg [[RISBG:%r[1-9]+]], %r2, 0, 189, 0{{$}}
126; CHECK-DAG: sll %r2, 3
127; CHECK-DAG: l [[OLD:%r[0-9]+]], 0([[RISBG]])
128; CHECK: [[LOOP:\.[^:]*]]:
129; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0(%r2)
130; CHECK: clrjhe [[ROT]], %r3, [[KEEP:\..*]]
131; CHECK: risbg [[ROT]], %r3, 32, 47, 0
132; CHECK: [[KEEP]]:
133; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
134; CHECK: cs [[OLD]], [[NEW]], 0([[RISBG]])
135; CHECK: jl [[LOOP]]
136; CHECK: rll %r2, [[OLD]], 16(%r2)
137; CHECK: br %r14
138;
139; CHECK-SHIFT1-LABEL: f4:
140; CHECK-SHIFT1: sll %r2, 3
141; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], %r2
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, 16
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 i16 *%src, i16 %b seq_cst
155  ret i16 %res
156}
157
158; Check the lowest useful signed minimum value.  We need to load 0x80010000
159; into the source register.
160define i16 @f5(i16 *%src) {
161; CHECK-LABEL: f5:
162; CHECK: llilh [[SRC2:%r[0-9]+]], 32769
163; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]]
164; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 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 i16 *%src, i16 -32767 seq_cst
172  ret i16 %res
173}
174
175; Check the highest useful signed maximum value.  We need to load 0x7ffe0000
176; into the source register.
177define i16 @f6(i16 *%src) {
178; CHECK-LABEL: f6:
179; CHECK: llilh [[SRC2:%r[0-9]+]], 32766
180; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]]
181; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 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 i16 *%src, i16 32766 seq_cst
189  ret i16 %res
190}
191
192; Check the lowest useful unsigned maximum value.  We need to load 0x00010000
193; into the source register.
194define i16 @f7(i16 *%src) {
195; CHECK-LABEL: f7:
196; CHECK: llilh [[SRC2:%r[0-9]+]], 1
197; CHECK: clrjle [[ROT:%r[0-9]+]], [[SRC2]],
198; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 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 i16 *%src, i16 1 seq_cst
206  ret i16 %res
207}
208
209; Check the highest useful unsigned maximum value.  We need to load 0xfffe0000
210; into the source register.
211define i16 @f8(i16 *%src) {
212; CHECK-LABEL: f8:
213; CHECK: llilh [[SRC2:%r[0-9]+]], 65534
214; CHECK: clrjhe [[ROT:%r[0-9]+]], [[SRC2]],
215; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 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 i16 *%src, i16 65534 seq_cst
223  ret i16 %res
224}
225