11/*
2- * Copyright (c) 2000, 2024 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2000, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -1428,11 +1428,13 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
14281428 _igvn.hash_delete (outer_main_head);
14291429 outer_main_head->set_req (LoopNode::EntryControl, min_taken);
14301430 set_idom (outer_main_head, min_taken, dd_main_head);
1431+ assert (post_head->in (1 )->is_IfProj (), " must be zero-trip guard If node projection of the post loop" );
14311432
14321433 VectorSet visited;
14331434 Node_Stack clones (main_head->back_control ()->outcnt ());
14341435 // Step B3: Make the fall-in values to the main-loop come from the
14351436 // fall-out values of the pre-loop.
1437+ const uint last_node_index_in_pre_loop_body = Compile::current ()->unique () - 1 ;
14361438 for (DUIterator i2 = main_head->outs (); main_head->has_out (i2); i2++) {
14371439 Node* main_phi = main_head->out (i2);
14381440 if (main_phi->is_Phi () && main_phi->in (0 ) == main_head && main_phi->outcnt () > 0 ) {
@@ -1445,21 +1447,13 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
14451447 main_phi->set_req (LoopNode::EntryControl, fallpre);
14461448 }
14471449 }
1450+ DEBUG_ONLY (const uint last_node_index_from_backedge_goo = Compile::current ()->unique () - 1 );
14481451
1449- // Nodes inside the loop may be control dependent on a predicate
1450- // that was moved before the preloop. If the back branch of the main
1451- // or post loops becomes dead, those nodes won't be dependent on the
1452- // test that guards that loop nest anymore which could lead to an
1453- // incorrect array access because it executes independently of the
1454- // test that was guarding the loop nest. We add a special CastII on
1455- // the if branch that enters the loop, between the input induction
1456- // variable value and the induction variable Phi to preserve correct
1457- // dependencies.
1458-
1459- assert (post_head->in (1 )->is_IfProj (), " must be zero-trip guard If node projection of the post loop" );
14601452 DEBUG_ONLY (ensure_zero_trip_guard_proj (outer_main_head->in (LoopNode::EntryControl), true );)
14611453 if (UseLoopPredicate) {
1462- initialize_assertion_predicates_for_main_loop (pre_head, main_head, first_node_index_in_pre_loop_body, old_new);
1454+ initialize_assertion_predicates_for_main_loop (pre_head, main_head, first_node_index_in_pre_loop_body,
1455+ last_node_index_in_pre_loop_body,
1456+ DEBUG_ONLY (last_node_index_from_backedge_goo COMMA) old_new);
14631457 }
14641458
14651459 // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
@@ -1734,10 +1728,15 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(CountedLoop
17341728// Target Loop: Original - main_loop_head
17351729void PhaseIdealLoop::initialize_assertion_predicates_for_main_loop (CountedLoopNode* pre_loop_head,
17361730 CountedLoopNode* main_loop_head,
1737- const uint first_node_index_in_cloned_loop_body,
1731+ const uint first_node_index_in_pre_loop_body,
1732+ const uint last_node_index_in_pre_loop_body,
1733+ DEBUG_ONLY (const uint last_node_index_from_backedge_goo COMMA)
17381734 const Node_List& old_new) {
1739- const NodeInOriginalLoopBody node_in_original_loop_body (first_node_index_in_cloned_loop_body, old_new);
1740- create_assertion_predicates_at_loop (pre_loop_head, main_loop_head, node_in_original_loop_body, true );
1735+ assert (first_node_index_in_pre_loop_body < last_node_index_in_pre_loop_body, " cloned some nodes" );
1736+ const NodeInMainLoopBody node_in_main_loop_body (first_node_index_in_pre_loop_body,
1737+ last_node_index_in_pre_loop_body,
1738+ DEBUG_ONLY (last_node_index_from_backedge_goo COMMA) old_new);
1739+ create_assertion_predicates_at_main_or_post_loop (pre_loop_head, main_loop_head, node_in_main_loop_body, true );
17411740}
17421741
17431742// Source Loop: Original - main_loop_head
@@ -1746,7 +1745,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_post_loop(CountedLoopNo
17461745 CountedLoopNode* post_loop_head,
17471746 const uint first_node_index_in_cloned_loop_body) {
17481747 const NodeInClonedLoopBody node_in_cloned_loop_body (first_node_index_in_cloned_loop_body);
1749- create_assertion_predicates_at_loop (main_loop_head, post_loop_head, node_in_cloned_loop_body, false );
1748+ create_assertion_predicates_at_main_or_post_loop (main_loop_head, post_loop_head, node_in_cloned_loop_body, false );
17501749}
17511750
17521751void PhaseIdealLoop::create_assertion_predicates_at_loop (CountedLoopNode* source_loop_head,
@@ -1768,6 +1767,47 @@ void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source
17681767 set_idom (target_outer_loop_head, last_created_predicate_success_proj, dom_depth (target_outer_loop_head));
17691768 }
17701769}
1770+
1771+ void PhaseIdealLoop::create_assertion_predicates_at_main_or_post_loop (CountedLoopNode* source_loop_head,
1772+ CountedLoopNode* target_loop_head,
1773+ const NodeInLoopBody& _node_in_loop_body,
1774+ bool clone_template) {
1775+ Node* old_target_loop_head_entry = target_loop_head->skip_strip_mined ()->in (LoopNode::EntryControl);
1776+ const uint node_index_before_new_assertion_predicate_nodes = C->unique ();
1777+ const bool need_to_rewire_old_target_loop_entry_dependencies = old_target_loop_head_entry->outcnt () > 1 ;
1778+ create_assertion_predicates_at_loop (source_loop_head, target_loop_head, _node_in_loop_body, clone_template);
1779+ if (need_to_rewire_old_target_loop_entry_dependencies) {
1780+ rewire_old_target_loop_entry_dependency_to_new_entry (target_loop_head, old_target_loop_head_entry,
1781+ node_index_before_new_assertion_predicate_nodes);
1782+ }
1783+ }
1784+
1785+ // Rewire any control dependent nodes on the old target loop entry before adding Assertion Predicate related nodes.
1786+ // These have been added by PhaseIdealLoop::clone_up_backedge_goo() and assume to be ending up at the target loop entry
1787+ // which is no longer the case when adding additional Assertion Predicates. Fix this by rewiring these nodes to the new
1788+ // target loop entry which corresponds to the tail of the last Assertion Predicate before the target loop. This is safe
1789+ // to do because these control dependent nodes on the old target loop entry created by clone_up_backedge_goo() were
1790+ // pinned on the loop backedge before. The Assertion Predicates are not control dependent on these nodes in any way.
1791+ void PhaseIdealLoop::rewire_old_target_loop_entry_dependency_to_new_entry (
1792+ LoopNode* target_loop_head, const Node* old_target_loop_entry,
1793+ const uint node_index_before_new_assertion_predicate_nodes) {
1794+ Node* new_main_loop_entry = target_loop_head->skip_strip_mined ()->in (LoopNode::EntryControl);
1795+ if (new_main_loop_entry == old_target_loop_entry) {
1796+ // No Assertion Predicates added.
1797+ return ;
1798+ }
1799+
1800+ for (DUIterator_Fast imax, i = old_target_loop_entry->fast_outs (imax); i < imax; i++) {
1801+ Node* out = old_target_loop_entry->fast_out (i);
1802+ if (!out->is_CFG () && out->_idx < node_index_before_new_assertion_predicate_nodes) {
1803+ _igvn.replace_input_of (out, 0 , new_main_loop_entry);
1804+ set_ctrl (out, new_main_loop_entry);
1805+ --i;
1806+ --imax;
1807+ }
1808+ }
1809+ }
1810+
17711811// ------------------------------do_unroll--------------------------------------
17721812// Unroll the loop body one step - make each trip do 2 iterations.
17731813void PhaseIdealLoop::do_unroll (IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
0 commit comments