blob: 360e7234ebb0460df4276e849418d1da6a22f4ea [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: long Main.sadLong2Long(long[], long[]) 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: <<ConsL:j\d+>> LongConstant 0 loop:none
26 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
27 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
28 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
29 /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
30 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080031 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070032 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
33 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
34 //
Aart Bik9cb7fe42017-11-30 11:46:45 -080035 /// CHECK-START-{ARM64,MIPS64}: long Main.sadLong2Long(long[], long[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +010036 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
37 /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none
38 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
39 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
40 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
41 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
42 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
43 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
44 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
45 /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070046 private static long sadLong2Long(long[] x, long[] y) {
47 int min_length = Math.min(x.length, y.length);
48 long sad = 0;
49 for (int i = 0; i < min_length; i++) {
50 sad += Math.abs(x[i] - y[i]);
51 }
52 return sad;
53 }
54
55 /// CHECK-START: long Main.sadLong2LongAlt(long[], long[]) loop_optimization (before)
56 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
57 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
58 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
59 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
60 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
61 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
62 /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
63 /// CHECK-DAG: <<Sub1:j\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
64 /// CHECK-DAG: <<Sub2:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
65 /// CHECK-DAG: <<Select:j\d+>> Select [<<Sub2>>,<<Sub1>>,{{z\d+}}] loop:<<Loop>> outer_loop:none
66 /// CHECK-DAG: Add [<<Phi2>>,<<Select>>] loop:<<Loop>> outer_loop:none
67 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
68 //
69 // No ABS? No SAD!
70 //
71 /// CHECK-START: long Main.sadLong2LongAlt(long[], long[]) loop_optimization (after)
72 /// CHECK-NOT: VecSADAccumulate
73 private static long sadLong2LongAlt(long[] x, long[] y) {
74 int min_length = Math.min(x.length, y.length);
75 long sad = 0;
76 for (int i = 0; i < min_length; i++) {
77 long s = x[i];
78 long p = y[i];
79 sad += s >= p ? s - p : p - s;
80 }
81 return sad;
82 }
83
84 /// CHECK-START: long Main.sadLong2LongAlt2(long[], long[]) loop_optimization (before)
85 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
86 /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
87 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
88 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
89 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
90 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
91 /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
92 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -080093 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -070094 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
95 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
96 //
Aart Bik9cb7fe42017-11-30 11:46:45 -080097 /// CHECK-START-{ARM64,MIPS64}: long Main.sadLong2LongAlt2(long[], long[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +010098 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
99 /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none
100 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
101 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
102 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
103 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
104 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
105 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
106 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
107 /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700108 private static long sadLong2LongAlt2(long[] x, long[] y) {
109 int min_length = Math.min(x.length, y.length);
110 long sad = 0;
111 for (int i = 0; i < min_length; i++) {
112 long s = x[i];
113 long p = y[i];
114 long m = s - p;
115 if (m < 0) m = -m;
116 sad += m;
117 }
118 return sad;
119 }
120
121 /// CHECK-START: long Main.sadLong2LongAt1(long[], long[]) 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: <<ConsL:j\d+>> LongConstant 1 loop:none
125 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
126 /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
127 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
128 /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
129 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
Aart Bik3dad3412018-02-28 12:01:46 -0800130 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700131 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
132 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
133 //
Aart Bik9cb7fe42017-11-30 11:46:45 -0800134 /// CHECK-START-{ARM64,MIPS64}: long Main.sadLong2LongAt1(long[], long[]) loop_optimization (after)
Lena Djokic38e380b2017-10-30 16:17:10 +0100135 /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
136 /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none
137 /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
138 /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
139 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
140 /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
141 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
142 /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
143 /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
144 /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none
Aart Bikdbbac8f2017-09-01 13:06:08 -0700145 private static long sadLong2LongAt1(long[] x, long[] y) {
146 int min_length = Math.min(x.length, y.length);
147 long sad = 1; // starts at 1
148 for (int i = 0; i < min_length; i++) {
149 sad += Math.abs(x[i] - y[i]);
150 }
151 return sad;
152 }
153
154 public static void main(String[] args) {
155 // Cross-test the two most extreme values individually.
156 long[] x = { 0, Long.MIN_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
157 long[] y = { 0, Long.MAX_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
158 expectEquals(1L, sadLong2Long(x, y));
159 expectEquals(1L, sadLong2Long(y, x));
160 expectEquals(-1L, sadLong2LongAlt(x, y));
161 expectEquals(-1L, sadLong2LongAlt(y, x));
162 expectEquals(1L, sadLong2LongAlt2(x, y));
163 expectEquals(1L, sadLong2LongAlt2(y, x));
164 expectEquals(2L, sadLong2LongAt1(x, y));
165 expectEquals(2L, sadLong2LongAt1(y, x));
166
167 // Use cross-values for the interesting values.
168 long[] interesting = {
169 0x0000000000000000L, 0x0000000000000001L, 0x000000007fffffffL,
170 0x0000000080000000L, 0x0000000080000001L, 0x00000000ffffffffL,
171 0x0000000100000000L, 0x0000000100000001L, 0x000000017fffffffL,
172 0x0000000180000000L, 0x0000000180000001L, 0x00000001ffffffffL,
173 0x7fffffff00000000L, 0x7fffffff00000001L, 0x7fffffff7fffffffL,
174 0x7fffffff80000000L, 0x7fffffff80000001L, 0x7fffffffffffffffL,
175 0x8000000000000000L, 0x8000000000000001L, 0x800000007fffffffL,
176 0x8000000080000000L, 0x8000000080000001L, 0x80000000ffffffffL,
177 0x8000000100000000L, 0x8000000100000001L, 0x800000017fffffffL,
178 0x8000000180000000L, 0x8000000180000001L, 0x80000001ffffffffL,
179 0xffffffff00000000L, 0xffffffff00000001L, 0xffffffff7fffffffL,
180 0xffffffff80000000L, 0xffffffff80000001L, 0xffffffffffffffffL
181 };
182 int n = interesting.length;
183 int m = n * n + 1;
184 x = new long[m];
185 y = new long[m];
186 int k = 0;
187 for (int i = 0; i < n; i++) {
188 for (int j = 0; j < n; j++) {
189 x[k] = interesting[i];
190 y[k] = interesting[j];
191 k++;
192 }
193 }
194 x[k] = 10;
195 y[k] = 2;
196 expectEquals(8L, sadLong2Long(x, y));
197 expectEquals(-901943132200L, sadLong2LongAlt(x, y));
198 expectEquals(8L, sadLong2LongAlt2(x, y));
199 expectEquals(9L, sadLong2LongAt1(x, y));
200
201 System.out.println("passed");
202 }
203
204 private static void expectEquals(long expected, long result) {
205 if (expected != result) {
206 throw new Error("Expected: " + expected + ", found: " + result);
207 }
208 }
209}