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