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 ABS vectorization. 19 */ 20 public class Main { 21 22 private final static boolean isDalvik = 23 System.getProperty("java.vm.name").equals("Dalvik"); 24 25 private static final int SPQUIET = 1 << 22; 26 private static final long DPQUIET = 1L << 51; 27 28 /// CHECK-START: void Main.doitByte(byte[]) loop_optimization (before) 29 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 30 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 31 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 32 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 33 // 34 /// CHECK-START-{ARM,ARM64}: void Main.doitByte(byte[]) loop_optimization (after) 35 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 36 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 37 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 38 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 39 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 40 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 41 // 42 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 43 // doitByte(byte[] x)44 private static void doitByte(byte[] x) { 45 for (int i = 0; i < x.length; i++) { 46 x[i] = (byte) Math.abs(x[i]); 47 } 48 } 49 50 /// CHECK-START: void Main.doitChar(char[]) loop_optimization (before) 51 /// CHECK-NOT: Abs 52 // 53 /// CHECK-START: void Main.doitChar(char[]) loop_optimization (after) 54 /// CHECK-NOT: VecAbs doitChar(char[] x)55 private static void doitChar(char[] x) { 56 // Basically a nop due to zero extension. 57 for (int i = 0; i < x.length; i++) { 58 x[i] = (char) Math.abs(x[i]); 59 } 60 } 61 62 /// CHECK-START: void Main.doitShort(short[]) loop_optimization (before) 63 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 64 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 65 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 66 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 67 // 68 /// CHECK-START-{ARM,ARM64}: void Main.doitShort(short[]) loop_optimization (after) 69 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 70 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 71 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 72 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 73 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 74 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 75 // 76 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 77 // doitShort(short[] x)78 private static void doitShort(short[] x) { 79 for (int i = 0; i < x.length; i++) { 80 x[i] = (short) Math.abs(x[i]); 81 } 82 } 83 84 /// CHECK-START: void Main.doitCastedChar(char[]) loop_optimization (before) 85 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 86 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 87 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 88 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 89 // 90 /// CHECK-START-ARM64: void Main.doitCastedChar(char[]) loop_optimization (after) 91 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 92 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 93 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 94 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 95 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 96 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 97 // 98 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 99 // doitCastedChar(char[] x)100 private static void doitCastedChar(char[] x) { 101 for (int i = 0; i < x.length; i++) { 102 x[i] = (char) Math.abs((short) x[i]); 103 } 104 } 105 106 /// CHECK-START: void Main.doitInt(int[]) loop_optimization (before) 107 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 108 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 109 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 110 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 111 // 112 /// CHECK-START-{ARM,ARM64}: void Main.doitInt(int[]) loop_optimization (after) 113 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 114 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 115 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 116 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 117 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 118 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 119 // 120 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 121 // doitInt(int[] x)122 private static void doitInt(int[] x) { 123 for (int i = 0; i < x.length; i++) { 124 x[i] = Math.abs(x[i]); 125 } 126 } 127 128 /// CHECK-START: void Main.doitLong(long[]) loop_optimization (before) 129 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 130 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 131 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 132 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 133 // 134 /// CHECK-START-ARM64: void Main.doitLong(long[]) loop_optimization (after) 135 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 136 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 137 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 138 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 139 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 140 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 141 // 142 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 143 // doitLong(long[] x)144 private static void doitLong(long[] x) { 145 for (int i = 0; i < x.length; i++) { 146 x[i] = Math.abs(x[i]); 147 } 148 } 149 150 /// CHECK-START: void Main.doitFloat(float[]) loop_optimization (before) 151 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 152 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 153 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 154 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 155 // 156 /// CHECK-START-ARM64: void Main.doitFloat(float[]) loop_optimization (after) 157 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 158 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 159 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 160 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 161 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 162 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 163 // 164 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 165 // doitFloat(float[] x)166 private static void doitFloat(float[] x) { 167 for (int i = 0; i < x.length; i++) { 168 x[i] = Math.abs(x[i]); 169 } 170 } 171 172 /// CHECK-START: void Main.doitDouble(double[]) loop_optimization (before) 173 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 174 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 175 /// CHECK-DAG: Abs loop:<<Loop>> outer_loop:none 176 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 177 // 178 /// CHECK-START-ARM64: void Main.doitDouble(double[]) loop_optimization (after) 179 /// CHECK-DAG: VecLoad loop:<<Loop1:B\d+>> outer_loop:none 180 /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none 181 /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none 182 /// CHECK-DAG: ArrayGet loop:<<Loop2:B\d+>> outer_loop:none 183 /// CHECK-DAG: Abs loop:<<Loop2>> outer_loop:none 184 /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none 185 // 186 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 187 // doitDouble(double[] x)188 private static void doitDouble(double[] x) { 189 for (int i = 0; i < x.length; i++) { 190 x[i] = Math.abs(x[i]); 191 } 192 } 193 main(String[] args)194 public static void main(String[] args) { 195 // Bytes, chars, shorts. 196 byte[] xb = new byte[256]; 197 for (int i = 0; i < 256; i++) { 198 xb[i] = (byte) i; 199 } 200 doitByte(xb); 201 for (int i = 0; i < 256; i++) { 202 expectEquals32((byte) Math.abs((byte) i), xb[i]); 203 } 204 char[] xc = new char[1024 * 64]; 205 for (int i = 0; i < 1024 * 64; i++) { 206 xc[i] = (char) i; 207 } 208 doitChar(xc); 209 for (int i = 0; i < 1024 * 64; i++) { 210 expectEquals32((char) Math.abs((char) i), xc[i]); 211 } 212 short[] xs = new short[1024 * 64]; 213 for (int i = 0; i < 1024 * 64; i++) { 214 xs[i] = (short) i; 215 } 216 doitShort(xs); 217 for (int i = 0; i < 1024 * 64; i++) { 218 expectEquals32((short) Math.abs((short) i), xs[i]); 219 } 220 for (int i = 0; i < 1024 * 64; i++) { 221 xc[i] = (char) i; 222 } 223 doitCastedChar(xc); 224 for (int i = 0; i < 1024 * 64; i++) { 225 expectEquals32((char) Math.abs((short) i), xc[i]); 226 } 227 // Set up minint32, maxint32 and some others. 228 int[] xi = new int[8]; 229 xi[0] = 0x80000000; 230 xi[1] = 0x7fffffff; 231 xi[2] = 0x80000001; 232 xi[3] = -13; 233 xi[4] = -1; 234 xi[5] = 0; 235 xi[6] = 1; 236 xi[7] = 999; 237 doitInt(xi); 238 expectEquals32(0x80000000, xi[0]); 239 expectEquals32(0x7fffffff, xi[1]); 240 expectEquals32(0x7fffffff, xi[2]); 241 expectEquals32(13, xi[3]); 242 expectEquals32(1, xi[4]); 243 expectEquals32(0, xi[5]); 244 expectEquals32(1, xi[6]); 245 expectEquals32(999, xi[7]); 246 247 // Set up minint64, maxint64 and some others. 248 long[] xl = new long[8]; 249 xl[0] = 0x8000000000000000L; 250 xl[1] = 0x7fffffffffffffffL; 251 xl[2] = 0x8000000000000001L; 252 xl[3] = -13; 253 xl[4] = -1; 254 xl[5] = 0; 255 xl[6] = 1; 256 xl[7] = 999; 257 doitLong(xl); 258 expectEquals64(0x8000000000000000L, xl[0]); 259 expectEquals64(0x7fffffffffffffffL, xl[1]); 260 expectEquals64(0x7fffffffffffffffL, xl[2]); 261 expectEquals64(13, xl[3]); 262 expectEquals64(1, xl[4]); 263 expectEquals64(0, xl[5]); 264 expectEquals64(1, xl[6]); 265 expectEquals64(999, xl[7]); 266 267 // Set up float NaN and some others. 268 float[] xf = new float[16]; 269 xf[0] = Float.intBitsToFloat(0x7f800001); 270 xf[1] = Float.intBitsToFloat(0x7fa00000); 271 xf[2] = Float.intBitsToFloat(0x7fc00000); 272 xf[3] = Float.intBitsToFloat(0x7fffffff); 273 xf[4] = Float.intBitsToFloat(0xff800001); 274 xf[5] = Float.intBitsToFloat(0xffa00000); 275 xf[6] = Float.intBitsToFloat(0xffc00000); 276 xf[7] = Float.intBitsToFloat(0xffffffff); 277 xf[8] = Float.NEGATIVE_INFINITY; 278 xf[9] = -99.2f; 279 xf[10] = -1.0f; 280 xf[11] = -0.0f; 281 xf[12] = +0.0f; 282 xf[13] = +1.0f; 283 xf[14] = +99.2f; 284 xf[15] = Float.POSITIVE_INFINITY; 285 doitFloat(xf); 286 expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[0])); 287 expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[1])); 288 expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[2])); 289 expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[3])); 290 expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[4])); 291 expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[5])); 292 expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[6])); 293 expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[7])); 294 expectEquals32( 295 Float.floatToRawIntBits(Float.POSITIVE_INFINITY), 296 Float.floatToRawIntBits(xf[8])); 297 expectEquals32( 298 Float.floatToRawIntBits(99.2f), 299 Float.floatToRawIntBits(xf[9])); 300 expectEquals32( 301 Float.floatToRawIntBits(1.0f), 302 Float.floatToRawIntBits(xf[10])); 303 expectEquals32(0, Float.floatToRawIntBits(xf[11])); 304 expectEquals32(0, Float.floatToRawIntBits(xf[12])); 305 expectEquals32( 306 Float.floatToRawIntBits(1.0f), 307 Float.floatToRawIntBits(xf[13])); 308 expectEquals32( 309 Float.floatToRawIntBits(99.2f), 310 Float.floatToRawIntBits(xf[14])); 311 expectEquals32( 312 Float.floatToRawIntBits(Float.POSITIVE_INFINITY), 313 Float.floatToRawIntBits(xf[15])); 314 315 // Set up double NaN and some others. 316 double[] xd = new double[16]; 317 xd[0] = Double.longBitsToDouble(0x7ff0000000000001L); 318 xd[1] = Double.longBitsToDouble(0x7ff4000000000000L); 319 xd[2] = Double.longBitsToDouble(0x7ff8000000000000L); 320 xd[3] = Double.longBitsToDouble(0x7fffffffffffffffL); 321 xd[4] = Double.longBitsToDouble(0xfff0000000000001L); 322 xd[5] = Double.longBitsToDouble(0xfff4000000000000L); 323 xd[6] = Double.longBitsToDouble(0xfff8000000000000L); 324 xd[7] = Double.longBitsToDouble(0xffffffffffffffffL); 325 xd[8] = Double.NEGATIVE_INFINITY; 326 xd[9] = -99.2f; 327 xd[10] = -1.0f; 328 xd[11] = -0.0f; 329 xd[12] = +0.0f; 330 xd[13] = +1.0f; 331 xd[14] = +99.2f; 332 xd[15] = Double.POSITIVE_INFINITY; 333 doitDouble(xd); 334 expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[0])); 335 expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[1])); 336 expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[2])); 337 expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[3])); 338 expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[4])); 339 expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[5])); 340 expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[6])); 341 expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[7])); 342 expectEquals64( 343 Double.doubleToRawLongBits(Double.POSITIVE_INFINITY), 344 Double.doubleToRawLongBits(xd[8])); 345 expectEquals64( 346 Double.doubleToRawLongBits(99.2f), 347 Double.doubleToRawLongBits(xd[9])); 348 expectEquals64( 349 Double.doubleToRawLongBits(1.0f), 350 Double.doubleToRawLongBits(xd[10])); 351 expectEquals64(0, Double.doubleToRawLongBits(xd[11])); 352 expectEquals64(0, Double.doubleToRawLongBits(xd[12])); 353 expectEquals64( 354 Double.doubleToRawLongBits(1.0f), 355 Double.doubleToRawLongBits(xd[13])); 356 expectEquals64( 357 Double.doubleToRawLongBits(99.2f), 358 Double.doubleToRawLongBits(xd[14])); 359 expectEquals64( 360 Double.doubleToRawLongBits(Double.POSITIVE_INFINITY), 361 Double.doubleToRawLongBits(xd[15])); 362 363 System.out.println("passed"); 364 } 365 expectEquals32(int expected, int result)366 private static void expectEquals32(int expected, int result) { 367 if (expected != result) { 368 throw new Error("Expected: " + expected + ", found: " + result); 369 } 370 } 371 expectEquals64(long expected, long result)372 private static void expectEquals64(long expected, long result) { 373 if (expected != result) { 374 throw new Error("Expected: " + expected + ", found: " + result); 375 } 376 } 377 378 // We allow that an expected NaN result has become quiet. expectEqualsNaN32(int expected, int result)379 private static void expectEqualsNaN32(int expected, int result) { 380 if (expected != result && (expected | SPQUIET) != result) { 381 if (!isDalvik) { 382 // If not on ART, relax the expected value more towards just 383 // "spec compliance" and allow sign bit to remain set for NaN. 384 if (expected == (result & Integer.MAX_VALUE)) { 385 return; 386 } 387 } 388 throw new Error("Expected: 0x" + Integer.toHexString(expected) 389 + ", found: 0x" + Integer.toHexString(result)); 390 } 391 } 392 393 // We allow that an expected NaN result has become quiet. expectEqualsNaN64(long expected, long result)394 private static void expectEqualsNaN64(long expected, long result) { 395 if (expected != result && (expected | DPQUIET) != result) { 396 if (!isDalvik) { 397 // If not on ART, relax the expected value more towards just 398 // "spec compliance" and allow sign bit to remain set for NaN. 399 if (expected == (result & Long.MAX_VALUE)) { 400 return; 401 } 402 } 403 throw new Error("Expected: 0x" + Long.toHexString(expected) 404 + ", found: 0x" + Long.toHexString(result)); 405 } 406 } 407 } 408