blob: 5a66fbbebc90d3ed360afa99b8f67c9e48ae8cf6 [file] [log] [blame]
Alexandre Rames22aa54b2016-10-18 09:32:29 +01001/*
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
17public class Main {
18
xueliang.zhong2a3471f2017-05-08 18:36:40 +010019 public class ExampleObj {
20 int n1;
21 int n2;
22
23 public ExampleObj(int n1, int n2) {
24 this.n1 = n1;
25 this.n2 = n2;
26 }
27 }
28
Alexandre Rames22aa54b2016-10-18 09:32:29 +010029 static int static_variable = 0;
30
xueliang.zhong2a3471f2017-05-08 18:36:40 +010031 public ExampleObj my_obj;
32 public static int number1;
33 public static int number2;
Mingyao Yang1545ccc2017-08-08 15:24:26 -070034 public static volatile int number3;
xueliang.zhong2a3471f2017-05-08 18:36:40 +010035
Alexandre Rames22aa54b2016-10-18 09:32:29 +010036 /// CHECK-START-ARM64: int Main.arrayAccess() scheduler (before)
37 /// CHECK: <<Const1:i\d+>> IntConstant 1
Alexandre Rames22aa54b2016-10-18 09:32:29 +010038 /// CHECK: <<res0:i\d+>> Phi
Tamas Keneza6f5c8c2018-06-20 13:57:04 +020039 /// CHECK: <<i0:i\d+>> Phi
Alexandre Rames22aa54b2016-10-18 09:32:29 +010040 /// 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
Alexandre Rames22aa54b2016-10-18 09:32:29 +010049 /// CHECK: <<res0:i\d+>> Phi
Tamas Keneza6f5c8c2018-06-20 13:57:04 +020050 /// CHECK: <<i0:i\d+>> Phi
Alexandre Rames22aa54b2016-10-18 09:32:29 +010051 /// 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
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
xueliang.zhong2a3471f2017-05-08 18:36:40 +010068 /// 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
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>>]
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
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
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000279 // 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
Artem Serovd1aa7d02018-06-22 11:35:46 +0100295 /// CHECK: <<ArraySet2:v\d+>> ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}] loop:<<Loop>> outer_loop:none
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000296 /// 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
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000305 /// CHECK: <<Addr1:i\d+>> IntermediateAddress [<<NullA>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
Artem Serovd1aa7d02018-06-22 11:35:46 +0100306 /// CHECK: Add [<<ArrayGet1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000307 /// 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
Artem Serovd1aa7d02018-06-22 11:35:46 +0100310 /// CHECK: <<ArraySet2:v\d+>> ArraySet [<<Addr1>>,{{i\d+}},{{i\d+}}] loop:<<Loop>> outer_loop:none
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000311 /// CHECK: Add loop:<<Loop>> outer_loop:none
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.
Evgeny Astigeevich45217372019-04-03 10:46:13 +0100325 // After using LSA to analyze the original references, the scheduler should be able
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000326 // 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
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
xueliang.zhong2a3471f2017-05-08 18:36:40 +0100354 /// 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
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++;
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +0100414 // Note: ClinitCheck(Main) is eliminated because Main initialization is trivial. b/62478025
xueliang.zhong2a3471f2017-05-08 18:36:40 +0100415 number1++;
416 number2++;
417 }
418 }
419
Mingyao Yang1545ccc2017-08-08 15:24:26 -0700420 /// 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
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
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
Alexandre Rames22aa54b2016-10-18 09:32:29 +0100501 /// 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
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
Artem Serov89ff8b22017-11-20 11:51:05 +0000525 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
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
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
Evgeny Astigeevich45217372019-04-03 10:46:13 +0100587 // 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
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.
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.
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
Alexandre Rames22aa54b2016-10-18 09:32:29 +0100701 public static void main(String[] args) {
Artem Serov89ff8b22017-11-20 11:51:05 +0000702 testVecSetScalars();
703 testVecReplicateScalar();
Evgeny Astigeevich45217372019-04-03 10:46:13 +0100704 testCrossItersDependencies();
705 testNoSelfDependantSchedNode(3);
706 testNonPreventingSchedulingCrossItersDeps(3);
Alexandre Rames22aa54b2016-10-18 09:32:29 +0100707 if ((arrayAccess() + intDiv(10)) != -35) {
708 System.out.println("FAIL");
709 }
710 }
711}