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