blob: 8a44d9ed12f4c7e87770c88362d93182390eaff1 [file] [log] [blame]
Aart Bikdbbac8f2017-09-01 13:06:08 -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 SAD (sum of absolute differences).
19 */
20public class Main {
21
22 // TODO: lower precision still coming, b/64091002
23
24 private static short sadShort2Short(short[] s1, short[] s2) {
25 int min_length = Math.min(s1.length, s2.length);
26 short sad = 0;
27 for (int i = 0; i < min_length; i++) {
28 sad += Math.abs(s1[i] - s2[i]);
29 }
30 return sad;
31 }
32
33 private static short sadShort2ShortAlt(short[] s1, short[] s2) {
34 int min_length = Math.min(s1.length, s2.length);
35 short sad = 0;
36 for (int i = 0; i < min_length; i++) {
37 short s = s1[i];
38 short p = s2[i];
39 sad += s >= p ? s - p : p - s;
40 }
41 return sad;
42 }
43
44 private static short sadShort2ShortAlt2(short[] s1, short[] s2) {
45 int min_length = Math.min(s1.length, s2.length);
46 short sad = 0;
47 for (int i = 0; i < min_length; i++) {
48 short s = s1[i];
49 short p = s2[i];
50 int x = s - p;
51 if (x < 0) x = -x;
52 sad += x;
53 }
54 return sad;
55 }
56
57 /// CHECK-START: int Main.sadShort2Int(short[], short[]) loop_optimization (before)
58 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
59 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
60 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
61 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
62 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
63 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
64 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080065 /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070066 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
67 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
68 //
Aart Bik9cb7fe42017-11-30 11:46:45 -080069 /// CHECK-START-{ARM64,MIPS64}: int Main.sadShort2Int(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +010070 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
71 /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
72 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
73 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
74 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
75 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
76 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
77 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
78 /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070079 private static int sadShort2Int(short[] s1, short[] s2) {
80 int min_length = Math.min(s1.length, s2.length);
81 int sad = 0;
82 for (int i = 0; i < min_length; i++) {
83 sad += Math.abs(s1[i] - s2[i]);
84 }
85 return sad;
86 }
87
88 /// CHECK-START: int Main.sadShort2IntAlt(short[], short[]) loop_optimization (before)
89 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
90 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
91 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
92 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
93 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
94 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
95 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080096 /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070097 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
98 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
99 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800100 /// CHECK-START-{ARM64,MIPS64}: int Main.sadShort2IntAlt(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100101 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
102 /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
103 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
104 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
105 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
106 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
107 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
108 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
109 /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700110 private static int sadShort2IntAlt(short[] s1, short[] s2) {
111 int min_length = Math.min(s1.length, s2.length);
112 int sad = 0;
113 for (int i = 0; i < min_length; i++) {
114 short s = s1[i];
115 short p = s2[i];
116 sad += s >= p ? s - p : p - s;
117 }
118 return sad;
119 }
120
121 /// CHECK-START: int Main.sadShort2IntAlt2(short[], short[]) loop_optimization (before)
122 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
123 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
124 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
125 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
126 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
127 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
128 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800129 /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700130 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
131 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
132 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800133 /// CHECK-START-{ARM64,MIPS64}: int Main.sadShort2IntAlt2(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100134 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
135 /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
136 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
137 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
138 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
139 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
140 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
141 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
142 /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700143 private static int sadShort2IntAlt2(short[] s1, short[] s2) {
144 int min_length = Math.min(s1.length, s2.length);
145 int sad = 0;
146 for (int i = 0; i < min_length; i++) {
147 short s = s1[i];
148 short p = s2[i];
149 int x = s - p;
150 if (x < 0) x = -x;
151 sad += x;
152 }
153 return sad;
154 }
155
156 /// CHECK-START: long Main.sadShort2Long(short[], short[]) loop_optimization (before)
157 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
158 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
159 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
160 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
161 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
162 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
163 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
164 /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
165 /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
166 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800167 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700168 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
169 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
170 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800171 /// CHECK-START-{ARM64,MIPS64}: long Main.sadShort2Long(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100172 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
173 /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
174 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
175 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
176 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
177 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
178 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
179 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
180 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
181 /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700182 private static long sadShort2Long(short[] s1, short[] s2) {
183 int min_length = Math.min(s1.length, s2.length);
184 long sad = 0;
185 for (int i = 0; i < min_length; i++) {
186 long x = s1[i];
187 long y = s2[i];
188 sad += Math.abs(x - y);
189 }
190 return sad;
191 }
192
193 /// CHECK-START: long Main.sadShort2LongAt1(short[], short[]) loop_optimization (before)
194 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
195 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
196 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
197 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
198 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
199 /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
200 /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
201 /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
202 /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
203 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800204 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700205 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
206 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
207 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800208 /// CHECK-START-{ARM64,MIPS64}: long Main.sadShort2LongAt1(short[], short[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100209 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
210 /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
211 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
212 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
213 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
214 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
215 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
216 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
217 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
218 /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700219 private static long sadShort2LongAt1(short[] s1, short[] s2) {
220 int min_length = Math.min(s1.length, s2.length);
221 long sad = 1; // starts at 1
222 for (int i = 0; i < min_length; i++) {
223 long x = s1[i];
224 long y = s2[i];
225 sad += Math.abs(x - y);
226 }
227 return sad;
228 }
229
230 public static void main(String[] args) {
231 // Cross-test the two most extreme values individually.
232 short[] s1 = { 0, -32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
233 short[] s2 = { 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
234 expectEquals(-1, sadShort2Short(s1, s2));
235 expectEquals(-1, sadShort2Short(s2, s1));
236 expectEquals(-1, sadShort2ShortAlt(s1, s2));
237 expectEquals(-1, sadShort2ShortAlt(s2, s1));
238 expectEquals(-1, sadShort2ShortAlt2(s1, s2));
239 expectEquals(-1, sadShort2ShortAlt2(s2, s1));
240 expectEquals(65535, sadShort2Int(s1, s2));
241 expectEquals(65535, sadShort2Int(s2, s1));
242 expectEquals(65535, sadShort2IntAlt(s1, s2));
243 expectEquals(65535, sadShort2IntAlt(s2, s1));
244 expectEquals(65535, sadShort2IntAlt2(s1, s2));
245 expectEquals(65535, sadShort2IntAlt2(s2, s1));
246 expectEquals(65535L, sadShort2Long(s1, s2));
247 expectEquals(65535L, sadShort2Long(s2, s1));
248 expectEquals(65536L, sadShort2LongAt1(s1, s2));
249 expectEquals(65536L, sadShort2LongAt1(s2, s1));
250
251 // Use cross-values to test all cases.
252 short[] interesting = {
253 (short) 0x0000,
254 (short) 0x0001,
255 (short) 0x0002,
256 (short) 0x1234,
257 (short) 0x8000,
258 (short) 0x8001,
259 (short) 0x7fff,
260 (short) 0xffff
261 };
262 int n = interesting.length;
263 int m = n * n + 1;
264 s1 = new short[m];
265 s2 = new short[m];
266 int k = 0;
267 for (int i = 0; i < n; i++) {
268 for (int j = 0; j < n; j++) {
269 s1[k] = interesting[i];
270 s2[k] = interesting[j];
271 k++;
272 }
273 }
274 s1[k] = 10;
275 s2[k] = 2;
276 expectEquals(-18932, sadShort2Short(s1, s2));
277 expectEquals(-18932, sadShort2ShortAlt(s1, s2));
278 expectEquals(-18932, sadShort2ShortAlt2(s1, s2));
279 expectEquals(1291788, sadShort2Int(s1, s2));
280 expectEquals(1291788, sadShort2IntAlt(s1, s2));
281 expectEquals(1291788, sadShort2IntAlt2(s1, s2));
282 expectEquals(1291788L, sadShort2Long(s1, s2));
283 expectEquals(1291789L, sadShort2LongAt1(s1, s2));
284
285 System.out.println("passed");
286 }
287
288 private static void expectEquals(int expected, int result) {
289 if (expected != result) {
290 throw new Error("Expected: " + expected + ", found: " + result);
291 }
292 }
293
294 private static void expectEquals(long expected, long result) {
295 if (expected != result) {
296 throw new Error("Expected: " + expected + ", found: " + result);
297 }
298 }
299}