1 /*
2  * Copyright (C) 2015 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 public class Main {
18 
assertIntEquals(int expected, int result)19   public static void assertIntEquals(int expected, int result) {
20     if (expected != result) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
25   /**
26    * Test that HArrayGet with a constant index is not split.
27    */
28 
29   /// CHECK-START-ARM64: int Main.constantIndexGet(int[]) instruction_simplifier_arm64 (before)
30   /// CHECK:             <<Array:l\d+>>         NullCheck
31   /// CHECK:             <<Index:i\d+>>         BoundsCheck
32   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
33 
34   /// CHECK-START-ARM64: int Main.constantIndexGet(int[]) instruction_simplifier_arm64 (after)
35   /// CHECK:             <<Array:l\d+>>         NullCheck
36   /// CHECK:             <<Index:i\d+>>         BoundsCheck
37   /// CHECK-NOT:                                IntermediateAddress
38   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
39 
40 
41   /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (before)
42   /// CHECK:             <<Array:l\d+>>         NullCheck
43   /// CHECK:             <<Index:i\d+>>         BoundsCheck
44   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
45 
46   /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (after)
47   /// CHECK:           <<Array:l\d+>>         NullCheck
48   /// CHECK:           <<Index:i\d+>>         BoundsCheck
49   /// CHECK-NOT:                              IntermediateAddress
50   /// CHECK:                                  ArrayGet [<<Array>>,<<Index>>]
51 
constantIndexGet(int array[])52   public static int constantIndexGet(int array[]) {
53     return array[1];
54   }
55 
56   /**
57    * Test that HArraySet with a constant index is not split.
58    */
59 
60   /// CHECK-START-ARM64: void Main.constantIndexSet(int[]) instruction_simplifier_arm64 (before)
61   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
62   /// CHECK:             <<Array:l\d+>>         NullCheck
63   /// CHECK:             <<Index:i\d+>>         BoundsCheck
64   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
65 
66   /// CHECK-START-ARM64: void Main.constantIndexSet(int[]) instruction_simplifier_arm64 (after)
67   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
68   /// CHECK:             <<Array:l\d+>>         NullCheck
69   /// CHECK:             <<Index:i\d+>>         BoundsCheck
70   /// CHECK-NOT:                                IntermediateAddress
71   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
72 
73 
74   /// CHECK-START-ARM:   void Main.constantIndexSet(int[]) instruction_simplifier_arm (before)
75   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
76   /// CHECK:             <<Array:l\d+>>         NullCheck
77   /// CHECK:             <<Index:i\d+>>         BoundsCheck
78   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
79 
80   /// CHECK-START-ARM:   void Main.constantIndexSet(int[]) instruction_simplifier_arm (after)
81   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
82   /// CHECK:             <<Array:l\d+>>         NullCheck
83   /// CHECK:             <<Index:i\d+>>         BoundsCheck
84   /// CHECK-NOT:                                IntermediateAddress
85   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
86 
constantIndexSet(int array[])87   public static void constantIndexSet(int array[]) {
88     array[1] = 2;
89   }
90 
91   /**
92    * Test basic splitting of HArrayGet.
93    */
94 
95   /// CHECK-START-ARM64: int Main.get(int[], int) instruction_simplifier_arm64 (before)
96   /// CHECK:             <<Array:l\d+>>         NullCheck
97   /// CHECK:             <<Index:i\d+>>         BoundsCheck
98   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
99 
100   /// CHECK-START-ARM64: int Main.get(int[], int) instruction_simplifier_arm64 (after)
101   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
102   /// CHECK:             <<Array:l\d+>>         NullCheck
103   /// CHECK:             <<Index:i\d+>>         BoundsCheck
104   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
105   /// CHECK-NEXT:                               ArrayGet [<<Address>>,<<Index>>]
106 
107 
108   /// CHECK-START-ARM:   int Main.get(int[], int) instruction_simplifier_arm (before)
109   /// CHECK:             <<Array:l\d+>>         NullCheck
110   /// CHECK:             <<Index:i\d+>>         BoundsCheck
111   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
112 
113   /// CHECK-START-ARM:   int Main.get(int[], int) instruction_simplifier_arm (after)
114   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
115   /// CHECK:             <<Array:l\d+>>         NullCheck
116   /// CHECK:             <<Index:i\d+>>         BoundsCheck
117   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
118   /// CHECK-NEXT:                               ArrayGet [<<Address>>,<<Index>>]
119 
get(int array[], int index)120   public static int get(int array[], int index) {
121     return array[index];
122   }
123 
124   /**
125    * Test basic splitting of HArraySet.
126    */
127 
128   /// CHECK-START-ARM64: void Main.set(int[], int, int) instruction_simplifier_arm64 (before)
129   /// CHECK:                                    ParameterValue
130   /// CHECK:                                    ParameterValue
131   /// CHECK:             <<Arg:i\d+>>           ParameterValue
132   /// CHECK:             <<Array:l\d+>>         NullCheck
133   /// CHECK:             <<Index:i\d+>>         BoundsCheck
134   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Arg>>]
135 
136   /// CHECK-START-ARM64: void Main.set(int[], int, int) instruction_simplifier_arm64 (after)
137   /// CHECK:                                    ParameterValue
138   /// CHECK:                                    ParameterValue
139   /// CHECK:             <<Arg:i\d+>>           ParameterValue
140   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
141   /// CHECK:             <<Array:l\d+>>         NullCheck
142   /// CHECK:             <<Index:i\d+>>         BoundsCheck
143   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
144   /// CHECK-NEXT:                               ArraySet [<<Address>>,<<Index>>,<<Arg>>]
145 
146 
147   /// CHECK-START-ARM:   void Main.set(int[], int, int) instruction_simplifier_arm (before)
148   /// CHECK:                                    ParameterValue
149   /// CHECK:                                    ParameterValue
150   /// CHECK:             <<Arg:i\d+>>           ParameterValue
151   /// CHECK:             <<Array:l\d+>>         NullCheck
152   /// CHECK:             <<Index:i\d+>>         BoundsCheck
153   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Arg>>]
154 
155   /// CHECK-START-ARM:   void Main.set(int[], int, int) instruction_simplifier_arm (after)
156   /// CHECK:                                    ParameterValue
157   /// CHECK:                                    ParameterValue
158   /// CHECK:             <<Arg:i\d+>>           ParameterValue
159   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
160   /// CHECK:             <<Array:l\d+>>         NullCheck
161   /// CHECK:             <<Index:i\d+>>         BoundsCheck
162   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
163   /// CHECK-NEXT:                               ArraySet [<<Address>>,<<Index>>,<<Arg>>]
164 
set(int array[], int index, int value)165   public static void set(int array[], int index, int value) {
166     array[index] = value;
167   }
168 
169   /**
170    * Check that the intermediate address can be shared after GVN.
171    */
172 
173   /// CHECK-START-ARM64: void Main.getSet(int[], int) instruction_simplifier_arm64 (before)
174   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
175   /// CHECK:             <<Array:l\d+>>         NullCheck
176   /// CHECK:             <<Index:i\d+>>         BoundsCheck
177   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
178   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
179   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
180 
181   /// CHECK-START-ARM64: void Main.getSet(int[], int) instruction_simplifier_arm64 (after)
182   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
183   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
184   /// CHECK:             <<Array:l\d+>>         NullCheck
185   /// CHECK:             <<Index:i\d+>>         BoundsCheck
186   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
187   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
188   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
189   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
190   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
191 
192   /// CHECK-START-ARM64: void Main.getSet(int[], int) GVN$after_arch (after)
193   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
194   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
195   /// CHECK:             <<Array:l\d+>>         NullCheck
196   /// CHECK:             <<Index:i\d+>>         BoundsCheck
197   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
198   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
199   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
200   /// CHECK-NOT:                                IntermediateAddress
201   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Add>>]
202 
203 
204   /// CHECK-START-ARM:   void Main.getSet(int[], int) instruction_simplifier_arm (before)
205   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
206   /// CHECK:             <<Array:l\d+>>         NullCheck
207   /// CHECK:             <<Index:i\d+>>         BoundsCheck
208   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
209   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
210   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
211 
212   /// CHECK-START-ARM:   void Main.getSet(int[], int) instruction_simplifier_arm (after)
213   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
214   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
215   /// CHECK:             <<Array:l\d+>>         NullCheck
216   /// CHECK:             <<Index:i\d+>>         BoundsCheck
217   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
218   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
219   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
220   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
221   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
222 
223   /// CHECK-START-ARM:   void Main.getSet(int[], int) GVN$after_arch (after)
224   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
225   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
226   /// CHECK:             <<Array:l\d+>>         NullCheck
227   /// CHECK:             <<Index:i\d+>>         BoundsCheck
228   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
229   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
230   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
231   /// CHECK-NOT:                                IntermediateAddress
232   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Add>>]
getSet(int array[], int index)233   public static void getSet(int array[], int index) {
234     array[index] = array[index] + 1;
235   }
236 
237   /**
238    * Check that the intermediate address computation is not reordered or merged
239    * across IRs that can trigger GC.
240    */
241 
242   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) instruction_simplifier_arm64 (before)
243   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
244   /// CHECK:             <<Array:l\d+>>         NullCheck
245   /// CHECK:             <<Index:i\d+>>         BoundsCheck
246   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
247   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
248   /// CHECK:                                    NewArray
249   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
250 
251   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) instruction_simplifier_arm64 (after)
252   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
253   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
254   /// CHECK:             <<Array:l\d+>>         NullCheck
255   /// CHECK:             <<Index:i\d+>>         BoundsCheck
256   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
257   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
258   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
259   /// CHECK:                                    NewArray
260   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
261   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
262 
263   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) GVN$after_arch (after)
264   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
265   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
266   /// CHECK:             <<Array:l\d+>>         NullCheck
267   /// CHECK:             <<Index:i\d+>>         BoundsCheck
268   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
269   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
270   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
271   /// CHECK:                                    NewArray
272   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
273   /// CHECK:                                    ArraySet [<<Address2>>,<<Index>>,<<Add>>]
274 
275 
276   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) instruction_simplifier_arm (before)
277   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
278   /// CHECK:             <<Array:l\d+>>         NullCheck
279   /// CHECK:             <<Index:i\d+>>         BoundsCheck
280   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
281   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
282   /// CHECK:                                    NewArray
283   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
284 
285   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) instruction_simplifier_arm (after)
286   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
287   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
288   /// CHECK:             <<Array:l\d+>>         NullCheck
289   /// CHECK:             <<Index:i\d+>>         BoundsCheck
290   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
291   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
292   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
293   /// CHECK:                                    NewArray
294   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
295   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
296 
297   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) GVN$after_arch (after)
298   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
299   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
300   /// CHECK:             <<Array:l\d+>>         NullCheck
301   /// CHECK:             <<Index:i\d+>>         BoundsCheck
302   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
303   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
304   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
305   /// CHECK:                                    NewArray
306   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
307   /// CHECK:                                    ArraySet [<<Address2>>,<<Index>>,<<Add>>]
308 
accrossGC(int array[], int index)309   public static int[] accrossGC(int array[], int index) {
310     int tmp = array[index] + 1;
311     int[] new_array = new int[1];
312     array[index] = tmp;
313     return new_array;
314   }
315 
316   /**
317    * Test that the intermediate address is shared between array accesses after
318    * the bounds check have been removed by BCE.
319    */
320   // For checker tests `instruction_simplifier_<arch> (after)` below, by the time we reach
321   // the architecture-specific instruction simplifier, BCE has removed the bounds checks in
322   // the loop.
323 
324   // Note that we do not care that the `DataOffset` is `12`. But if we do not
325   // specify it and any other `IntConstant` appears before that instruction,
326   // checker will match the previous `IntConstant`, and we will thus fail the
327   // check.
328 
329   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (before)
330   /// CHECK:             <<Const7:i\d+>>        IntConstant 7
331   /// CHECK:             <<Array:l\d+>>         NewArray
332   /// CHECK:             <<Index:i\d+>>         Phi
333   /// CHECK:                                    If
334   //  -------------- Loop
335   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
336   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
337   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Div>>]
338 
339   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (after)
340   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
341   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
342   /// CHECK:             <<Array:l\d+>>         NewArray
343   /// CHECK:             <<Index:i\d+>>         Phi
344   /// CHECK:                                    If
345   //  -------------- Loop
346   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
347   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
348   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
349   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
350   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Div>>]
351 
352   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() GVN$after_arch (after)
353   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
354   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
355   /// CHECK:             <<Array:l\d+>>         NewArray
356   /// CHECK:             <<Index:i\d+>>         Phi
357   /// CHECK:                                    If
358   //  -------------- Loop
359   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
360   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
361   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
362   /// CHECK-NOT:                                IntermediateAddress
363   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Div>>]
364 
365 
366   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() instruction_simplifier_arm (before)
367   /// CHECK:             <<Const7:i\d+>>        IntConstant 7
368   /// CHECK:             <<Array:l\d+>>         NewArray
369   /// CHECK:             <<Index:i\d+>>         Phi
370   /// CHECK:                                    If
371   //  -------------- Loop
372   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
373   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
374   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Div>>]
375 
376   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() instruction_simplifier_arm (after)
377   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
378   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
379   /// CHECK:             <<Array:l\d+>>         NewArray
380   /// CHECK:             <<Index:i\d+>>         Phi
381   /// CHECK:                                    If
382   //  -------------- Loop
383   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
384   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
385   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
386   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
387   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Div>>]
388 
389   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() GVN$after_arch (after)
390   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
391   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
392   /// CHECK:             <<Array:l\d+>>         NewArray
393   /// CHECK:             <<Index:i\d+>>         Phi
394   /// CHECK:                                    If
395   //  -------------- Loop
396   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
397   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
398   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
399   /// CHECK-NOT:                                IntermediateAddress
400   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Div>>]
401 
canMergeAfterBCE1()402   public static int canMergeAfterBCE1() {
403     int[] array = {0, 7, 14, 21, 28, 35, 42};
404     for (int i = 0; i < array.length; i++) {
405       array[i] = array[i] / 7;
406     }
407     return array[array.length - 1];
408   }
409 
410   /**
411    * This test case is similar to `canMergeAfterBCE1`, but with different
412    * indexes for the accesses.
413    */
414 
415   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() instruction_simplifier_arm64 (before)
416   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
417   /// CHECK:             <<Array:l\d+>>         NewArray
418   /// CHECK:             <<Index:i\d+>>         Phi
419   /// CHECK:                                    If
420   //  -------------- Loop
421   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
422   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Array>>,<<Index>>]
423   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Array>>,<<Index1>>]
424   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
425   /// CHECK:                                    ArraySet [<<Array>>,<<Index1>>,<<Shl>>]
426 
427   // Note that we do not care that the `DataOffset` is `12`. But if we do not
428   // specify it and any other `IntConstant` appears before that instruction,
429   // checker will match the previous `IntConstant`, and we will thus fail the
430   // check.
431 
432   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() instruction_simplifier_arm64 (after)
433   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
434   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
435   /// CHECK:             <<Array:l\d+>>         NewArray
436   /// CHECK:             <<Index:i\d+>>         Phi
437   /// CHECK:                                    If
438   //  -------------- Loop
439   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
440   /// CHECK-DAG:         <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
441   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address1>>,<<Index>>]
442   /// CHECK-DAG:         <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
443   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address2>>,<<Index1>>]
444   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
445   /// CHECK:             <<Address3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
446   /// CHECK:                                    ArraySet [<<Address3>>,<<Index1>>,<<Shl>>]
447 
448   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN$after_arch (after)
449   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
450   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
451   /// CHECK:             <<Array:l\d+>>         NewArray
452   /// CHECK:             <<Index:i\d+>>         Phi
453   /// CHECK:                                    If
454   //  -------------- Loop
455   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
456   /// CHECK-DAG:         <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
457   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address>>,<<Index>>]
458   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address>>,<<Index1>>]
459   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
460   /// CHECK:                                    ArraySet [<<Address>>,<<Index1>>,<<Shl>>]
461 
462   // There should be only one intermediate address computation in the loop.
463 
464   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN$after_arch (after)
465   /// CHECK:                                    IntermediateAddress
466   /// CHECK-NOT:                                IntermediateAddress
467 
468 
469   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() instruction_simplifier_arm (before)
470   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
471   /// CHECK:             <<Array:l\d+>>         NewArray
472   /// CHECK:             <<Index:i\d+>>         Phi
473   /// CHECK:                                    If
474   //  -------------- Loop
475   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
476   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Array>>,<<Index>>]
477   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Array>>,<<Index1>>]
478   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
479   /// CHECK:                                    ArraySet [<<Array>>,<<Index1>>,<<Shl>>]
480 
481   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() instruction_simplifier_arm (after)
482   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
483   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
484   /// CHECK:             <<Array:l\d+>>         NewArray
485   /// CHECK:             <<Index:i\d+>>         Phi
486   /// CHECK:                                    If
487   //  -------------- Loop
488   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
489   /// CHECK-DAG:         <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
490   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address1>>,<<Index>>]
491   /// CHECK-DAG:         <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
492   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address2>>,<<Index1>>]
493   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
494   /// CHECK:             <<Address3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
495   /// CHECK:                                    ArraySet [<<Address3>>,<<Index1>>,<<Shl>>]
496 
497   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() GVN$after_arch (after)
498   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
499   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
500   /// CHECK:             <<Array:l\d+>>         NewArray
501   /// CHECK:             <<Index:i\d+>>         Phi
502   /// CHECK:                                    If
503   //  -------------- Loop
504   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
505   /// CHECK-DAG:         <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
506   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address>>,<<Index>>]
507   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address>>,<<Index1>>]
508   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
509   /// CHECK:                                    ArraySet [<<Address>>,<<Index1>>,<<Shl>>]
510 
511   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() GVN$after_arch (after)
512   /// CHECK:                                    IntermediateAddress
513   /// CHECK-NOT:                                IntermediateAddress
514 
canMergeAfterBCE2()515   public static int canMergeAfterBCE2() {
516     int[] array = {128, 64, 32, 8, 4, 2 };
517     for (int i = 0; i < array.length - 1; i++) {
518       array[i + 1] = array[i] << array[i + 1];
519     }
520     return array[array.length - 1];
521   }
522 
523   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (before)
524   /// CHECK-DAG:         <<Array1:l\d+>>        NewArray
525   /// CHECK-DAG:         <<Array2:l\d+>>        NewArray
526   /// CHECK-DAG:         <<Array3:l\d+>>        NewArray
527   /// CHECK-DAG:         <<Index:i\d+>>         Phi
528   /// CHECK-DAG:                                ArrayGet [<<Array1>>,<<Index>>]
529   /// CHECK-DAG:                                ArrayGet [<<Array2>>,<<Index>>]
530   /// CHECK-DAG:                                ArrayGet [<<Array3>>,<<Index>>]
531 
532   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after)
533   /// CHECK-DAG:         <<Array1:l\d+>>        NewArray
534   /// CHECK-DAG:         <<Array2:l\d+>>        NewArray
535   /// CHECK-DAG:         <<Array3:l\d+>>        NewArray
536   /// CHECK-DAG:         <<Index:i\d+>>         Phi
537   /// CHECK-DAG:                                ArrayGet [<<Array1>>,<<Index>>]
538   /// CHECK-DAG:                                ArrayGet [<<Array2>>,<<Index>>]
539   /// CHECK-DAG:                                ArrayGet [<<Array3>>,<<Index>>]
540 
541   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after)
542   /// CHECK-NOT:                                IntermediateAddress
checkLongFloatDouble()543   public static int checkLongFloatDouble() {
544     long[] array_long = {0, 1, 2, 3};
545     float[] array_float = {(float)0.0, (float)1.0, (float)2.0, (float)3.0};
546     double[] array_double = {0.0, 1.0, 2.0, 3.0};
547     double s = 0.0;
548 
549     for (int i = 0; i < 4; i++) {
550       s += (double)array_long[i] + (double)array_float[i] + array_double[i];
551     }
552     return (int)s;
553   }
554 
555   //
556   //  Check that IntermediateAddress can be shared across BoundsCheck, DivZeroCheck and NullCheck -
557   //  instruction which have fatal slow paths.
558   //
559   /// CHECK-START-{ARM,ARM64}: void Main.checkGVNForFatalChecks(int, int, char[], int[]) GVN$after_arch (before)
560   /// CHECK:                       IntermediateAddress
561   /// CHECK:                       IntermediateAddress
562   //
563   /// CHECK-NOT:                   IntermediateAddress
564 
565   /// CHECK-START-{ARM,ARM64}: void Main.checkGVNForFatalChecks(int, int, char[], int[]) GVN$after_arch (after)
566   /// CHECK:                       IntermediateAddress
567   //
568   /// CHECK-NOT:                   IntermediateAddress
checkGVNForFatalChecks(int begin, int end, char[] buf1, int[] buf2)569   public final static void checkGVNForFatalChecks(int begin, int end, char[] buf1, int[] buf2) {
570     buf1[begin] = 'a';
571     buf2[0] = begin / end;
572     buf1[end] = 'n';
573   }
574 
575   //
576   // Check that IntermediateAddress can be shared for object ArrayGets.
577   //
578   /// CHECK-START-ARM64: int Main.checkObjectArrayGet(int, java.lang.Integer[], java.lang.Integer[]) instruction_simplifier_arm64 (before)
579   /// CHECK: <<Parameter:l\d+>>     ParameterValue
580   /// CHECK: <<Array:l\d+>>         NullCheck [<<Parameter>>]
581   /// CHECK:                        ArrayGet [<<Array>>,{{i\d+}}]
582   /// CHECK:                        ArrayGet [<<Array>>,{{i\d+}}]
583   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
584   /// CHECK:                        ArrayGet [<<Array>>,{{i\d+}}]
585   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
586   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
587 
588   /// CHECK-START-ARM64: int Main.checkObjectArrayGet(int, java.lang.Integer[], java.lang.Integer[]) instruction_simplifier_arm64 (after)
589   /// CHECK: <<Parameter:l\d+>>     ParameterValue
590   /// CHECK: <<DataOffset:i\d+>>    IntConstant 12
591   /// CHECK: <<Array:l\d+>>         NullCheck [<<Parameter>>]
592   /// CHECK: <<IntAddr1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
593   /// CHECK:                        ArrayGet [<<IntAddr1>>,{{i\d+}}]
594   /// CHECK: <<IntAddr2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
595   /// CHECK:                        ArrayGet [<<IntAddr2>>,{{i\d+}}]
596   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
597   /// CHECK: <<IntAddr3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
598   /// CHECK:                        ArrayGet [<<IntAddr3>>,{{i\d+}}]
599   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
600   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
601   //
602   /// CHECK-NOT:                    IntermediateAddress
603 
604   /// CHECK-START-ARM64: int Main.checkObjectArrayGet(int, java.lang.Integer[], java.lang.Integer[]) GVN$after_arch (after)
605   /// CHECK: <<Parameter:l\d+>>     ParameterValue
606   /// CHECK: <<DataOffset:i\d+>>    IntConstant 12
607   /// CHECK: <<Array:l\d+>>         NullCheck [<<Parameter>>]
608   /// CHECK: <<IntAddr1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
609   /// CHECK:                        ArrayGet [<<IntAddr1>>,{{i\d+}}]
610   /// CHECK:                        ArrayGet [<<IntAddr1>>,{{i\d+}}]
611   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
612   /// CHECK: <<IntAddr3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
613   /// CHECK:                        ArrayGet [<<IntAddr3>>,{{i\d+}}]
614   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
615   /// CHECK:                        ArraySet [<<Array>>,{{i\d+}},{{l\d+}}]
616   //
617   /// CHECK-NOT:                    IntermediateAddress
checkObjectArrayGet(int index, Integer[] a, Integer[] b)618   public final static int checkObjectArrayGet(int index, Integer[] a, Integer[] b) {
619     Integer five = Integer.valueOf(5);
620     int tmp1 = a[index];
621     tmp1 += a[index + 1];
622     a[index + 1] = five;
623     tmp1 += a[index + 2];
624     a[index + 2] = five;
625     a[index + 3] = five;
626     return tmp1;
627   }
628 
629   /// CHECK-START-ARM64: int Main.testIntAddressObjDisasm(java.lang.Integer[], int) disassembly (after)
630   /// CHECK: <<IntAddr:i\d+>>       IntermediateAddress
631   /// CHECK:                          add w<<AddrReg:\d+>>, {{w\d+}}, #0xc
632   /// CHECK:                        ArrayGet [<<IntAddr>>,{{i\d+}}]
633   /// CHECK:                          ldr {{w\d+}}, [x<<AddrReg>>, x{{\d+}}, lsl #2]
634   /// CHECK:                        ArrayGet [<<IntAddr>>,{{i\d+}}]
635   /// CHECK:                          ldr {{w\d+}}, [x<<AddrReg>>, x{{\d+}}, lsl #2]
636 
637   /// CHECK-START-ARM64: int Main.testIntAddressObjDisasm(java.lang.Integer[], int) disassembly (after)
638   /// CHECK:                          add {{w\d+}}, {{w\d+}}, #0xc
639   /// CHECK-NOT:                      add {{w\d+}}, {{w\d+}}, #0xc
testIntAddressObjDisasm(Integer[] obj, int x)640   private int testIntAddressObjDisasm(Integer[] obj, int x) {
641     return obj[x] + obj[x + 1];
642   }
643 
644   public final static int ARRAY_SIZE = 128;
645 
main(String[] args)646   public static void main(String[] args) {
647     int[] array = {123, 456, 789};
648 
649     assertIntEquals(456, constantIndexGet(array));
650 
651     constantIndexSet(array);
652     assertIntEquals(2, array[1]);
653 
654     assertIntEquals(789, get(array, 2));
655 
656     set(array, 1, 456);
657     assertIntEquals(456, array[1]);
658 
659     getSet(array, 0);
660     assertIntEquals(124, array[0]);
661 
662     accrossGC(array, 0);
663     assertIntEquals(125, array[0]);
664 
665     assertIntEquals(6, canMergeAfterBCE1());
666     assertIntEquals(2097152, canMergeAfterBCE2());
667 
668     assertIntEquals(18, checkLongFloatDouble());
669 
670     char[] c1 = new char[ARRAY_SIZE];
671     int[] i1 = new int[ARRAY_SIZE];
672     checkGVNForFatalChecks(1, 2, c1, i1);
673     assertIntEquals('n', c1[2]);
674   }
675 }
676