179
179
* compiler.predicates.assertion.TestAssertionPredicates Stress
180
180
*/
181
181
182
+ /*
183
+ * @test id=StressXcompMaxUnroll0
184
+ * @key randomness
185
+ * @bug 8288981 8356084
186
+ * @requires vm.compiler2.enabled
187
+ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+AbortVMOnCompilationFailure
188
+ * -XX:LoopMaxUnroll=0 -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode
189
+ * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::*
190
+ * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::*
191
+ * compiler.predicates.assertion.TestAssertionPredicates StressXcompMaxUnroll0
192
+ */
193
+
182
194
/*
183
195
* @test id=NoLoopPredicationXcomp
184
196
* @bug 8288981 8350577
@@ -226,6 +238,7 @@ public class TestAssertionPredicates {
226
238
static boolean flagFalse , flagFalse2 ;
227
239
static int iFld = 34 ;
228
240
static int iFld2 , iFld3 ;
241
+ static int two = 2 ;
229
242
static long lFld , lFldOne = 1 ;
230
243
static float fFld ;
231
244
static short sFld ;
@@ -238,7 +251,7 @@ static class Foo {
238
251
}
239
252
240
253
static Foo foo = new Foo ();
241
-
254
+ static int fooArrSize = 10000001 ;
242
255
243
256
public static void main (String [] args ) {
244
257
switch (args [0 ]) {
@@ -315,14 +328,15 @@ public static void main(String[] args) {
315
328
test8308504No2 ();
316
329
}
317
330
}
318
- case "DataUpdate" -> {
331
+ case "DataUpdate" , "StressXcompMaxUnroll0" -> {
319
332
for (int i = 0 ; i < 10 ; i ++) {
320
333
// The following tests create large arrays. Limit the number of invocations to reduce the time spent.
321
334
flag = !flag ;
322
335
testDataUpdateUnswitchingPeelingUnroll ();
323
336
testDataUpdateUnswitchUnroll ();
324
337
testDataUpdateUnroll ();
325
338
testDataUpdatePeelingUnroll ();
339
+ testPeelingThreeTimesDataUpdate ();
326
340
}
327
341
}
328
342
case "CloneDown" -> {
@@ -1064,18 +1078,18 @@ static void testDataUpdateUnswitchingPeelingUnroll() {
1064
1078
for (int i = 0 ; i < limit ; i ++) {
1065
1079
fooArr [10000000 * i ] = foo ;
1066
1080
}
1067
- // 9 ) This loop is not optimized in any way because we have a call inside the loop. This loop is only required
1081
+ // 10 ) This loop is not optimized in any way because we have a call inside the loop. This loop is only required
1068
1082
// to trigger a crash.
1069
- // 10 ) During GCM with StressGCM, we could schedule the LoadN from the main loop before checking if we should
1083
+ // 11 ) During GCM with StressGCM, we could schedule the LoadN from the main loop before checking if we should
1070
1084
// enter the main loop. When 'flag' is true, we only have an array of size 20000001. We then perform
1071
1085
// the LoadN[3*10000000] and crash when the memory is unmapped.
1072
1086
for (float f = 0 ; f < 1.6f ; f += 0.5f ) {
1073
1087
// 2) Loop is unswitched
1074
- // 3 ) Both loop are peeled (we focus on one of those since both are almost identical except for the
1088
+ // 4 ) Both loop are peeled (we focus on one of those since both are almost identical except for the
1075
1089
// unswitched condition):
1076
1090
// Peeled iteration [i = 0]
1077
1091
// Loop [i = 1..4, stride = 1]
1078
- // 4 ) Loop unroll policy now returns true.
1092
+ // 5 ) Loop unroll policy now returns true.
1079
1093
// Peeled iteration [i = 0]
1080
1094
// - Loop is pre-main-posted
1081
1095
// Loop-pre[i = 1..4, stride = 1]
@@ -1085,16 +1099,16 @@ static void testDataUpdateUnswitchingPeelingUnroll() {
1085
1099
// Loop-pre[i = 1..4, stride = 1]
1086
1100
// Loop-main[i = 2..4, stride = 2]
1087
1101
// Loop-post[i = 2..4, stride = 1]
1088
- // 5 ) During IGVN, we find that the backedge is never taken for main loop (we would over-iteratre) and it
1102
+ // 6 ) During IGVN, we find that the backedge is never taken for main loop (we would over-iteratre) and it
1089
1103
// collapses to a single iteration.
1090
- // 6 ) After loop opts, the pre-loop is removed.
1104
+ // 7 ) After loop opts, the pre-loop is removed.
1091
1105
for (int i = 0 ; i < limit ; i ++) {
1092
1106
// 1) Hoisted with a Hoisted Range Check Predicate
1093
- // 7 ) The 'i = 1' value is propagated to the single main loop iteration and we have the following
1107
+ // 8 ) The 'i = 1' value is propagated to the single main loop iteration and we have the following
1094
1108
// fixed-index accesses:
1095
1109
// LoadN[2*10000000];
1096
1110
// LoadN[3*10000000];
1097
- // 8 ) Without explicitly pinning the LoadN from the main loop at the main loop entry (i.e. below the
1111
+ // 9 ) Without explicitly pinning the LoadN from the main loop at the main loop entry (i.e. below the
1098
1112
// zero trip guard), they are still pinned below the Hoisted Range Check Predicate before the loop.
1099
1113
fooArr [i * 10000000 ].iFld += 34 ;
1100
1114
if (flagFalse ) {
@@ -1327,11 +1341,74 @@ static void testDataUpdatePeelingUnroll() {
1327
1341
}
1328
1342
}
1329
1343
1344
+
1345
+ // -Xcomp -XX:LoopMaxUnroll=0 -XX:+StressGCM -XX:CompileCommand=compileonly,Test*::*
1346
+ private static void testPeelingThreeTimesDataUpdate () {
1347
+ Foo [] fooArr = new Foo [fooArrSize ];
1348
+ for (int i = 0 ; i < two ; i ++) {
1349
+ fooArr [10000000 * i ] = foo ;
1350
+ }
1351
+ int x = 0 ;
1352
+
1353
+ // 2) The Hoisted Range Check Predicate is accompanied by two Template Assertion Predicates. The LoadN node,
1354
+ // previously pinned at the hoisted range check, is now pinned at the Template Assertion Predicate. Note
1355
+ // that the LoadN is still inside the loop body.
1356
+ // 3) The loop is now peeled 3 times which also peels 3 loads from 'fooArr' out of the loop:
1357
+ // // Peeled section from 1st Loop Peeling
1358
+ // ...
1359
+ // LoadN[0]
1360
+ // ...
1361
+ // <loop entry guard>
1362
+ // // Peeled section from 2nd Loop Peeling
1363
+ // ...
1364
+ // LoadN[10000000]
1365
+ // Initialized Assertion Predicate (***)
1366
+ // <loop entry guard>
1367
+ // // Peeled section from 3rd Loop Peeling
1368
+ // ...
1369
+ // LoadN[20000000]
1370
+ // ...
1371
+ // Initialized Assertion Predicate
1372
+ // <loop entry guard>
1373
+ // Template Assertion Predicate
1374
+ // Initialized Assertion Predicate
1375
+ // Loop:
1376
+ // LoadN[i*10000000]
1377
+ //
1378
+ // To avoid that the peeled LoadN nodes float above the corresponding loop entry guards, we need to pin them
1379
+ // below. That is done by updating the dependency of the peeled LoadN to the new Template Assertion Predicate.
1380
+ // This is currently broken: We wrongly set the dependency to the Initialized Assertion Predicate instead of the
1381
+ // Template Assertion Predicate. We can then no longer find the dependency and miss to update it in the next
1382
+ // Loop Peeling application. As a result, all the LoadN pile up at the originally added Initialized Assertion
1383
+ // Predicate of the first Loop Peeling application at (***).
1384
+ //
1385
+ // With GCM, we could schedule LoadN[20000000] at (***), before the loop entry corresponding loop entry guard
1386
+ // for this load. We then crash during runtime because we are accessing an out-of-range index. The fix is to
1387
+ // properly update the data dependencies to the Template Assertion Predicates and not the Initialized Assertion
1388
+ // Predicates.
1389
+ for (int i = 0 ; i < two ; i ++) {
1390
+ // 1) Hoisted with a Hoisted Range Check Predicate
1391
+ x += fooArr [i * 10000000 ].iFld ;
1392
+
1393
+ if (iFld2 == 4 ) {
1394
+ return ;
1395
+ }
1396
+
1397
+ if (i > 0 && iFld2 == 3 ) {
1398
+ iFld2 = 42 ;
1399
+ return ;
1400
+ }
1401
+
1402
+ if (i > 1 && iFld2 == 2 ) {
1403
+ return ;
1404
+ }
1405
+ }
1406
+ }
1407
+
1330
1408
/*
1331
1409
* Tests collected in JBS and duplicated issues
1332
1410
*/
1333
1411
1334
-
1335
1412
// -Xbatch -XX:CompileCommand=compileonly,Test*::*
1336
1413
static void test8305428 () {
1337
1414
int j = 1 ;
0 commit comments