1 /* 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 */ 20 public class SimdSadLong { 21 22 /// CHECK-START: long SimdSadLong.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 31 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none 32 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none 33 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none 34 // 35 /// CHECK-START-ARM64: long SimdSadLong.sadLong2Long(long[], long[]) loop_optimization (after) 36 /// 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 sadLong2Long(long[] x, long[] y)46 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 SimdSadLong.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 SimdSadLong.sadLong2LongAlt(long[], long[]) loop_optimization (after) 72 /// CHECK-NOT: VecSADAccumulate sadLong2LongAlt(long[] x, long[] y)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 SimdSadLong.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 93 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none 94 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none 95 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none 96 // 97 /// CHECK-START-ARM64: long SimdSadLong.sadLong2LongAlt2(long[], long[]) loop_optimization (after) 98 /// 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 sadLong2LongAlt2(long[] x, long[] y)108 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 SimdSadLong.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 130 /// CHECK-DAG: <<Intrin:j\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none 131 /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none 132 /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none 133 // 134 /// CHECK-START-ARM64: long SimdSadLong.sadLong2LongAt1(long[], long[]) loop_optimization (after) 135 /// 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 sadLong2LongAt1(long[] x, long[] y)145 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 main()154 public static void main() { 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("SimdSadLong passed"); 202 } 203 expectEquals(long expected, long result)204 private static void expectEquals(long expected, long result) { 205 if (expected != result) { 206 throw new Error("Expected: " + expected + ", found: " + result); 207 } 208 } 209 } 210