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 MIN/MAX vectorization. 19 */ 20 public class Main { 21 22 /// CHECK-START: void Main.doitMin(double[], double[], double[]) loop_optimization (before) 23 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 24 /// CHECK-DAG: <<Get1:d\d+>> ArrayGet loop:<<Loop>> outer_loop:none 25 /// CHECK-DAG: <<Get2:d\d+>> ArrayGet loop:<<Loop>> outer_loop:none 26 /// CHECK-DAG: <<Min:d\d+>> InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMinDoubleDouble loop:<<Loop>> outer_loop:none 27 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Min>>] loop:<<Loop>> outer_loop:none 28 // 29 // TODO x86: 0.0 vs -0.0? 30 // TODO MIPS64: min(x, NaN)? 31 // 32 /// CHECK-START-ARM64: void Main.doitMin(double[], double[], double[]) loop_optimization (after) 33 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 34 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 35 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 36 /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 37 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Min>>] loop:<<Loop>> outer_loop:none 38 private static void doitMin(double[] x, double[] y, double[] z) { 39 int min = Math.min(x.length, Math.min(y.length, z.length)); 40 for (int i = 0; i < min; i++) { 41 x[i] = Math.min(y[i], z[i]); 42 } 43 } 44 45 /// CHECK-START: void Main.doitMax(double[], double[], double[]) loop_optimization (before) 46 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 47 /// CHECK-DAG: <<Get1:d\d+>> ArrayGet loop:<<Loop>> outer_loop:none 48 /// CHECK-DAG: <<Get2:d\d+>> ArrayGet loop:<<Loop>> outer_loop:none 49 /// CHECK-DAG: <<Max:d\d+>> InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMaxDoubleDouble loop:<<Loop>> outer_loop:none 50 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Max>>] loop:<<Loop>> outer_loop:none 51 // 52 // TODO x86: 0.0 vs -0.0? 53 // TODO MIPS64: max(x, NaN)? 54 // 55 /// CHECK-START-ARM64: void Main.doitMax(double[], double[], double[]) loop_optimization (after) 56 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 57 /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 58 /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 59 /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 60 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Max>>] loop:<<Loop>> outer_loop:none 61 private static void doitMax(double[] x, double[] y, double[] z) { 62 int min = Math.min(x.length, Math.min(y.length, z.length)); 63 for (int i = 0; i < min; i++) { 64 x[i] = Math.max(y[i], z[i]); 65 } 66 } 67 68 public static void main(String[] args) { 69 double[] interesting = { 70 -0.0f, 71 +0.0f, 72 -1.0f, 73 +1.0f, 74 -3.14f, 75 +3.14f, 76 -100.0f, 77 +100.0f, 78 -4444.44f, 79 +4444.44f, 80 Double.MIN_NORMAL, 81 Double.MIN_VALUE, 82 Double.MAX_VALUE, 83 Double.NEGATIVE_INFINITY, 84 Double.POSITIVE_INFINITY, 85 Double.NaN 86 }; 87 // Initialize cross-values for the interesting values. 88 int total = interesting.length * interesting.length; 89 double[] x = new double[total]; 90 double[] y = new double[total]; 91 double[] z = new double[total]; 92 int k = 0; 93 for (int i = 0; i < interesting.length; i++) { 94 for (int j = 0; j < interesting.length; j++) { 95 x[k] = 0; 96 y[k] = interesting[i]; 97 z[k] = interesting[j]; 98 k++; 99 } 100 } 101 102 // And test. 103 doitMin(x, y, z); 104 for (int i = 0; i < total; i++) { 105 double expected = Math.min(y[i], z[i]); 106 expectEquals(expected, x[i]); 107 } 108 doitMax(x, y, z); 109 for (int i = 0; i < total; i++) { 110 double expected = Math.max(y[i], z[i]); 111 expectEquals(expected, x[i]); 112 } 113 114 System.out.println("passed"); 115 } 116 117 private static void expectEquals(double expected, double result) { 118 // Tests the bits directly. This distinguishes correctly between +0.0 119 // and -0.0 and returns a canonical representation for all NaN. 120 long expected_bits = Double.doubleToLongBits(expected); 121 long result_bits = Double.doubleToLongBits(result); 122 if (expected_bits != result_bits) { 123 throw new Error("Expected: " + expected + 124 "(0x" + Long.toHexString(expected_bits) + "), found: " + result + 125 "(0x" + Long.toHexString(result_bits) + ")"); 126 } 127 } 128 } 129