Skip to content

Commit d9a2213

Browse files
committed
8345299: C2: some nodes can still have incorrect control after do_range_check()
Reviewed-by: chagedorn, kvn
1 parent 2286fae commit d9a2213

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,7 +2463,7 @@ bool PhaseIdealLoop::is_scaled_iv_plus_extra_offset(Node* exp1, Node* offset3, N
24632463

24642464
//------------------------------do_range_check---------------------------------
24652465
// Eliminate range-checks and other trip-counter vs loop-invariant tests.
2466-
void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
2466+
void PhaseIdealLoop::do_range_check(IdealLoopTree* loop) {
24672467
#ifndef PRODUCT
24682468
if (PrintOpto && VerifyLoopOptimizations) {
24692469
tty->print("Range Check Elimination ");
@@ -2526,8 +2526,9 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
25262526
// Range check elimination optimizes out conditions whose parameters are loop invariant in the main loop. They usually
25272527
// have control above the pre loop, but there's no guarantee that they do. There's no guarantee either that the pre
25282528
// loop limit has control that's out of loop (a previous round of range check elimination could have set a limit that's
2529-
// not loop invariant).
2530-
Node* new_limit_ctrl = dominated_node(pre_ctrl, pre_limit_ctrl);
2529+
// not loop invariant). new_limit_ctrl is used for both the pre and main loops. Early control for the main limit may be
2530+
// below the pre loop entry and the pre limit and must be taken into account when initializing new_limit_ctrl.
2531+
Node* new_limit_ctrl = dominated_node(pre_ctrl, pre_limit_ctrl, compute_early_ctrl(main_limit, main_limit_ctrl));
25312532

25322533
// Ensure the original loop limit is available from the
25332534
// pre-loop Opaque1 node.
@@ -2778,8 +2779,10 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
27782779
// new pre_limit can push Bool/Cmp/Opaque nodes down (when one of the eliminated condition has parameters that are not
27792780
// loop invariant in the pre loop.
27802781
set_ctrl(pre_opaq, new_limit_ctrl);
2781-
set_ctrl(pre_end->cmp_node(), new_limit_ctrl);
2782-
set_ctrl(pre_end->in(1), new_limit_ctrl);
2782+
// Can't use new_limit_ctrl for Bool/Cmp because it can be out of loop while they are loop variant. Conservatively set
2783+
// control to latest possible one.
2784+
set_ctrl(pre_end->cmp_node(), pre_end->in(0));
2785+
set_ctrl(pre_end->in(1), pre_end->in(0));
27832786

27842787
_igvn.replace_input_of(pre_opaq, 1, pre_limit);
27852788

@@ -2819,11 +2822,12 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
28192822
// The OpaqueNode is unshared by design
28202823
assert(opqzm->outcnt() == 1, "cannot hack shared node");
28212824
_igvn.replace_input_of(opqzm, 1, main_limit);
2822-
// new main_limit can push Bool/Cmp nodes down (when one of the eliminated condition has parameters that are not loop
2823-
// invariant in the pre loop.
2825+
// new main_limit can push opaque node for zero trip guard down (when one of the eliminated condition has parameters
2826+
// that are not loop invariant in the pre loop).
28242827
set_ctrl(opqzm, new_limit_ctrl);
2825-
set_ctrl(iffm->in(1)->in(1), new_limit_ctrl);
2826-
set_ctrl(iffm->in(1), new_limit_ctrl);
2828+
// Bool/Cmp nodes for zero trip guard should have been assigned control between the main and pre loop (because zero
2829+
// trip guard depends on induction variable value out of pre loop) so shouldn't need to be adjusted
2830+
assert(is_dominator(new_limit_ctrl, get_ctrl(iffm->in(1)->in(1))), "control of cmp should be below control of updated input");
28272831

28282832
C->print_method(PHASE_AFTER_RANGE_CHECK_ELIMINATION, 4, cl);
28292833
}
@@ -3402,7 +3406,7 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n
34023406
// with full checks, but the main-loop with no checks. Remove said checks
34033407
// from the main body.
34043408
if (should_rce) {
3405-
phase->do_range_check(this, old_new);
3409+
phase->do_range_check(this);
34063410
}
34073411

34083412
// Double loop body for unrolling. Adjust the minimum-trip test (will do

src/hotspot/share/opto/loopnode.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ class PhaseIdealLoop : public PhaseTransform {
14161416
}
14171417

14181418
// Eliminate range-checks and other trip-counter vs loop-invariant tests.
1419-
void do_range_check(IdealLoopTree *loop, Node_List &old_new);
1419+
void do_range_check(IdealLoopTree* loop);
14201420

14211421
// Clone loop with an invariant test (that does not exit) and
14221422
// insert a clone of the test that selects which version to

0 commit comments

Comments
 (0)