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 halving-add idiomatic vectorization.
19  */
20 public class Main {
21 
22   private static final int N = 64 * 1024;
23   private static final int M = N + 31;
24 
25   static short[] sB1 = new short[M];
26   static short[] sB2 = new short[M];
27   static short[] sBo = new short[M];
28 
29   /// CHECK-START: void Main.halving_add_signed(short[], short[], short[]) loop_optimization (before)
30   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
31   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
32   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
33   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
34   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
35   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
36   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
37   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
38   //
39   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed(short[], short[], short[]) loop_optimization (after)
40   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
41   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
42   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
43   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
halving_add_signed(short[] b1, short[] b2, short[] bo)44   private static void halving_add_signed(short[] b1, short[] b2, short[] bo) {
45     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
46     for (int i = 0; i < min_length; i++) {
47       bo[i] = (short) ((b1[i] + b2[i]) >> 1);
48     }
49   }
50 
51   /// CHECK-START: void Main.halving_add_signed_alt(short[], short[], short[]) loop_optimization (before)
52   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
53   /// CHECK-DAG: <<I10:i\d+>>  IntConstant 10                      loop:none
54   /// CHECK-DAG: <<M10:i\d+>>  IntConstant -10                     loop:none
55   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
56   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
57   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
58   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I10>>]              loop:<<Loop>>      outer_loop:none
59   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get2>>,<<M10>>]              loop:<<Loop>>      outer_loop:none
60   /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>]             loop:<<Loop>>      outer_loop:none
61   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add3>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
62   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
63   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
64   //
65   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
66   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
67   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
68   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
69   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
halving_add_signed_alt(short[] b1, short[] b2, short[] bo)70   private static void halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
71     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
72     for (int i = 0; i < min_length; i++) {
73       // Cancelling constant computations do not confuse recognition.
74       bo[i] = (short) (((b1[i] + 10) + (b2[i] - 10)) >> 1);
75     }
76   }
77 
78   /// CHECK-START: void Main.halving_add_unsigned(short[], short[], short[]) instruction_simplifier (before)
79   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
80   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
81   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
82   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
83   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
84   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
85   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
86   /// CHECK-DAG: <<Add:i\d+>>  Add [<<And1>>,<<And2>>]             loop:<<Loop>>      outer_loop:none
87   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
88   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
89   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
90   //
91   /// CHECK-START: void Main.halving_add_unsigned(short[], short[], short[]) loop_optimization (before)
92   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
93   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
94   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
95   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
96   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
97   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
98   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
99   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
100   //
101   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
102   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
103   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
104   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
105   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
halving_add_unsigned(short[] b1, short[] b2, short[] bo)106   private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
107     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
108     for (int i = 0; i < min_length; i++) {
109       bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff)) >> 1);
110     }
111   }
112 
113   /// CHECK-START: void Main.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (before)
114   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
115   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
116   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
117   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
118   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
119   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
120   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
121   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
122   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
123   //
124   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
125   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
126   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
127   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
128   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
rounding_halving_add_signed(short[] b1, short[] b2, short[] bo)129   private static void rounding_halving_add_signed(short[] b1, short[] b2, short[] bo) {
130     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
131     for (int i = 0; i < min_length; i++) {
132       bo[i] = (short) ((b1[i] + b2[i] + 1) >> 1);
133     }
134   }
135 
136   /// CHECK-START: void Main.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (before)
137   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
138   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
139   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
140   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
141   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
142   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
143   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
144   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
145   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
146   //
147   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
148   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
149   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
150   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
151   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
rounding_halving_add_signed_alt(short[] b1, short[] b2, short[] bo)152   private static void rounding_halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
153     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
154     for (int i = 0; i < min_length; i++) {
155       // Slightly different order in idiom does not confuse recognition.
156       bo[i] = (short) (((1 + b1[i]) + b2[i]) >> 1);
157     }
158   }
159 
160   /// CHECK-START: void Main.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (before)
161   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
162   /// CHECK-DAG: <<I10:i\d+>>  IntConstant 10                      loop:none
163   /// CHECK-DAG: <<M9:i\d+>>   IntConstant -9                      loop:none
164   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
165   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
166   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
167   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I10>>]              loop:<<Loop>>      outer_loop:none
168   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get2>>,<<M9>>]               loop:<<Loop>>      outer_loop:none
169   /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>]             loop:<<Loop>>      outer_loop:none
170   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add3>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
171   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
172   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
173   //
174   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (after)
175   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
176   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
177   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
178   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
rounding_halving_add_signed_alt2(short[] b1, short[] b2, short[] bo)179   private static void rounding_halving_add_signed_alt2(short[] b1, short[] b2, short[] bo) {
180     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
181     for (int i = 0; i < min_length; i++) {
182       // Computations that cancel to adding 1 also do not confuse recognition.
183       bo[i] = (short) (((b1[i] + 10) + (b2[i] - 9)) >> 1);
184     }
185   }
186 
187   /// CHECK-START: void Main.rounding_halving_add_unsigned(short[], short[], short[]) instruction_simplifier (before)
188   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
189   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
190   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
191   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
192   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
193   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
194   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
195   /// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>]             loop:<<Loop>>      outer_loop:none
196   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
198   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
199   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
200   //
201   /// CHECK-START: void Main.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (before)
202   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
203   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
204   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
205   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
206   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
207   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
208   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
209   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
210   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
211   //
212   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
213   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
214   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
215   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
216   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo)217   private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
218     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
219     for (int i = 0; i < min_length; i++) {
220       bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff) + 1) >> 1);
221     }
222   }
223 
224   /// CHECK-START: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) instruction_simplifier (before)
225   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
226   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
227   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
228   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
229   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
230   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
231   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
232   /// CHECK-DAG: <<Add1:i\d+>> Add [<<And2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
233   /// CHECK-DAG: <<Add2:i\d+>> Add [<<And1>>,<<Add1>>]             loop:<<Loop>>      outer_loop:none
234   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
235   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
236   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
237   //
238   /// CHECK-START: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (before)
239   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
240   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
241   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
242   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
243   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
244   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get1>>,<<Add1>>]             loop:<<Loop>>      outer_loop:none
245   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
246   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
247   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
248   //
249   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (after)
250   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
251   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
252   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
253   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
rounding_halving_add_unsigned_alt(short[] b1, short[] b2, short[] bo)254   private static void rounding_halving_add_unsigned_alt(short[] b1, short[] b2, short[] bo) {
255     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
256     for (int i = 0; i < min_length; i++) {
257       // Slightly different order in idiom does not confuse recognition.
258       bo[i] = (short) ((b1[i] & 0xffff) + ((b2[i] & 0xffff) + 1) >> 1);
259     }
260   }
261 
262   /// CHECK-START: void Main.halving_add_signed_constant(short[], short[]) loop_optimization (before)
263   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
264   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                   loop:none
265   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
266   /// CHECK-DAG: <<Get:s\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
267   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<SMAX>>]              loop:<<Loop>>      outer_loop:none
268   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
269   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
270   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
271   //
272   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed_constant(short[], short[]) loop_optimization (after)
273   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
274   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
275   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
276   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
277   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
halving_add_signed_constant(short[] b1, short[] bo)278   private static void halving_add_signed_constant(short[] b1, short[] bo) {
279     int min_length = Math.min(bo.length, b1.length);
280     for (int i = 0; i < min_length; i++) {
281       bo[i] = (short) ((b1[i] + 0x7fff) >> 1);
282     }
283   }
284 
285   /// CHECK-START: void Main.halving_add_unsigned_constant(short[], short[]) instruction_simplifier (before)
286   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
287   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
288   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
289   /// CHECK-DAG: <<Get:s\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
290   /// CHECK-DAG: <<And:i\d+>>  And [<<Get>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
291   /// CHECK-DAG: <<Add:i\d+>>  Add [<<And>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
292   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
293   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
294   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
295   //
296   /// CHECK-START: void Main.halving_add_unsigned_constant(short[], short[]) loop_optimization (before)
297   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
298   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
299   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
300   /// CHECK-DAG: <<Get:c\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
301   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
302   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
303   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
304   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
305   //
306   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
307   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
308   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
309   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
310   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
311   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
halving_add_unsigned_constant(short[] b1, short[] bo)312   private static void halving_add_unsigned_constant(short[] b1, short[] bo) {
313     int min_length = Math.min(bo.length, b1.length);
314     for (int i = 0; i < min_length; i++) {
315       bo[i] = (short) (((b1[i] & 0xffff) + 0xffff) >> 1);
316     }
317   }
318 
main(String[] args)319   public static void main(String[] args) {
320     // Some interesting values.
321     short[] interesting = {
322       (short) 0x0000,
323       (short) 0x0001,
324       (short) 0x0002,
325       (short) 0x1234,
326       (short) 0x8000,
327       (short) 0x8001,
328       (short) 0x7fff,
329       (short) 0xffff
330     };
331     // Initialize cross-values to test all cases, and also
332     // set up some extra values to exercise the cleanup loop.
333     for (int i = 0; i < M; i++) {
334       sB1[i] = (short) i;
335       sB2[i] = interesting[i & 7];
336     }
337 
338     // Test halving add idioms.
339     halving_add_signed(sB1, sB2, sBo);
340     for (int i = 0; i < M; i++) {
341       short e = (short) ((sB1[i] + sB2[i]) >> 1);
342       expectEquals(e, sBo[i]);
343     }
344     halving_add_signed_alt(sB1, sB2, sBo);
345     for (int i = 0; i < M; i++) {
346       short e = (short) ((sB1[i] + sB2[i]) >> 1);
347       expectEquals(e, sBo[i]);
348     }
349     halving_add_unsigned(sB1, sB2, sBo);
350     for (int i = 0; i < M; i++) {
351       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff)) >> 1);
352       expectEquals(e, sBo[i]);
353     }
354     rounding_halving_add_signed(sB1, sB2, sBo);
355     for (int i = 0; i < M; i++) {
356       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
357       expectEquals(e, sBo[i]);
358     }
359     rounding_halving_add_signed_alt(sB1, sB2, sBo);
360     for (int i = 0; i < M; i++) {
361       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
362       expectEquals(e, sBo[i]);
363     }
364     rounding_halving_add_signed_alt2(sB1, sB2, sBo);
365     for (int i = 0; i < M; i++) {
366       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
367       expectEquals(e, sBo[i]);
368     }
369     rounding_halving_add_unsigned(sB1, sB2, sBo);
370     for (int i = 0; i < M; i++) {
371       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff) + 1) >> 1);
372       expectEquals(e, sBo[i]);
373     }
374     rounding_halving_add_unsigned_alt(sB1, sB2, sBo);
375     for (int i = 0; i < M; i++) {
376       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff) + 1) >> 1);
377       expectEquals(e, sBo[i]);
378     }
379     halving_add_signed_constant(sB1, sBo);
380     for (int i = 0; i < M; i++) {
381       short e = (short) ((sB1[i] + 0x7fff) >> 1);
382       expectEquals(e, sBo[i]);
383     }
384     halving_add_unsigned_constant(sB1, sBo);
385     for (int i = 0; i < M; i++) {
386       short e = (short) (((sB1[i] & 0xffff) + 0xffff) >> 1);
387       expectEquals(e, sBo[i]);
388     }
389 
390     System.out.println("passed");
391   }
392 
expectEquals(int expected, int result)393   private static void expectEquals(int expected, int result) {
394     if (expected != result) {
395       throw new Error("Expected: " + expected + ", found: " + result);
396     }
397   }
398 }
399