@@ -1710,18 +1710,20 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
17101710 // Rewire control of n to right outside of the loop, regardless if its input(s) are later sunk or not.
17111711 Node* maybe_pinned_n = n;
17121712 Node* outside_ctrl = place_outside_loop (n_ctrl, loop_ctrl);
1713- if (n->depends_only_on_test ()) {
1714- Node* pinned_clone = n->pin_array_access_node ();
1715- if (pinned_clone != nullptr ) {
1716- // Pin array access nodes: if this is an array load, it's going to be dependent on a condition that's not a
1717- // range check for that access. If that condition is replaced by an identical dominating one, then an
1718- // unpinned load would risk floating above its range check.
1719- register_new_node (pinned_clone, n_ctrl);
1720- maybe_pinned_n = pinned_clone;
1721- _igvn.replace_node (n, pinned_clone);
1713+ if (!would_sink_below_pre_loop_exit (loop_ctrl, outside_ctrl)) {
1714+ if (n->depends_only_on_test ()) {
1715+ Node* pinned_clone = n->pin_array_access_node ();
1716+ if (pinned_clone != nullptr ) {
1717+ // Pin array access nodes: if this is an array load, it's going to be dependent on a condition that's not a
1718+ // range check for that access. If that condition is replaced by an identical dominating one, then an
1719+ // unpinned load would risk floating above its range check.
1720+ register_new_node (pinned_clone, n_ctrl);
1721+ maybe_pinned_n = pinned_clone;
1722+ _igvn.replace_node (n, pinned_clone);
1723+ }
17221724 }
1725+ _igvn.replace_input_of (maybe_pinned_n, 0 , outside_ctrl);
17231726 }
1724- _igvn.replace_input_of (maybe_pinned_n, 0 , outside_ctrl);
17251727 }
17261728 }
17271729 if (n_loop != _ltree_root && n->outcnt () > 1 ) {
@@ -1929,6 +1931,21 @@ bool PhaseIdealLoop::ctrl_of_all_uses_out_of_loop(const Node* n, Node* n_ctrl, I
19291931 return true ;
19301932}
19311933
1934+ // Sinking a node from a pre loop to its main loop pins the node between the pre and main loops. If that node is input
1935+ // to a check that's eliminated by range check elimination, it becomes input to an expression that feeds into the exit
1936+ // test of the pre loop above the point in the graph where it's pinned. This results in a broken graph. One way to avoid
1937+ // it would be to not eliminate the check in the main loop. Instead, we prevent sinking of the node here so better code
1938+ // is generated for the main loop.
1939+ bool PhaseIdealLoop::would_sink_below_pre_loop_exit (IdealLoopTree* n_loop, Node* ctrl) {
1940+ if (n_loop->_head ->is_CountedLoop () && n_loop->_head ->as_CountedLoop ()->is_pre_loop ()) {
1941+ CountedLoopNode* pre_loop = n_loop->_head ->as_CountedLoop ();
1942+ if (is_dominator (pre_loop->loopexit (), ctrl)) {
1943+ return true ;
1944+ }
1945+ }
1946+ return false ;
1947+ }
1948+
19321949bool PhaseIdealLoop::ctrl_of_use_out_of_loop (const Node* n, Node* n_ctrl, IdealLoopTree* n_loop, Node* ctrl) {
19331950 if (n->is_Load ()) {
19341951 ctrl = get_late_ctrl_with_anti_dep (n->as_Load (), n_ctrl, ctrl);
@@ -1940,14 +1957,8 @@ bool PhaseIdealLoop::ctrl_of_use_out_of_loop(const Node* n, Node* n_ctrl, IdealL
19401957 if (n_loop->is_member (u_loop)) {
19411958 return false ; // Found use in inner loop
19421959 }
1943- // Sinking a node from a pre loop to its main loop pins the node between the pre and main loops. If that node is input
1944- // to a check that's eliminated by range check elimination, it becomes input to an expression that feeds into the exit
1945- // test of the pre loop above the point in the graph where it's pinned.
1946- if (n_loop->_head ->is_CountedLoop () && n_loop->_head ->as_CountedLoop ()->is_pre_loop ()) {
1947- CountedLoopNode* pre_loop = n_loop->_head ->as_CountedLoop ();
1948- if (is_dominator (pre_loop->loopexit (), ctrl)) {
1949- return false ;
1950- }
1960+ if (would_sink_below_pre_loop_exit (n_loop, ctrl)) {
1961+ return false ;
19511962 }
19521963 return true ;
19531964}
0 commit comments