blob: 9075d8007c8247296ada4005a05cd80110801fcf [file] [log] [blame]
Aart Bikc8e93c72017-05-10 10:49:22 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * Tests for MIN/MAX vectorization.
19 */
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010020public class ShortSimdMinMax {
Aart Bikc8e93c72017-05-10 10:49:22 -070021
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010022 /// CHECK-START: void ShortSimdMinMax.doitMin(short[], short[], short[]) loop_optimization (before)
Aart Bikc8e93c72017-05-10 10:49:22 -070023 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
24 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
25 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
Aart Bik1f8d51b2018-02-15 10:42:37 -080026 /// CHECK-DAG: <<Min:i\d+>> Min [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bikc8e93c72017-05-10 10:49:22 -070027 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none
28 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
29 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010030 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMin(short[], short[], short[]) loop_optimization (after)
Aart Bik8c6c3572017-10-25 11:48:48 -070031 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
32 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010033 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get1>>,<<Get2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -070034 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>> outer_loop:none
Aart Bikc8e93c72017-05-10 10:49:22 -070035 private static void doitMin(short[] x, short[] y, short[] z) {
36 int min = Math.min(x.length, Math.min(y.length, z.length));
37 for (int i = 0; i < min; i++) {
38 x[i] = (short) Math.min(y[i], z[i]);
39 }
40 }
41
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010042 /// CHECK-START: void ShortSimdMinMax.doitMinUnsigned(short[], short[], short[]) instruction_simplifier (before)
Aart Bik304c8a52017-05-23 11:01:13 -070043 /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535 loop:none
44 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
45 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
46 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
47 /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
48 /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
49 /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<And1>>,<<And2>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
50 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none
Vladimir Marko61b92282017-10-11 13:23:17 +010051 /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none
52 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010053 /// CHECK-START: void ShortSimdMinMax.doitMinUnsigned(short[], short[], short[]) loop_optimization (before)
Vladimir Marko61b92282017-10-11 13:23:17 +010054 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
55 /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
56 /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
Aart Bik1f8d51b2018-02-15 10:42:37 -080057 /// CHECK-DAG: <<Min:i\d+>> Min [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Vladimir Marko61b92282017-10-11 13:23:17 +010058 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none
Aart Bik304c8a52017-05-23 11:01:13 -070059 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
60 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010061 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMinUnsigned(short[], short[], short[]) loop_optimization (after)
Aart Bik8c6c3572017-10-25 11:48:48 -070062 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
63 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none
Aart Bik4d1a9d42017-10-19 14:40:55 -070064 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get1>>,<<Get2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -070065 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>> outer_loop:none
Aart Bik304c8a52017-05-23 11:01:13 -070066 private static void doitMinUnsigned(short[] x, short[] y, short[] z) {
67 int min = Math.min(x.length, Math.min(y.length, z.length));
68 for (int i = 0; i < min; i++) {
69 x[i] = (short) Math.min(y[i] & 0xffff, z[i] & 0xffff);
70 }
71 }
72
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010073 /// CHECK-START: void ShortSimdMinMax.doitMax(short[], short[], short[]) loop_optimization (before)
Aart Bikc8e93c72017-05-10 10:49:22 -070074 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
75 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
76 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
Aart Bik1f8d51b2018-02-15 10:42:37 -080077 /// CHECK-DAG: <<Max:i\d+>> Max [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bikc8e93c72017-05-10 10:49:22 -070078 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Max>>] loop:<<Loop>> outer_loop:none
79 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
80 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010081 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMax(short[], short[], short[]) loop_optimization (after)
Aart Bik8c6c3572017-10-25 11:48:48 -070082 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
83 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010084 /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Get1>>,<<Get2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -070085 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none
Aart Bikc8e93c72017-05-10 10:49:22 -070086 private static void doitMax(short[] x, short[] y, short[] z) {
87 int min = Math.min(x.length, Math.min(y.length, z.length));
88 for (int i = 0; i < min; i++) {
89 x[i] = (short) Math.max(y[i], z[i]);
90 }
91 }
92
Vladimir Marko2aaa44f2018-03-27 15:02:47 +010093 /// CHECK-START: void ShortSimdMinMax.doitMaxUnsigned(short[], short[], short[]) instruction_simplifier (before)
Aart Bik304c8a52017-05-23 11:01:13 -070094 /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535 loop:none
95 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
96 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
97 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
98 /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
99 /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
100 /// CHECK-DAG: <<Max:i\d+>> InvokeStaticOrDirect [<<And1>>,<<And2>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
101 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Max>>] loop:<<Loop>> outer_loop:none
Vladimir Marko61b92282017-10-11 13:23:17 +0100102 /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none
103 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +0100104 /// CHECK-START: void ShortSimdMinMax.doitMaxUnsigned(short[], short[], short[]) loop_optimization (before)
Vladimir Marko61b92282017-10-11 13:23:17 +0100105 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
106 /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
107 /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
Aart Bik1f8d51b2018-02-15 10:42:37 -0800108 /// CHECK-DAG: <<Max:i\d+>> Max [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Vladimir Marko61b92282017-10-11 13:23:17 +0100109 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Max>>] loop:<<Loop>> outer_loop:none
Aart Bik304c8a52017-05-23 11:01:13 -0700110 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
111 //
Vladimir Marko2aaa44f2018-03-27 15:02:47 +0100112 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMaxUnsigned(short[], short[], short[]) loop_optimization (after)
Aart Bik8c6c3572017-10-25 11:48:48 -0700113 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
114 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none
Aart Bik4d1a9d42017-10-19 14:40:55 -0700115 /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Get1>>,<<Get2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -0700116 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none
Aart Bik304c8a52017-05-23 11:01:13 -0700117 private static void doitMaxUnsigned(short[] x, short[] y, short[] z) {
118 int min = Math.min(x.length, Math.min(y.length, z.length));
119 for (int i = 0; i < min; i++) {
120 x[i] = (short) Math.max(y[i] & 0xffff, z[i] & 0xffff);
121 }
122 }
123
Vladimir Marko2aaa44f2018-03-27 15:02:47 +0100124 /// CHECK-START: void ShortSimdMinMax.doitMin100(short[], short[]) loop_optimization (before)
Aart Bikdbbac8f2017-09-01 13:06:08 -0700125 /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none
126 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
127 /// CHECK-DAG: <<Get:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
Aart Bik1f8d51b2018-02-15 10:42:37 -0800128 /// CHECK-DAG: <<Min:i\d+>> Min [<<Get>>,<<I100>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700129 /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none
130 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
131 //
Aart Bik5aac9212018-04-03 14:06:43 -0700132 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMin100(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100133 /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none
134 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none
135 /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
136 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Repl>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
137 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700138 private static void doitMin100(short[] x, short[] y) {
139 int min = Math.min(x.length, y.length);
140 for (int i = 0; i < min; i++) {
141 x[i] = (short) Math.min(y[i], 100);
142 }
143 }
144
Aart Bik5aac9212018-04-03 14:06:43 -0700145 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMinMax(short[], short[]) loop_optimization (after)
146 /// CHECK-DAG: <<I11:i\d+>> IntConstant -1111 loop:none
147 /// CHECK-DAG: <<I23:i\d+>> IntConstant 2323 loop:none
148 /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none
149 /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none
150 /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
151 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
152 /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
153 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none
154 private static void doitMinMax(short[] x, short[] y) {
155 int n = Math.min(x.length, y.length);
156 for (int i = 0; i < n; i++) {
157 x[i] = (short) Math.max(-1111, Math.min(y[i], 2323));
158 }
159 }
160
161 /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMinMaxUnsigned(short[], short[]) loop_optimization (after)
162 /// CHECK-DAG: <<I11:i\d+>> IntConstant 1111 loop:none
163 /// CHECK-DAG: <<I23:i\d+>> IntConstant 2323 loop:none
164 /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none
165 /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none
166 /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none
167 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
168 /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
169 /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none
170 private static void doitMinMaxUnsigned(short[] x, short[] y) {
171 int n = Math.min(x.length, y.length);
172 for (int i = 0; i < n; i++) {
173 x[i] = (short) Math.max(1111, Math.min(y[i] & 0xffff, 2323));
174 }
175 }
176
Vladimir Marko2aaa44f2018-03-27 15:02:47 +0100177 public static void main() {
Aart Bikc8e93c72017-05-10 10:49:22 -0700178 short[] interesting = {
179 (short) 0x0000, (short) 0x0001, (short) 0x007f,
180 (short) 0x0080, (short) 0x0081, (short) 0x00ff,
181 (short) 0x0100, (short) 0x0101, (short) 0x017f,
182 (short) 0x0180, (short) 0x0181, (short) 0x01ff,
183 (short) 0x7f00, (short) 0x7f01, (short) 0x7f7f,
184 (short) 0x7f80, (short) 0x7f81, (short) 0x7fff,
185 (short) 0x8000, (short) 0x8001, (short) 0x807f,
186 (short) 0x8080, (short) 0x8081, (short) 0x80ff,
187 (short) 0x8100, (short) 0x8101, (short) 0x817f,
188 (short) 0x8180, (short) 0x8181, (short) 0x81ff,
189 (short) 0xff00, (short) 0xff01, (short) 0xff7f,
190 (short) 0xff80, (short) 0xff81, (short) 0xffff
191 };
192 // Initialize cross-values for the interesting values.
193 int total = interesting.length * interesting.length;
194 short[] x = new short[total];
195 short[] y = new short[total];
196 short[] z = new short[total];
197 int k = 0;
198 for (int i = 0; i < interesting.length; i++) {
199 for (int j = 0; j < interesting.length; j++) {
200 x[k] = 0;
201 y[k] = interesting[i];
202 z[k] = interesting[j];
203 k++;
204 }
205 }
206
207 // And test.
208 doitMin(x, y, z);
209 for (int i = 0; i < total; i++) {
210 short expected = (short) Math.min(y[i], z[i]);
211 expectEquals(expected, x[i]);
212 }
Aart Bik304c8a52017-05-23 11:01:13 -0700213 doitMinUnsigned(x, y, z);
214 for (int i = 0; i < total; i++) {
215 short expected = (short) Math.min(y[i] & 0xffff, z[i] & 0xffff);
216 expectEquals(expected, x[i]);
217 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700218 doitMax(x, y, z);
219 for (int i = 0; i < total; i++) {
220 short expected = (short) Math.max(y[i], z[i]);
221 expectEquals(expected, x[i]);
222 }
Aart Bik304c8a52017-05-23 11:01:13 -0700223 doitMaxUnsigned(x, y, z);
224 for (int i = 0; i < total; i++) {
225 short expected = (short) Math.max(y[i] & 0xffff, z[i] & 0xffff);
226 expectEquals(expected, x[i]);
227 }
Aart Bikdbbac8f2017-09-01 13:06:08 -0700228 doitMin100(x, y);
229 for (int i = 0; i < total; i++) {
230 short expected = (short) Math.min(y[i], 100);
231 expectEquals(expected, x[i]);
232 }
Aart Bik5aac9212018-04-03 14:06:43 -0700233 doitMinMax(x, y);
234 for (int i = 0; i < total; i++) {
235 int s = y[i];
236 short expected = (short) (s < -1111 ? -1111 : (s > 2323 ? 2323 : s));
237 expectEquals(expected, x[i]);
238 }
239 doitMinMaxUnsigned(x, y);
240 for (int i = 0; i < total; i++) {
241 int u = y[i] & 0xffff;
242 short expected = (short) (u < 1111 ? 1111 : (u > 2323 ? 2323 : u));
243 expectEquals(expected, x[i]);
244 }
Aart Bikc8e93c72017-05-10 10:49:22 -0700245
Vladimir Marko2aaa44f2018-03-27 15:02:47 +0100246 System.out.println("ShortSimdMinMax passed");
Aart Bikc8e93c72017-05-10 10:49:22 -0700247 }
248
249 private static void expectEquals(short expected, short result) {
250 if (expected != result) {
251 throw new Error("Expected: " + expected + ", found: " + result);
252 }
253 }
254}