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(short[], short[], short[]) loop_optimization (before)
23   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
24   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
25   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
26   /// CHECK-DAG: <<Min:i\d+>>  InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
27   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Min>>]            loop:<<Loop>>      outer_loop:none
28   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
29   //
30   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitMin(short[], short[], short[]) loop_optimization (after)
31   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                              loop:<<Loop:B\d+>>    outer_loop:none
32   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                              loop:<<Loop>>         outer_loop:none
33   /// CHECK-DAG: <<Min:d\d+>>  VecMin [<<Get1>>,<<Get2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
34   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>>         outer_loop:none
doitMin(short[] x, short[] y, short[] z)35   private static void doitMin(short[] x, short[] y, short[] z) {
36     int min = Math.min(x.length, Math.min(y.length, z.length));
37     for (int i = 0; i < min; i++) {
38       x[i] = (short) Math.min(y[i], z[i]);
39     }
40   }
41 
42   /// CHECK-START: void Main.doitMinUnsigned(short[], short[], short[]) instruction_simplifier (before)
43   /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535                   loop:none
44   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
45   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
46   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
47   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>]             loop:<<Loop>>      outer_loop:none
48   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>]             loop:<<Loop>>      outer_loop:none
49   /// CHECK-DAG: <<Min:i\d+>>  InvokeStaticOrDirect [<<And1>>,<<And2>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
50   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Min>>]            loop:<<Loop>>      outer_loop:none
51   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
52   //
53   /// CHECK-START: void Main.doitMinUnsigned(short[], short[], short[]) loop_optimization (before)
54   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
55   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
56   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
57   /// CHECK-DAG: <<Min:i\d+>>  InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
58   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Min>>]            loop:<<Loop>>      outer_loop:none
59   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
60   //
61   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitMinUnsigned(short[], short[], short[]) loop_optimization (after)
62   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                              loop:<<Loop:B\d+>>     outer_loop:none
63   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                              loop:<<Loop>>          outer_loop:none
64   /// CHECK-DAG: <<Min:d\d+>>  VecMin [<<Get1>>,<<Get2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
65   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>>          outer_loop:none
doitMinUnsigned(short[] x, short[] y, short[] z)66   private static void doitMinUnsigned(short[] x, short[] y, short[] z) {
67     int min = Math.min(x.length, Math.min(y.length, z.length));
68     for (int i = 0; i < min; i++) {
69       x[i] = (short) Math.min(y[i] & 0xffff, z[i] & 0xffff);
70     }
71   }
72 
73   /// CHECK-START: void Main.doitMax(short[], short[], short[]) loop_optimization (before)
74   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
75   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
76   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
77   /// CHECK-DAG: <<Max:i\d+>>  InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
78   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Max>>]            loop:<<Loop>>      outer_loop:none
79   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
80   //
81   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitMax(short[], short[], short[]) loop_optimization (after)
82   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                              loop:<<Loop:B\d+>>    outer_loop:none
83   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                              loop:<<Loop>>         outer_loop:none
84   /// CHECK-DAG: <<Max:d\d+>>  VecMax [<<Get1>>,<<Get2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
85   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>>         outer_loop:none
doitMax(short[] x, short[] y, short[] z)86   private static void doitMax(short[] x, short[] y, short[] z) {
87     int min = Math.min(x.length, Math.min(y.length, z.length));
88     for (int i = 0; i < min; i++) {
89       x[i] = (short) Math.max(y[i], z[i]);
90     }
91   }
92 
93   /// CHECK-START: void Main.doitMaxUnsigned(short[], short[], short[]) instruction_simplifier (before)
94   /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535                   loop:none
95   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
96   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
97   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
98   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>]             loop:<<Loop>>      outer_loop:none
99   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>]             loop:<<Loop>>      outer_loop:none
100   /// CHECK-DAG: <<Max:i\d+>>  InvokeStaticOrDirect [<<And1>>,<<And2>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
101   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Max>>]            loop:<<Loop>>      outer_loop:none
102   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
103   //
104   /// CHECK-START: void Main.doitMaxUnsigned(short[], short[], short[]) loop_optimization (before)
105   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
106   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
107   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
108   /// CHECK-DAG: <<Max:i\d+>>  InvokeStaticOrDirect [<<Get1>>,<<Get2>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
109   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Max>>]            loop:<<Loop>>      outer_loop:none
110   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
111   //
112   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitMaxUnsigned(short[], short[], short[]) loop_optimization (after)
113   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                              loop:<<Loop:B\d+>>     outer_loop:none
114   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                              loop:<<Loop>>          outer_loop:none
115   /// CHECK-DAG: <<Max:d\d+>>  VecMax [<<Get1>>,<<Get2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none
116   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>>          outer_loop:none
doitMaxUnsigned(short[] x, short[] y, short[] z)117   private static void doitMaxUnsigned(short[] x, short[] y, short[] z) {
118     int min = Math.min(x.length, Math.min(y.length, z.length));
119     for (int i = 0; i < min; i++) {
120       x[i] = (short) Math.max(y[i] & 0xffff, z[i] & 0xffff);
121     }
122   }
123 
124   /// CHECK-START: void Main.doitMin100(short[], short[]) loop_optimization (before)
125   /// CHECK-DAG: <<I100:i\d+>> IntConstant 100                     loop:none
126   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
127   /// CHECK-DAG: <<Get:s\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
128   /// CHECK-DAG: <<Min:i\d+>>  InvokeStaticOrDirect [<<Get>>,<<I100>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
129   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Min>>]            loop:<<Loop>>      outer_loop:none
130   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
131   //
132   /// CHECK-START-{ARM64,MIPS64}: void Main.doitMin100(short[], short[]) loop_optimization (after)
133   /// CHECK-DAG: <<I100:i\d+>> IntConstant 100                      loop:none
134   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>]        loop:none
135   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                              loop:<<Loop:B\d+>>   outer_loop:none
136   /// CHECK-DAG: <<Min:d\d+>>  VecMin [<<Get>>,<<Repl>>] packed_type:Int16 loop:<<Loop>> outer_loop:none
137   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<Min>>] loop:<<Loop>>        outer_loop:none
doitMin100(short[] x, short[] y)138   private static void doitMin100(short[] x, short[] y) {
139     int min = Math.min(x.length, y.length);
140     for (int i = 0; i < min; i++) {
141       x[i] = (short) Math.min(y[i], 100);
142     }
143   }
144 
main(String[] args)145   public static void main(String[] args) {
146     short[] interesting = {
147       (short) 0x0000, (short) 0x0001, (short) 0x007f,
148       (short) 0x0080, (short) 0x0081, (short) 0x00ff,
149       (short) 0x0100, (short) 0x0101, (short) 0x017f,
150       (short) 0x0180, (short) 0x0181, (short) 0x01ff,
151       (short) 0x7f00, (short) 0x7f01, (short) 0x7f7f,
152       (short) 0x7f80, (short) 0x7f81, (short) 0x7fff,
153       (short) 0x8000, (short) 0x8001, (short) 0x807f,
154       (short) 0x8080, (short) 0x8081, (short) 0x80ff,
155       (short) 0x8100, (short) 0x8101, (short) 0x817f,
156       (short) 0x8180, (short) 0x8181, (short) 0x81ff,
157       (short) 0xff00, (short) 0xff01, (short) 0xff7f,
158       (short) 0xff80, (short) 0xff81, (short) 0xffff
159     };
160     // Initialize cross-values for the interesting values.
161     int total = interesting.length * interesting.length;
162     short[] x = new short[total];
163     short[] y = new short[total];
164     short[] z = new short[total];
165     int k = 0;
166     for (int i = 0; i < interesting.length; i++) {
167       for (int j = 0; j < interesting.length; j++) {
168         x[k] = 0;
169         y[k] = interesting[i];
170         z[k] = interesting[j];
171         k++;
172       }
173     }
174 
175     // And test.
176     doitMin(x, y, z);
177     for (int i = 0; i < total; i++) {
178       short expected = (short) Math.min(y[i], z[i]);
179       expectEquals(expected, x[i]);
180     }
181     doitMinUnsigned(x, y, z);
182     for (int i = 0; i < total; i++) {
183       short expected = (short) Math.min(y[i] & 0xffff, z[i] & 0xffff);
184       expectEquals(expected, x[i]);
185     }
186     doitMax(x, y, z);
187     for (int i = 0; i < total; i++) {
188       short expected = (short) Math.max(y[i], z[i]);
189       expectEquals(expected, x[i]);
190     }
191     doitMaxUnsigned(x, y, z);
192     for (int i = 0; i < total; i++) {
193       short expected = (short) Math.max(y[i] & 0xffff, z[i] & 0xffff);
194       expectEquals(expected, x[i]);
195     }
196     doitMin100(x, y);
197     for (int i = 0; i < total; i++) {
198       short expected = (short) Math.min(y[i], 100);
199       expectEquals(expected, x[i]);
200     }
201 
202     System.out.println("passed");
203   }
204 
expectEquals(short expected, short result)205   private static void expectEquals(short expected, short result) {
206     if (expected != result) {
207       throw new Error("Expected: " + expected + ", found: " + result);
208     }
209   }
210 }
211