@@ -831,16 +831,53 @@ class Invariance : public StackObj {
831
831
// Returns true if the predicate of iff is in "scale*iv + offset u< load_range(ptr)" format
832
832
// Note: this function is particularly designed for loop predication. We require load_range
833
833
// and offset to be loop invariant computed on the fly by "invar"
834
- bool IdealLoopTree::is_range_check_if (IfNode *iff , PhaseIdealLoop *phase, BasicType bt, Node *iv, Node *&range,
834
+ bool IdealLoopTree::is_range_check_if (IfProjNode* if_success_proj , PhaseIdealLoop *phase, BasicType bt, Node *iv, Node *&range,
835
835
Node *&offset, jlong &scale) const {
836
+ IfNode* iff = if_success_proj->in (0 )->as_If ();
836
837
if (!is_loop_exit (iff)) {
837
838
return false ;
838
839
}
839
840
if (!iff->in (1 )->is_Bool ()) {
840
841
return false ;
841
842
}
842
843
const BoolNode *bol = iff->in (1 )->as_Bool ();
843
- if (bol->_test ._test != BoolTest::lt) {
844
+ if (bol->_test ._test != BoolTest::lt || if_success_proj->is_IfFalse ()) {
845
+ // We don't have the required range check pattern:
846
+ // if (scale*iv + offset <u limit) {
847
+ //
848
+ // } else {
849
+ // trap();
850
+ // }
851
+ //
852
+ // Having the trap on the true projection:
853
+ // if (scale*iv + offset <u limit) {
854
+ // trap();
855
+ // }
856
+ //
857
+ // is not correct. We would need to flip the test to get the expected "trap on false path" pattern:
858
+ // if (scale*iv + offset >=u limit) {
859
+ //
860
+ // } else {
861
+ // trap();
862
+ // }
863
+ //
864
+ // If we create a Hoisted Range Check Predicate for this wrong pattern, it could succeed at runtime (i.e. true
865
+ // for the value of "scale*iv + offset" in the first loop iteration and true for the value of "scale*iv + offset"
866
+ // in the last loop iteration) while the check to be hoisted could fail in other loop iterations.
867
+ //
868
+ // Example:
869
+ // Loop: "for (int i = -1; i < 1000; i++)"
870
+ // init = "scale*iv + offset" in the first loop iteration = 1*-1 + 0 = -1
871
+ // last = "scale*iv + offset" in the last loop iteration = 1*999 + 0 = 999
872
+ // limit = 100
873
+ //
874
+ // Hoisted Range Check Predicate is always true:
875
+ // init >=u limit && last >=u limit <=>
876
+ // -1 >=u 100 && 999 >= u 100
877
+ //
878
+ // But for 0 <= x < 100: x >=u 100 is false.
879
+ // We would wrongly skip the branch with the trap() and possibly miss to execute some other statements inside that
880
+ // trap() branch.
844
881
return false ;
845
882
}
846
883
if (!bol->in (1 )->is_Cmp ()) {
@@ -871,14 +908,14 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, BasicT
871
908
return true ;
872
909
}
873
910
874
- bool IdealLoopTree::is_range_check_if (IfNode *iff , PhaseIdealLoop *phase, Invariance& invar DEBUG_ONLY (COMMA ProjNode *predicate_proj)) const {
911
+ bool IdealLoopTree::is_range_check_if (IfProjNode* if_success_proj , PhaseIdealLoop *phase, Invariance& invar DEBUG_ONLY (COMMA ProjNode *predicate_proj)) const {
875
912
Node* range = nullptr ;
876
913
Node* offset = nullptr ;
877
914
jlong scale = 0 ;
878
915
Node* iv = _head->as_BaseCountedLoop ()->phi ();
879
916
Compile* C = Compile::current ();
880
917
const uint old_unique_idx = C->unique ();
881
- if (!is_range_check_if (iff , phase, T_INT, iv, range, offset, scale)) {
918
+ if (!is_range_check_if (if_success_proj , phase, T_INT, iv, range, offset, scale)) {
882
919
return false ;
883
920
}
884
921
if (!invar.is_invariant (range)) {
@@ -931,10 +968,8 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
931
968
// max(scale*i + offset) = scale*(limit-stride) + offset
932
969
// (2) stride*scale < 0
933
970
// max(scale*i + offset) = scale*init + offset
934
- BoolNode* PhaseIdealLoop::rc_predicate (IdealLoopTree *loop, Node* ctrl,
935
- int scale, Node* offset,
936
- Node* init, Node* limit, jint stride,
937
- Node* range, bool upper, bool &overflow, bool negate) {
971
+ BoolNode* PhaseIdealLoop::rc_predicate (IdealLoopTree* loop, Node* ctrl, int scale, Node* offset, Node* init,
972
+ Node* limit, jint stride, Node* range, bool upper, bool & overflow) {
938
973
jint con_limit = (limit != nullptr && limit->is_Con ()) ? limit->get_int () : 0 ;
939
974
jint con_init = init->is_Con () ? init->get_int () : 0 ;
940
975
jint con_offset = offset->is_Con () ? offset->get_int () : 0 ;
@@ -1060,7 +1095,7 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
1060
1095
cmp = new CmpUNode (max_idx_expr, range);
1061
1096
}
1062
1097
register_new_node (cmp, ctrl);
1063
- BoolNode* bol = new BoolNode (cmp, negate ? BoolTest::ge : BoolTest::lt);
1098
+ BoolNode* bol = new BoolNode (cmp, BoolTest::lt);
1064
1099
register_new_node (bol, ctrl);
1065
1100
1066
1101
if (TraceLoopPredicate) {
@@ -1323,12 +1358,12 @@ void PhaseIdealLoop::loop_predication_follow_branches(Node *n, IdealLoopTree *lo
1323
1358
} while (stack.size () > 0 );
1324
1359
}
1325
1360
1326
- bool PhaseIdealLoop::loop_predication_impl_helper (IdealLoopTree* loop, IfProjNode* if_proj ,
1361
+ bool PhaseIdealLoop::loop_predication_impl_helper (IdealLoopTree* loop, IfProjNode* if_success_proj ,
1327
1362
ParsePredicateSuccessProj* parse_predicate_proj, CountedLoopNode* cl,
1328
1363
ConNode* zero, Invariance& invar, Deoptimization::DeoptReason reason) {
1329
1364
// Following are changed to nonnull when a predicate can be hoisted
1330
1365
IfProjNode* new_predicate_proj = nullptr ;
1331
- IfNode* iff = if_proj ->in (0 )->as_If ();
1366
+ IfNode* iff = if_success_proj ->in (0 )->as_If ();
1332
1367
Node* test = iff->in (1 );
1333
1368
if (!test->is_Bool ()) { // Conv2B, ...
1334
1369
return false ;
@@ -1344,7 +1379,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1344
1379
1345
1380
// Negate test if necessary (Parse Predicates always have IfTrue as success projection and IfFalse as uncommon trap)
1346
1381
bool negated = false ;
1347
- if (if_proj ->is_IfFalse ()) {
1382
+ if (if_success_proj ->is_IfFalse ()) {
1348
1383
new_predicate_bol = new BoolNode (new_predicate_bol->in (1 ), new_predicate_bol->_test .negate ());
1349
1384
register_new_node (new_predicate_bol, ctrl);
1350
1385
negated = true ;
@@ -1361,8 +1396,9 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1361
1396
loop->dump_head ();
1362
1397
}
1363
1398
#endif
1364
- } else if (cl != nullptr && loop->is_range_check_if (iff , this , invar DEBUG_ONLY (COMMA parse_predicate_proj))) {
1399
+ } else if (cl != nullptr && loop->is_range_check_if (if_success_proj , this , invar DEBUG_ONLY (COMMA parse_predicate_proj))) {
1365
1400
// Range check for counted loops
1401
+ assert (if_success_proj->is_IfTrue (), " trap must be on false projection for a range check" );
1366
1402
const Node* cmp = bol->in (1 )->as_Cmp ();
1367
1403
Node* idx = cmp->in (1 );
1368
1404
assert (!invar.is_invariant (idx), " index is variant" );
@@ -1397,33 +1433,31 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1397
1433
}
1398
1434
// If predicate expressions may overflow in the integer range, longs are used.
1399
1435
bool overflow = false ;
1400
- // Negate test if necessary (Parse Predicates always have IfTrue as success projection and IfFalse as uncommon trap)
1401
- const bool negate = (if_proj->is_IfFalse ());
1402
-
1403
1436
// Test the lower bound
1404
- BoolNode* lower_bound_bol = rc_predicate (loop, ctrl, scale, offset, init, limit, stride, rng, false , overflow, negate );
1437
+ BoolNode* lower_bound_bol = rc_predicate (loop, ctrl, scale, offset, init, limit, stride, rng, false , overflow);
1405
1438
1406
1439
const int if_opcode = iff->Opcode ();
1407
1440
IfProjNode* lower_bound_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr , reason, overflow ? Op_If : if_opcode);
1408
1441
IfNode* lower_bound_iff = lower_bound_proj->in (0 )->as_If ();
1409
1442
_igvn.hash_delete (lower_bound_iff);
1410
1443
lower_bound_iff->set_req (1 , lower_bound_bol);
1411
- if (TraceLoopPredicate) tty->print_cr (" lower bound check if: %s %d " , negate ? " negated " : " " , lower_bound_iff->_idx );
1444
+ if (TraceLoopPredicate) tty->print_cr (" lower bound check if: %d " , lower_bound_iff->_idx );
1412
1445
1413
1446
// Test the upper bound
1414
- BoolNode* upper_bound_bol = rc_predicate (loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true , overflow, negate);
1447
+ BoolNode* upper_bound_bol = rc_predicate (loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true ,
1448
+ overflow);
1415
1449
1416
1450
IfProjNode* upper_bound_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr , reason, overflow ? Op_If : if_opcode);
1417
1451
assert (upper_bound_proj->in (0 )->as_If ()->in (0 ) == lower_bound_proj, " should dominate" );
1418
1452
IfNode* upper_bound_iff = upper_bound_proj->in (0 )->as_If ();
1419
1453
_igvn.hash_delete (upper_bound_iff);
1420
1454
upper_bound_iff->set_req (1 , upper_bound_bol);
1421
- if (TraceLoopPredicate) tty->print_cr (" upper bound check if: %s %d " , negate ? " negated " : " " , lower_bound_iff->_idx );
1455
+ if (TraceLoopPredicate) tty->print_cr (" upper bound check if: %d " , lower_bound_iff->_idx );
1422
1456
1423
1457
// Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the
1424
1458
// upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later
1425
1459
// splitting the predicated loop into (unreachable) sub-loops (i.e. done by unrolling, peeling, pre/main/post etc.).
1426
- new_predicate_proj = add_template_assertion_predicate (iff, loop, if_proj , parse_predicate_proj, upper_bound_proj, scale,
1460
+ new_predicate_proj = add_template_assertion_predicate (iff, loop, if_success_proj , parse_predicate_proj, upper_bound_proj, scale,
1427
1461
offset, init, limit, stride, rng, overflow, reason);
1428
1462
1429
1463
#ifndef PRODUCT
@@ -1439,10 +1473,10 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1439
1473
}
1440
1474
assert (new_predicate_proj != nullptr , " sanity" );
1441
1475
// Success - attach condition (new_predicate_bol) to predicate if
1442
- invar.map_ctrl (if_proj , new_predicate_proj); // so that invariance test can be appropriate
1476
+ invar.map_ctrl (if_success_proj , new_predicate_proj); // so that invariance test can be appropriate
1443
1477
1444
1478
// Eliminate the old If in the loop body
1445
- dominated_by (new_predicate_proj, iff, if_proj ->_con != new_predicate_proj->_con );
1479
+ dominated_by (new_predicate_proj, iff, if_success_proj ->_con != new_predicate_proj->_con );
1446
1480
1447
1481
C->set_major_progress ();
1448
1482
return true ;
@@ -1459,7 +1493,8 @@ IfProjNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL
1459
1493
Node* opaque_init = new OpaqueLoopInitNode (C, init);
1460
1494
register_new_node (opaque_init, upper_bound_proj);
1461
1495
bool negate = (if_proj->_con != predicate_proj->_con );
1462
- BoolNode* bol = rc_predicate (loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0 ) != (scale > 0 ), overflow, negate);
1496
+ BoolNode* bol = rc_predicate (loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng,
1497
+ (stride > 0 ) != (scale > 0 ), overflow);
1463
1498
Node* opaque_bol = new Opaque4Node (C, bol, _igvn.intcon (1 )); // This will go away once loop opts are over
1464
1499
C->add_template_assertion_predicate_opaq (opaque_bol);
1465
1500
register_new_node (opaque_bol, upper_bound_proj);
@@ -1481,7 +1516,8 @@ IfProjNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL
1481
1516
max_value = new CastIINode (max_value, loop->_head ->as_CountedLoop ()->phi ()->bottom_type ());
1482
1517
register_new_node (max_value, predicate_proj);
1483
1518
1484
- bol = rc_predicate (loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0 ) != (scale > 0 ), overflow, negate);
1519
+ bol = rc_predicate (loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0 ) != (scale > 0 ),
1520
+ overflow);
1485
1521
opaque_bol = new Opaque4Node (C, bol, _igvn.intcon (1 ));
1486
1522
C->add_template_assertion_predicate_opaq (opaque_bol);
1487
1523
register_new_node (opaque_bol, new_proj);
0 commit comments