--- old/src/hotspot/share/opto/loopopts.cpp 2020-08-25 09:08:13.348652809 +0200 +++ new/src/hotspot/share/opto/loopopts.cpp 2020-08-25 09:08:13.176738747 +0200 @@ -1411,13 +1411,21 @@ } bool did_break = (i < imax); // Did we break out of the previous loop? if (!did_break && n->outcnt() > 1) { // All uses in outer loops! - Node *late_load_ctrl = NULL; + Node* late_load_ctrl = NULL; + Node* outer_strip_mined_loop_exit = NULL; if (n->is_Load()) { // If n is a load, get and save the result from get_late_ctrl(), // to be later used in calculating the control for n's clones. clear_dom_lca_tags(); late_load_ctrl = get_late_ctrl(n, n_ctrl); + if (n_loop->head()->is_Loop() && n_loop->head()->as_Loop()->is_strip_mined() && !n_loop->head()->is_OuterStripMinedLoop() + && n_loop->tail()->in(0) == late_load_ctrl->in(0)) { + // late_load_ctrl is a loop exit of an inner loop of an outer strip mined loop. + // Use the outer strip mined loop exit instead later if it dominates x_ctrl. + outer_strip_mined_loop_exit = n_loop->_parent->head()->as_OuterStripMinedLoop()->outer_loop_exit(); + } } + // If n is a load, and the late control is the same as the current // control, then the cloning of n is a pointless exercise, because // GVN will ensure that we end up where we started. @@ -1457,10 +1465,17 @@ // to force them to not combine and return back inside the loop // during GVN optimization (4641526). // - // Because we are setting the actual control input, factor in - // the result from get_late_ctrl() so we respect any - // anti-dependences. (6233005). - x_ctrl = dom_lca(late_load_ctrl, x_ctrl); + // Because we are setting the actual control input, factor in the result from get_late_ctrl() so we respect + // any anti-dependences (6233005). If late_load_ctrl is an inner loop exit inside an outer strip mined loop + // whose exit dominates the latest possible placement for x, then use this outer strip mined loop exit + // instead of the inner loop exit (= late_load_ctrl) to move the load completely out of the loop. + // This still respects any anti-dependencies in get_late_ctrl(). + if (outer_strip_mined_loop_exit != NULL && is_dominator(outer_strip_mined_loop_exit, get_late_ctrl(x, late_load_ctrl))) { + assert(dom_lca(outer_strip_mined_loop_exit, x_ctrl) == outer_strip_mined_loop_exit, "must be the same result"); + x_ctrl = outer_strip_mined_loop_exit; + } else { + x_ctrl = dom_lca(late_load_ctrl, x_ctrl); + } // Don't allow the control input to be a CFG splitting node. // Such nodes should only have ProjNodes as outs, e.g. IfNode