1 /*
2  * Copyright (C) 2016 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 
19   public class ExampleObj {
20     int n1;
21     int n2;
22 
ExampleObj(int n1, int n2)23     public ExampleObj(int n1, int n2) {
24       this.n1 = n1;
25       this.n2 = n2;
26     }
27   }
28 
29   static int static_variable = 0;
30 
31   public ExampleObj my_obj;
32   public static int number1;
33   public static int number2;
34   public static volatile int number3;
35 
36   /// CHECK-START-ARM64: int Main.arrayAccess() scheduler (before)
37   /// CHECK:    <<Const1:i\d+>>       IntConstant 1
38   /// CHECK:    <<res0:i\d+>>         Phi
39   /// CHECK:    <<i0:i\d+>>           Phi
40   /// CHECK:    <<Array:i\d+>>        IntermediateAddress
41   /// CHECK:    <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<i0>>]
42   /// CHECK:    <<res1:i\d+>>         Add [<<res0>>,<<ArrayGet1>>]
43   /// CHECK:    <<i1:i\d+>>           Add [<<i0>>,<<Const1>>]
44   /// CHECK:    <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<i1>>]
45   /// CHECK:                          Add [<<res1>>,<<ArrayGet2>>]
46 
47   /// CHECK-START-ARM64: int Main.arrayAccess() scheduler (after)
48   /// CHECK:    <<Const1:i\d+>>       IntConstant 1
49   /// CHECK:    <<res0:i\d+>>         Phi
50   /// CHECK:    <<i0:i\d+>>           Phi
51   /// CHECK:    <<Array:i\d+>>        IntermediateAddress
52   /// CHECK:    <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<i0>>]
53   /// CHECK:    <<i1:i\d+>>           Add [<<i0>>,<<Const1>>]
54   /// CHECK:    <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<i1>>]
55   /// CHECK:    <<res1:i\d+>>         Add [<<res0>>,<<ArrayGet1>>]
56   /// CHECK:                          Add [<<res1>>,<<ArrayGet2>>]
57 
arrayAccess()58   public static int arrayAccess() {
59     int res = 0;
60     int [] array = new int[10];
61     for (int i = 0; i < 9; i++) {
62       res += array[i];
63       res += array[i + 1];
64     }
65     return res;
66   }
67 
68   /// CHECK-START-ARM: void Main.arrayAccessVariable(int) scheduler (before)
69   /// CHECK:     <<Param:i\d+>>        ParameterValue
70   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
71   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
72   /// CHECK-DAG: <<Const3:i\d+>>       IntConstant -1
73   /// CHECK:     <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
74   /// CHECK:     <<Add2:i\d+>>         Add [<<Param>>,<<Const2>>]
75   /// CHECK:     <<Add3:i\d+>>         Add [<<Param>>,<<Const3>>]
76   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
77   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
78   /// CHECK:     <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const1>>]
79   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
80   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Add2>>]
81   /// CHECK:     <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const1>>]
82   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Add2>>,<<AddArray2>>]
83   /// CHECK:     <<ArrayGet3:i\d+>>    ArrayGet [<<Array>>,<<Add3>>]
84   /// CHECK:     <<AddArray3:i\d+>>    Add [<<ArrayGet3>>,<<Const1>>]
85   /// CHECK:     <<ArraySet3:v\d+>>    ArraySet [<<Array>>,<<Add3>>,<<AddArray3>>]
86 
87   /// CHECK-START-ARM: void Main.arrayAccessVariable(int) scheduler (after)
88   /// CHECK:     <<Param:i\d+>>        ParameterValue
89   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
90   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
91   /// CHECK-DAG: <<Const3:i\d+>>       IntConstant -1
92   /// CHECK:     <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
93   /// CHECK:     <<Add2:i\d+>>         Add [<<Param>>,<<Const2>>]
94   /// CHECK:     <<Add3:i\d+>>         Add [<<Param>>,<<Const3>>]
95   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
96   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
97   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
98   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
99   /// CHECK:                           Add
100   /// CHECK:                           Add
101   /// CHECK:                           Add
102   /// CHECK:                           ArraySet
103   /// CHECK:                           ArraySet
104   /// CHECK:                           ArraySet
105 
106   /// CHECK-START-ARM64: void Main.arrayAccessVariable(int) scheduler (before)
107   /// CHECK:     <<Param:i\d+>>        ParameterValue
108   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
109   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
110   /// CHECK-DAG: <<Const3:i\d+>>       IntConstant -1
111   /// CHECK:     <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
112   /// CHECK:     <<Add2:i\d+>>         Add [<<Param>>,<<Const2>>]
113   /// CHECK:     <<Add3:i\d+>>         Add [<<Param>>,<<Const3>>]
114   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
115   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
116   /// CHECK:     <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const1>>]
117   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
118   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Add2>>]
119   /// CHECK:     <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const1>>]
120   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Add2>>,<<AddArray2>>]
121   /// CHECK:     <<ArrayGet3:i\d+>>    ArrayGet [<<Array>>,<<Add3>>]
122   /// CHECK:     <<AddArray3:i\d+>>    Add [<<ArrayGet3>>,<<Const1>>]
123   /// CHECK:     <<ArraySet3:v\d+>>    ArraySet [<<Array>>,<<Add3>>,<<AddArray3>>]
124 
125   /// CHECK-START-ARM64: void Main.arrayAccessVariable(int) scheduler (after)
126   /// CHECK:     <<Param:i\d+>>        ParameterValue
127   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
128   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
129   /// CHECK-DAG: <<Const3:i\d+>>       IntConstant -1
130   /// CHECK:     <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
131   /// CHECK:     <<Add2:i\d+>>         Add [<<Param>>,<<Const2>>]
132   /// CHECK:     <<Add3:i\d+>>         Add [<<Param>>,<<Const3>>]
133   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
134   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
135   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
136   /// CHECK:                           ArrayGet [<<Array>>,{{i\d+}}]
137   /// CHECK:                           Add
138   /// CHECK:                           Add
139   /// CHECK:                           Add
140   /// CHECK:                           ArraySet
141   /// CHECK:                           ArraySet
142   /// CHECK:                           ArraySet
arrayAccessVariable(int i)143   public static void arrayAccessVariable(int i) {
144     int [] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
145     for (int j = 0; j < 100; j++) {
146       array[i + 1]++;
147       array[i + 2]++;
148       array[i - 1]++;
149     }
150   }
151 
152   /// CHECK-START-ARM: void Main.arrayAccessSub(int) scheduler (before)
153   /// CHECK:      <<Param:i\d+>>        ParameterValue
154   /// CHECK-DAG:  <<Const1:i\d+>>       IntConstant -1
155   /// CHECK-DAG:  <<Const2:i\d+>>       IntConstant 9
156   /// CHECK-DAG:  <<Const3:i\d+>>       IntConstant 1
157   /// CHECK:      <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
158   /// CHECK:      <<Sub2:i\d+>>         Sub [<<Const2>>,<<Param>>]
159   /// CHECK:      <<Array:i\d+>>        IntermediateAddress
160   /// CHECK:      <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
161   /// CHECK:      <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const3>>]
162   /// CHECK:      <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
163   /// CHECK:      <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Sub2>>]
164   /// CHECK:      <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const3>>]
165   /// CHECK:      <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Sub2>>,<<AddArray2>>]
166 
167   /// CHECK-START-ARM: void Main.arrayAccessSub(int) scheduler (after)
168   /// CHECK:      <<Param:i\d+>>        ParameterValue
169   /// CHECK-DAG:  <<Const1:i\d+>>       IntConstant -1
170   /// CHECK-DAG:  <<Const2:i\d+>>       IntConstant 9
171   /// CHECK-DAG:  <<Const3:i\d+>>       IntConstant 1
172   /// CHECK:      <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
173   /// CHECK:      <<Sub2:i\d+>>         Sub [<<Const2>>,<<Param>>]
174   /// CHECK:      <<Array:i\d+>>        IntermediateAddress
175   /// CHECK:      <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
176   /// CHECK:      <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const3>>]
177   /// CHECK:      <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
178   /// CHECK:      <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Sub2>>]
179   /// CHECK:      <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const3>>]
180   /// CHECK:      <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Sub2>>,<<AddArray2>>]
181 
182   /// CHECK-START-ARM64: void Main.arrayAccessSub(int) scheduler (before)
183   /// CHECK:      <<Param:i\d+>>        ParameterValue
184   /// CHECK-DAG:  <<Const1:i\d+>>       IntConstant -1
185   /// CHECK-DAG:  <<Const2:i\d+>>       IntConstant 9
186   /// CHECK-DAG:  <<Const3:i\d+>>       IntConstant 1
187   /// CHECK:      <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
188   /// CHECK:      <<Sub2:i\d+>>         Sub [<<Const2>>,<<Param>>]
189   /// CHECK:      <<Array:i\d+>>        IntermediateAddress
190   /// CHECK:      <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
191   /// CHECK:      <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const3>>]
192   /// CHECK:      <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
193   /// CHECK:      <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Sub2>>]
194   /// CHECK:      <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const3>>]
195   /// CHECK:      <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Sub2>>,<<AddArray2>>]
196 
197   /// CHECK-START-ARM64: void Main.arrayAccessSub(int) scheduler (after)
198   /// CHECK:      <<Param:i\d+>>        ParameterValue
199   /// CHECK-DAG:  <<Const1:i\d+>>       IntConstant -1
200   /// CHECK-DAG:  <<Const2:i\d+>>       IntConstant 9
201   /// CHECK-DAG:  <<Const3:i\d+>>       IntConstant 1
202   /// CHECK:      <<Add1:i\d+>>         Add [<<Param>>,<<Const1>>]
203   /// CHECK:      <<Sub2:i\d+>>         Sub [<<Const2>>,<<Param>>]
204   /// CHECK:      <<Array:i\d+>>        IntermediateAddress
205   /// CHECK:      <<ArrayGet1:i\d+>>    ArrayGet [<<Array>>,<<Add1>>]
206   /// CHECK:      <<AddArray1:i\d+>>    Add [<<ArrayGet1>>,<<Const3>>]
207   /// CHECK:      <<ArraySet1:v\d+>>    ArraySet [<<Array>>,<<Add1>>,<<AddArray1>>]
208   /// CHECK:      <<ArrayGet2:i\d+>>    ArrayGet [<<Array>>,<<Sub2>>]
209   /// CHECK:      <<AddArray2:i\d+>>    Add [<<ArrayGet2>>,<<Const3>>]
210   /// CHECK:      <<ArraySet2:v\d+>>    ArraySet [<<Array>>,<<Sub2>>,<<AddArray2>>]
arrayAccessSub(int i)211   public static void arrayAccessSub(int i) {
212     int [] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
213     for (int j = 0; j < 100; j++) {
214       // These two accesses MAY ALIAS
215       array[i - 1]++;
216       array[9 - i]++;
217     }
218   }
219 
220   /// CHECK-START-ARM: void Main.arrayAccessLoopVariable() scheduler (before)
221   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
222   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
223   /// CHECK:     <<Phi:i\d+>>          Phi
224   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
225   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet
226   /// CHECK:     <<AddArray1:i\d+>>    Add
227   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet
228   /// CHECK:     <<AddVar:i\d+>>       Add
229   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet
230   /// CHECK:     <<AddArray2:i\d+>>    Add
231   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet
232 
233   /// CHECK-START-ARM: void Main.arrayAccessLoopVariable() scheduler (after)
234   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
235   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
236   /// CHECK:     <<Phi:i\d+>>          Phi
237   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
238   /// CHECK:     <<AddVar:i\d+>>       Add
239   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet
240   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet
241   /// CHECK:     <<AddArray1:i\d+>>    Add
242   /// CHECK:     <<AddArray2:i\d+>>    Add
243   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet
244   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet
245 
246   /// CHECK-START-ARM64: void Main.arrayAccessLoopVariable() scheduler (before)
247   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
248   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
249   /// CHECK:     <<Phi:i\d+>>          Phi
250   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
251   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet
252   /// CHECK:     <<AddArray1:i\d+>>    Add
253   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet
254   /// CHECK:     <<AddVar:i\d+>>       Add
255   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet
256   /// CHECK:     <<AddArray2:i\d+>>    Add
257   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet
258 
259   /// CHECK-START-ARM64: void Main.arrayAccessLoopVariable() scheduler (after)
260   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
261   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
262   /// CHECK:     <<Phi:i\d+>>          Phi
263   /// CHECK:     <<Array:i\d+>>        IntermediateAddress
264   /// CHECK:     <<AddVar:i\d+>>       Add
265   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet
266   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet
267   /// CHECK:     <<AddArray1:i\d+>>    Add
268   /// CHECK:     <<AddArray2:i\d+>>    Add
269   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet
270   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet
arrayAccessLoopVariable()271   public static void arrayAccessLoopVariable() {
272     int [] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
273     for (int j = 0; j < 9; j++) {
274       array[j]++;
275       array[j + 1]++;
276     }
277   }
278 
279   // This case tests a bug found in LSA where LSA doesn't understand IntermediateAddress,
280   // and incorrectly reported no alias between ArraySet1 and ArrayGet2,
281   // thus ArrayGet2 is scheduled above ArraySet1 incorrectly.
282 
283   /// CHECK-START-ARM64: void Main.CrossOverLoop(int[], int[]) scheduler (before)
284   /// CHECK:     <<ParamA:l\d+>>       ParameterValue                           loop:none
285   /// CHECK:     <<ParamB:l\d+>>       ParameterValue                           loop:none
286   /// CHECK:     <<NullB:l\d+>>        NullCheck [<<ParamB>>]                   loop:none
287   /// CHECK:     <<NullA:l\d+>>        NullCheck [<<ParamA>>]                   loop:none
288   /// CHECK:                           Phi                                      loop:<<Loop:B\d+>> outer_loop:none
289   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet [<<NullB>>,{{i\d+}}]            loop:<<Loop>>      outer_loop:none
290   /// CHECK:                           Add                                      loop:<<Loop>>      outer_loop:none
291   /// CHECK:     <<Addr1:i\d+>>        IntermediateAddress [<<NullA>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
292   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}]   loop:<<Loop>>      outer_loop:none
293   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet [<<NullB>>,{{i\d+}}]            loop:<<Loop>>      outer_loop:none
294   /// CHECK:                           Add                                      loop:<<Loop>>      outer_loop:none
295   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}]   loop:<<Loop>>      outer_loop:none
296   /// CHECK:                           Add                                      loop:<<Loop>>      outer_loop:none
297 
298   /// CHECK-START-ARM64: void Main.CrossOverLoop(int[], int[]) scheduler (after)
299   /// CHECK:     <<ParamA:l\d+>>       ParameterValue                           loop:none
300   /// CHECK:     <<ParamB:l\d+>>       ParameterValue                           loop:none
301   /// CHECK:     <<NullB:l\d+>>        NullCheck [<<ParamB>>]                   loop:none
302   /// CHECK:     <<NullA:l\d+>>        NullCheck [<<ParamA>>]                   loop:none
303   /// CHECK:                           Phi                                      loop:<<Loop:B\d+>> outer_loop:none
304   /// CHECK:     <<ArrayGet1:i\d+>>    ArrayGet [<<NullB>>,{{i\d+}}]            loop:<<Loop>>      outer_loop:none
305   /// CHECK:     <<Addr1:i\d+>>        IntermediateAddress [<<NullA>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
306   /// CHECK:                           Add [<<ArrayGet1>>,{{i\d+}}]             loop:<<Loop>>      outer_loop:none
307   /// CHECK:     <<ArraySet1:v\d+>>    ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}]   loop:<<Loop>>      outer_loop:none
308   /// CHECK:     <<ArrayGet2:i\d+>>    ArrayGet [<<NullB>>,{{i\d+}}]            loop:<<Loop>>      outer_loop:none
309   /// CHECK:                           Add                                      loop:<<Loop>>      outer_loop:none
310   /// CHECK:     <<ArraySet2:v\d+>>    ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}]   loop:<<Loop>>      outer_loop:none
311   /// CHECK:                           Add                                      loop:<<Loop>>      outer_loop:none
CrossOverLoop(int a[], int b[])312   private static void CrossOverLoop(int a[], int b[]) {
313     b[20] = 99;
314     for (int i = 0; i < a.length; i++) {
315       a[i] = b[20] - 7;
316       i++;
317       a[i] = b[20] - 7;
318     }
319   }
320 
321   // This test case is similar to above cross over loop,
322   // but has more complex chains of transforming the original references:
323   // ParameterValue --> BoundType --> NullCheck --> ArrayGet.
324   // ParameterValue --> BoundType --> NullCheck --> IntermediateAddress --> ArraySet.
325   // After using LSA to analyze the original references, the scheduler should be able
326   // to find out that 'a' and 'b' may alias, hence unable to schedule these ArraGet/Set.
327 
328   /// CHECK-START-ARM64: void Main.CrossOverLoop2(java.lang.Object, java.lang.Object) scheduler (before)
329   /// CHECK:  Phi        loop:<<Loop:B\d+>> outer_loop:none
330   /// CHECK:  ArrayGet   loop:<<Loop>>      outer_loop:none
331   /// CHECK:  Add        loop:<<Loop>>      outer_loop:none
332   /// CHECK:  ArraySet   loop:<<Loop>>      outer_loop:none
333   /// CHECK:  ArrayGet   loop:<<Loop>>      outer_loop:none
334   /// CHECK:  Add        loop:<<Loop>>      outer_loop:none
335   /// CHECK:  ArraySet   loop:<<Loop>>      outer_loop:none
336 
337   /// CHECK-START-ARM64: void Main.CrossOverLoop2(java.lang.Object, java.lang.Object) scheduler (after)
338   /// CHECK:  Phi        loop:<<Loop:B\d+>> outer_loop:none
339   /// CHECK:  ArrayGet   loop:<<Loop>>      outer_loop:none
340   /// CHECK:  Add        loop:<<Loop>>      outer_loop:none
341   /// CHECK:  ArraySet   loop:<<Loop>>      outer_loop:none
342   /// CHECK:  ArrayGet   loop:<<Loop>>      outer_loop:none
343   /// CHECK:  Add        loop:<<Loop>>      outer_loop:none
344   /// CHECK:  ArraySet   loop:<<Loop>>      outer_loop:none
CrossOverLoop2(Object a, Object b)345   private static void CrossOverLoop2(Object a, Object b) {
346     ((int[])b)[20] = 99;
347     for (int i = 0; i < ((int[])a).length; i++) {
348       ((int[])a)[i] = ((int[])b)[20] - 7;
349       i++;
350       ((int[])a)[i] = ((int[])b)[20] - 7;
351     }
352   }
353 
354   /// CHECK-START-ARM: void Main.accessFields() scheduler (before)
355   /// CHECK:            InstanceFieldGet
356   /// CHECK:            Add
357   /// CHECK:            InstanceFieldSet
358   /// CHECK:            InstanceFieldGet
359   /// CHECK:            Add
360   /// CHECK:            InstanceFieldSet
361   /// CHECK:            StaticFieldGet
362   /// CHECK:            Add
363   /// CHECK:            StaticFieldSet
364   /// CHECK:            StaticFieldGet
365   /// CHECK:            Add
366   /// CHECK:            StaticFieldSet
367 
368   /// CHECK-START-ARM: void Main.accessFields() scheduler (after)
369   /// CHECK-DAG:        InstanceFieldGet
370   /// CHECK-DAG:        InstanceFieldGet
371   /// CHECK-DAG:        StaticFieldGet
372   /// CHECK-DAG:        StaticFieldGet
373   /// CHECK:            Add
374   /// CHECK:            Add
375   /// CHECK:            Add
376   /// CHECK:            Add
377   /// CHECK-DAG:        InstanceFieldSet
378   /// CHECK-DAG:        InstanceFieldSet
379   /// CHECK-DAG:        StaticFieldSet
380   /// CHECK-DAG:        StaticFieldSet
381 
382   /// CHECK-START-ARM64: void Main.accessFields() scheduler (before)
383   /// CHECK:            InstanceFieldGet
384   /// CHECK:            Add
385   /// CHECK:            InstanceFieldSet
386   /// CHECK:            InstanceFieldGet
387   /// CHECK:            Add
388   /// CHECK:            InstanceFieldSet
389   /// CHECK:            StaticFieldGet
390   /// CHECK:            Add
391   /// CHECK:            StaticFieldSet
392   /// CHECK:            StaticFieldGet
393   /// CHECK:            Add
394   /// CHECK:            StaticFieldSet
395 
396   /// CHECK-START-ARM64: void Main.accessFields() scheduler (after)
397   /// CHECK-DAG:        InstanceFieldGet
398   /// CHECK-DAG:        InstanceFieldGet
399   /// CHECK-DAG:        StaticFieldGet
400   /// CHECK-DAG:        StaticFieldGet
401   /// CHECK:            Add
402   /// CHECK:            Add
403   /// CHECK:            Add
404   /// CHECK:            Add
405   /// CHECK-DAG:        InstanceFieldSet
406   /// CHECK-DAG:        InstanceFieldSet
407   /// CHECK-DAG:        StaticFieldSet
408   /// CHECK-DAG:        StaticFieldSet
accessFields()409   public void accessFields() {
410     my_obj = new ExampleObj(1, 2);
411     for (int i = 0; i < 10; i++) {
412       my_obj.n1++;
413       my_obj.n2++;
414       // Note: ClinitCheck(Main) is eliminated because Main initialization is trivial. b/62478025
415       number1++;
416       number2++;
417     }
418   }
419 
420   /// CHECK-START-ARM: void Main.accessFieldsVolatile() scheduler (before)
421   /// CHECK-START-ARM64: void Main.accessFieldsVolatile() scheduler (before)
422   /// CHECK:            InstanceFieldGet
423   /// CHECK:            Add
424   /// CHECK:            InstanceFieldSet
425   /// CHECK:            InstanceFieldGet
426   /// CHECK:            Add
427   /// CHECK:            InstanceFieldSet
428   /// CHECK:            StaticFieldGet
429   /// CHECK:            Add
430   /// CHECK:            StaticFieldSet
431   /// CHECK:            StaticFieldGet
432   /// CHECK:            Add
433   /// CHECK:            StaticFieldSet
434 
435   /// CHECK-START-ARM: void Main.accessFieldsVolatile() scheduler (after)
436   /// CHECK-START-ARM64: void Main.accessFieldsVolatile() scheduler (after)
437   /// CHECK:            InstanceFieldGet
438   /// CHECK:            Add
439   /// CHECK:            InstanceFieldSet
440   /// CHECK:            InstanceFieldGet
441   /// CHECK:            Add
442   /// CHECK:            InstanceFieldSet
443   /// CHECK:            StaticFieldGet
444   /// CHECK:            Add
445   /// CHECK:            StaticFieldSet
446   /// CHECK:            StaticFieldGet
447   /// CHECK:            Add
448   /// CHECK:            StaticFieldSet
449 
accessFieldsVolatile()450   public void accessFieldsVolatile() {
451     my_obj = new ExampleObj(1, 2);
452     for (int i = 0; i < 10; i++) {
453       my_obj.n1++;
454       my_obj.n2++;
455       number1++;
456       number3++;
457     }
458   }
459 
460   /// CHECK-START-ARM: void Main.accessFieldsUnresolved() scheduler (before)
461   /// CHECK-START-ARM64: void Main.accessFieldsUnresolved() scheduler (before)
462   /// CHECK:            InstanceFieldGet
463   /// CHECK:            Add
464   /// CHECK:            InstanceFieldSet
465   /// CHECK:            InstanceFieldGet
466   /// CHECK:            Add
467   /// CHECK:            InstanceFieldSet
468   /// CHECK:            UnresolvedInstanceFieldGet
469   /// CHECK:            Add
470   /// CHECK:            UnresolvedInstanceFieldSet
471   /// CHECK:            UnresolvedStaticFieldGet
472   /// CHECK:            Add
473   /// CHECK:            UnresolvedStaticFieldSet
474 
475   /// CHECK-START-ARM: void Main.accessFieldsUnresolved() scheduler (after)
476   /// CHECK-START-ARM64: void Main.accessFieldsUnresolved() scheduler (after)
477   /// CHECK:            InstanceFieldGet
478   /// CHECK:            Add
479   /// CHECK:            InstanceFieldSet
480   /// CHECK:            InstanceFieldGet
481   /// CHECK:            Add
482   /// CHECK:            InstanceFieldSet
483   /// CHECK:            UnresolvedInstanceFieldGet
484   /// CHECK:            Add
485   /// CHECK:            UnresolvedInstanceFieldSet
486   /// CHECK:            UnresolvedStaticFieldGet
487   /// CHECK:            Add
488   /// CHECK:            UnresolvedStaticFieldSet
489 
accessFieldsUnresolved()490   public void accessFieldsUnresolved() {
491     my_obj = new ExampleObj(1, 2);
492     UnresolvedClass unresolved_obj = new UnresolvedClass();
493     for (int i = 0; i < 10; i++) {
494       my_obj.n1++;
495       my_obj.n2++;
496       unresolved_obj.instanceInt++;
497       UnresolvedClass.staticInt++;
498     }
499   }
500 
501   /// CHECK-START-ARM64: int Main.intDiv(int) scheduler (before)
502   /// CHECK:               Sub
503   /// CHECK:               DivZeroCheck
504   /// CHECK:               Div
505   /// CHECK:               StaticFieldSet
506 
507   /// CHECK-START-ARM64: int Main.intDiv(int) scheduler (after)
508   /// CHECK:               Sub
509   /// CHECK-NOT:           StaticFieldSet
510   /// CHECK:               DivZeroCheck
511   /// CHECK-NOT:           Sub
512   /// CHECK:               Div
intDiv(int arg)513   public static int intDiv(int arg) {
514     int res = 0;
515     int tmp = arg;
516     for (int i = 1; i < arg; i++) {
517       tmp -= i;
518       res = res / i;  // div-zero check barrier.
519       static_variable++;
520     }
521     res += tmp;
522     return res;
523   }
524 
expectEquals(int expected, int result)525   private static void expectEquals(int expected, int result) {
526     if (expected != result) {
527       throw new Error("Expected: " + expected + ", found: " + result);
528     }
529   }
530 
531   private static final int ARRAY_SIZE = 32;
532 
533   // Check that VecReplicateScalar is not reordered.
534   /// CHECK-START-ARM64: void Main.testVecReplicateScalar() scheduler (before)
535   /// CHECK:     Phi                loop:<<Loop:B\d+>> outer_loop:none
536   /// CHECK:     NewArray           loop:<<Loop>>      outer_loop:none
537   /// CHECK:     VecReplicateScalar loop:<<Loop>>      outer_loop:none
538 
539   /// CHECK-START-ARM64: void Main.testVecReplicateScalar() scheduler (after)
540   /// CHECK:     Phi                loop:<<Loop:B\d+>> outer_loop:none
541   /// CHECK:     NewArray           loop:<<Loop>>      outer_loop:none
542   /// CHECK:     VecReplicateScalar loop:<<Loop>>      outer_loop:none
testVecReplicateScalar()543   private static void testVecReplicateScalar() {
544     for (int j = 0; j <= 8; j++) {
545       int[] a = new int[ARRAY_SIZE];
546       for (int i = 0; i < a.length; i++) {
547         a[i] += 1;
548       }
549       for (int i = 0; i < a.length; i++) {
550         expectEquals(1, a[i]);
551       }
552     }
553   }
554 
555   // Check that VecSetScalars, VecReduce, VecExtractScalar are not reordered.
556   /// CHECK-START-ARM64: void Main.testVecSetScalars() scheduler (before)
557   /// CHECK:     Phi                  loop:<<Loop:B\d+>> outer_loop:none
558   /// CHECK:     NewArray             loop:<<Loop>>      outer_loop:none
559   /// CHECK:     VecSetScalars        loop:<<Loop>>      outer_loop:none
560   //
561   /// CHECK:     VecReduce            loop:<<Loop>>      outer_loop:none
562   /// CHECK:     VecExtractScalar     loop:<<Loop>>      outer_loop:none
563   /// CHECK:     InvokeStaticOrDirect loop:<<Loop>>      outer_loop:none
564   /// CHECK:     InvokeStaticOrDirect loop:<<Loop>>      outer_loop:none
565 
566   /// CHECK-START-ARM64: void Main.testVecSetScalars() scheduler (after)
567   /// CHECK:     Phi                  loop:<<Loop:B\d+>> outer_loop:none
568   /// CHECK:     NewArray             loop:<<Loop>>      outer_loop:none
569   /// CHECK:     VecSetScalars        loop:<<Loop>>      outer_loop:none
570   //
571   /// CHECK:     VecReduce            loop:<<Loop>>      outer_loop:none
572   /// CHECK:     VecExtractScalar     loop:<<Loop>>      outer_loop:none
573   /// CHECK:     InvokeStaticOrDirect loop:<<Loop>>      outer_loop:none
574   /// CHECK:     InvokeStaticOrDirect loop:<<Loop>>      outer_loop:none
testVecSetScalars()575   private static void testVecSetScalars() {
576     for (int j = 0; j <= 8; j++) {
577       int[] a = new int[ARRAY_SIZE];
578       int s = 5;
579       for (int i = 0; i < ARRAY_SIZE; i++) {
580         s+=a[i];
581       }
582       expectEquals(a[0], 0);
583       expectEquals(s, 5);
584     }
585   }
586 
587   // Check that instructions having cross iteration dependencies are not
588   // reordered.
589   //
590   /// CHECK-START-{ARM,ARM64}: void Main.testCrossItersDependencies() scheduler (before)
591   /// CHECK:     <<ID1:i\d+>>  Phi [{{i\d+}},<<ID3:i\d+>>]
592   /// CHECK:     <<ID2:i\d+>>  Phi [{{i\d+}},<<ID4:i\d+>>]
593   //
594   /// CHECK:     <<ID3>>  Sub [<<ID1>>,<<ID2>>]
595   /// CHECK:     <<ID4>>  Add [<<ID2>>,{{i\d+}}]
596 
597   /// CHECK-START-{ARM,ARM64}: void Main.testCrossItersDependencies() scheduler (after)
598   /// CHECK:     <<ID1:i\d+>>  Phi [{{i\d+}},<<ID3:i\d+>>]
599   /// CHECK:     <<ID2:i\d+>>  Phi [{{i\d+}},<<ID4:i\d+>>]
600   //
601   /// CHECK:     <<ID3>>  Sub [<<ID1>>,<<ID2>>]
602   /// CHECK:     <<ID4>>  Add [<<ID2>>,{{i\d+}}]
603 
604   /// CHECK-START-ARM: void Main.testCrossItersDependencies() disassembly (after)
605   /// CHECK:     subs
606   /// CHECK:     add
607   /// CHECK:     adds
608   /// CHECK:     ldrh
609   /// CHECK:     cmp
610   /// CHECK:     beq
611 
612   /// CHECK-START-ARM64: void Main.testCrossItersDependencies() disassembly (after)
613   /// CHECK:     sub
614   /// CHECK:     add
615   /// CHECK:     add
616   /// CHECK:     ldrh
617   /// CHECK:     cbz
testCrossItersDependencies()618   private static void testCrossItersDependencies() {
619     int[] data = {1, 2, 3, 0};
620     int sub = 0;
621     int sum = data[0];
622     for (int i = 1; data[i] != 0; ++i) {
623       sub -= sum;
624       sum += data[i];
625     }
626     expectEquals(sub, -4);
627     expectEquals(sum, 6);
628   }
629 
630   // Check instructions defining values for the next iteration don't become
631   // self-dependent in a scheduling graph which prevents valid reordering.
632   //
633   /// CHECK-START-{ARM,ARM64}: void Main.testNoSelfDependantSchedNode(int) scheduler (before)
634   /// CHECK:     IntermediateAddress
635   /// CHECK:     ArrayGet
636   /// CHECK:     LessThanOrEqual
637   /// CHECK:     Select
638   /// CHECK:     IntermediateAddress
639   /// CHECK:     ArraySet
640   /// CHECK:     Add
641 
642   /// CHECK-START-{ARM,ARM64}: void Main.testNoSelfDependantSchedNode(int) scheduler (after)
643   /// CHECK:     IntermediateAddress
644   /// CHECK:     ArrayGet
645   /// CHECK:     IntermediateAddress
646   /// CHECK:     LessThanOrEqual
647   /// CHECK:     Select
648   /// CHECK:     ArraySet
649   /// CHECK:     Add
650   //
651   // Parameter n is to prevent unrolling of the main loop.
testNoSelfDependantSchedNode(int n)652   private static void testNoSelfDependantSchedNode(int n) {
653     final int MAX = 2;
654     int[] a = {1, 2, 3};
655     int[] b = new int[a.length];
656     n = Math.min(n, a.length);
657     for (int i = 0; i < n; ++i) {
658       int j = a[i];
659       b[i] = (j > MAX ? MAX : 0);
660     }
661     expectEquals(b[0], 0);
662     expectEquals(b[1], 0);
663     expectEquals(b[2], 2);
664   }
665 
666   // In case of cross iteration dependencies when a value for the next iteration is also used on
667   // the current iteration a MOV instruction is generated anyway. In such cases setting dependency
668   // between scheduling nodes will not eliminate MOV.
669   // In the test 'i+1' is such an example.
670   // The test checks that a dependency between scheduling nodes (first ArrayGet and Add) is not
671   // setup and Add is scheduled before ArrayGet.
672   //
673   /// CHECK-START-{ARM,ARM64}: void Main.testNonPreventingSchedulingCrossItersDeps(int) scheduler (before)
674   /// CHECK:          IntermediateAddress
675   /// CHECK-NEXT:     ArrayGet
676   /// CHECK-NEXT:     Add
677   /// CHECK-NEXT:     ArrayGet
678 
679   /// CHECK-START-{ARM,ARM64}: void Main.testNonPreventingSchedulingCrossItersDeps(int) scheduler (after)
680   /// CHECK:          IntermediateAddress
681   /// CHECK-NEXT:     Add
682   /// CHECK-NEXT:     ArrayGet
683   /// CHECK-NEXT:     ArrayGet
684   //
685   // Parameter n is to prevent unrolling of the main loop.
testNonPreventingSchedulingCrossItersDeps(int n)686   private static void testNonPreventingSchedulingCrossItersDeps(int n) {
687     int[] a = {1, 2, 3};
688     n = Math.min(n, a.length);
689     for (int i = 0; i < n - 1; ++i) {
690       if (a[i] < a[i + 1]) {
691         int tmp = a[i];
692         a[i] = a[i + 1];
693         a[i + 1] = tmp;
694       }
695     }
696     expectEquals(a[0], 2);
697     expectEquals(a[1], 3);
698     expectEquals(a[2], 1);
699   }
700 
main(String[] args)701   public static void main(String[] args) {
702     testVecSetScalars();
703     testVecReplicateScalar();
704     testCrossItersDependencies();
705     testNoSelfDependantSchedNode(3);
706     testNonPreventingSchedulingCrossItersDeps(3);
707     if ((arrayAccess() + intDiv(10)) != -35) {
708       System.out.println("FAIL");
709     }
710   }
711 }
712