blob: 29415fd2cf64d83069071d503153aaa900948c9b [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 /// CHECK-START: int Main.sadInt2Int(int[], int[]) loop_optimization (before)
23 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
24 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
25 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
26 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
27 /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
28 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
29 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080030 /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070031 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
32 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
33 //
Aart Bik9cb7fe42017-11-30 11:46:45 -080034 /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.sadInt2Int(int[], int[]) loop_optimization (after)
35 /// CHECK-DAG: <<Cons:i\d+>> IntConstant {{2|4}} loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -070036 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [{{i\d+}}] loop:none
37 /// CHECK-DAG: <<Phi:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop:B\d+>> outer_loop:none
38 /// CHECK-DAG: <<Ld1:d\d+>> VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>> outer_loop:none
39 /// CHECK-DAG: <<Ld2:d\d+>> VecLoad [{{l\d+}},<<I>>] loop:<<Loop>> outer_loop:none
40 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
Aart Bik9cb7fe42017-11-30 11:46:45 -080041 /// CHECK-DAG: Add [<<I>>,<<Cons>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070042 private static int sadInt2Int(int[] x, int[] y) {
43 int min_length = Math.min(x.length, y.length);
44 int sad = 0;
45 for (int i = 0; i < min_length; i++) {
46 sad += Math.abs(x[i] - y[i]);
47 }
48 return sad;
49 }
50
51 /// CHECK-START: int Main.sadInt2IntAlt(int[], int[]) loop_optimization (before)
52 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
53 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
54 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
55 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
56 /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
57 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
58 /// CHECK-DAG: <<Sub1:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
59 /// CHECK-DAG: <<Sub2:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
60 /// CHECK-DAG: <<Select:i\d+>> Select [<<Sub2>>,<<Sub1>>,{{z\d+}}] loop:<<Loop>> outer_loop:none
61 /// CHECK-DAG: Add [<<Phi2>>,<<Select>>] loop:<<Loop>> outer_loop:none
62 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
63 //
64 // No ABS? No SAD!
65 //
Lena Djokic38e380b2017-10-30 16:17:10 +010066 /// CHECK-START: int Main.sadInt2IntAlt(int[], int[]) loop_optimization (after)
Aart Bikdbbac8f2017-09-01 13:06:08 -070067 /// CHECK-NOT: VecSADAccumulate
68 private static int sadInt2IntAlt(int[] x, int[] y) {
69 int min_length = Math.min(x.length, y.length);
70 int sad = 0;
71 for (int i = 0; i < min_length; i++) {
72 int s = x[i];
73 int p = y[i];
74 sad += s >= p ? s - p : p - s;
75 }
76 return sad;
77 }
78
79 /// CHECK-START: int Main.sadInt2IntAlt2(int[], int[]) loop_optimization (before)
80 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
81 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
82 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
83 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
84 /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
85 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
86 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080087 /// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070088 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
89 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
90 //
Aart Bik9cb7fe42017-11-30 11:46:45 -080091 /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.sadInt2IntAlt2(int[], int[]) loop_optimization (after)
92 /// CHECK-DAG: <<Cons:i\d+>> IntConstant {{2|4}} loop:none
Aart Bik8c6c3572017-10-25 11:48:48 -070093 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [{{i\d+}}] loop:none
94 /// CHECK-DAG: <<Phi:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop:B\d+>> outer_loop:none
95 /// CHECK-DAG: <<Ld1:d\d+>> VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>> outer_loop:none
96 /// CHECK-DAG: <<Ld2:d\d+>> VecLoad [{{l\d+}},<<I>>] loop:<<Loop>> outer_loop:none
97 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi>>,<<Ld1>>,<<Ld2>>] loop:<<Loop>> outer_loop:none
Aart Bik9cb7fe42017-11-30 11:46:45 -080098 /// CHECK-DAG: Add [<<I>>,<<Cons>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070099 private static int sadInt2IntAlt2(int[] x, int[] y) {
100 int min_length = Math.min(x.length, y.length);
101 int sad = 0;
102 for (int i = 0; i < min_length; i++) {
103 int s = x[i];
104 int p = y[i];
105 int m = s - p;
106 if (m < 0) m = -m;
107 sad += m;
108 }
109 return sad;
110 }
111
112 /// CHECK-START: long Main.sadInt2Long(int[], int[]) loop_optimization (before)
113 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
114 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
115 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
116 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
117 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
118 /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
119 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
120 /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
121 /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
122 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800123 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700124 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
125 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
126 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800127 /// CHECK-START-{ARM64,MIPS64}: long Main.sadInt2Long(int[], int[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100128 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
129 /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none
130 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
131 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
132 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
133 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
134 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
135 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
136 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
137 /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700138 private static long sadInt2Long(int[] x, int[] y) {
139 int min_length = Math.min(x.length, y.length);
140 long sad = 0;
141 for (int i = 0; i < min_length; i++) {
142 long s = x[i];
143 long p = y[i];
144 sad += Math.abs(s - p);
145 }
146 return sad;
147 }
148
149 /// CHECK-START: long Main.sadInt2LongAt1(int[], int[]) loop_optimization (before)
150 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
151 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
152 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
153 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
154 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
155 /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
156 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
157 /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
158 /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
159 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800160 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700161 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
162 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
163 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800164 /// CHECK-START-{ARM64,MIPS64}: long Main.sadInt2LongAt1(int[], int[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100165 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
166 /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none
167 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
168 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
169 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
170 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
171 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
172 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
173 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
174 /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700175 private static long sadInt2LongAt1(int[] x, int[] y) {
176 int min_length = Math.min(x.length, y.length);
177 long sad = 1; // starts at 1
178 for (int i = 0; i < min_length; i++) {
179 long s = x[i];
180 long p = y[i];
181 sad += Math.abs(s - p);
182 }
183 return sad;
184 }
185
186 public static void main(String[] args) {
187 // Cross-test the two most extreme values individually.
188 int[] x = { 0, Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
189 int[] y = { 0, Integer.MIN_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
190 expectEquals(1, sadInt2Int(x, y));
191 expectEquals(1, sadInt2Int(y, x));
192 expectEquals(-1, sadInt2IntAlt(x, y));
193 expectEquals(-1, sadInt2IntAlt(y, x));
194 expectEquals(1, sadInt2IntAlt2(x, y));
195 expectEquals(1, sadInt2IntAlt2(y, x));
196 expectEquals(4294967295L, sadInt2Long(x, y));
197 expectEquals(4294967295L, sadInt2Long(y, x));
198 expectEquals(4294967296L, sadInt2LongAt1(x, y));
199 expectEquals(4294967296L, sadInt2LongAt1(y, x));
200
201 // Use cross-values for the interesting values.
202 int[] interesting = {
203 0x00000000, 0x00000001, 0x00007fff, 0x00008000, 0x00008001, 0x0000ffff,
204 0x00010000, 0x00010001, 0x00017fff, 0x00018000, 0x00018001, 0x0001ffff,
205 0x7fff0000, 0x7fff0001, 0x7fff7fff, 0x7fff8000, 0x7fff8001, 0x7fffffff,
206 0x80000000, 0x80000001, 0x80007fff, 0x80008000, 0x80008001, 0x8000ffff,
207 0x80010000, 0x80010001, 0x80017fff, 0x80018000, 0x80018001, 0x8001ffff,
208 0xffff0000, 0xffff0001, 0xffff7fff, 0xffff8000, 0xffff8001, 0xffffffff
209 };
210 int n = interesting.length;
211 int m = n * n + 1;
212 x = new int[m];
213 y = new int[m];
214 int k = 0;
215 for (int i = 0; i < n; i++) {
216 for (int j = 0; j < n; j++) {
217 x[k] = interesting[i];
218 y[k] = interesting[j];
219 k++;
220 }
221 }
222 x[k] = 10;
223 y[k] = 2;
224 expectEquals(8, sadInt2Int(x, y));
225 expectEquals(-13762600, sadInt2IntAlt(x, y));
226 expectEquals(8, sadInt2IntAlt2(x, y));
227 expectEquals(2010030931928L, sadInt2Long(x, y));
228 expectEquals(2010030931929L, sadInt2LongAt1(x, y));
229
230 System.out.println("passed");
231 }
232
233 private static void expectEquals(int expected, int result) {
234 if (expected != result) {
235 throw new Error("Expected: " + expected + ", found: " + result);
236 }
237 }
238
239 private static void expectEquals(long expected, long result) {
240 if (expected != result) {
241 throw new Error("Expected: " + expected + ", found: " + result);
242 }
243 }
244}