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
@@ -1424,11 +1424,13 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
14241424 _igvn.hash_delete (outer_main_head);
14251425 outer_main_head->set_req (LoopNode::EntryControl, min_taken);
14261426 set_idom (outer_main_head, min_taken, dd_main_head);
1427+ assert (post_head->in (1 )->is_IfProj (), " must be zero-trip guard If node projection of the post loop" );
14271428
14281429 VectorSet visited;
14291430 Node_Stack clones (main_head->back_control ()->outcnt ());
14301431 // Step B3: Make the fall-in values to the main-loop come from the
14311432 // fall-out values of the pre-loop.
1433+ const uint last_node_index_in_pre_loop_body = Compile::current ()->unique () - 1 ;
14321434 for (DUIterator i2 = main_head->outs (); main_head->has_out (i2); i2++) {
14331435 Node* main_phi = main_head->out (i2);
14341436 if (main_phi->is_Phi () && main_phi->in (0 ) == main_head && main_phi->outcnt () > 0 ) {
@@ -1441,21 +1443,13 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
14411443 main_phi->set_req (LoopNode::EntryControl, fallpre);
14421444 }
14431445 }
1446+ DEBUG_ONLY (const uint last_node_index_from_backedge_goo = Compile::current ()->unique () - 1 );
14441447
1445- // Nodes inside the loop may be control dependent on a predicate
1446- // that was moved before the preloop. If the back branch of the main
1447- // or post loops becomes dead, those nodes won't be dependent on the
1448- // test that guards that loop nest anymore which could lead to an
1449- // incorrect array access because it executes independently of the
1450- // test that was guarding the loop nest. We add a special CastII on
1451- // the if branch that enters the loop, between the input induction
1452- // variable value and the induction variable Phi to preserve correct
1453- // dependencies.
1454-
1455- assert (post_head->in (1 )->is_IfProj (), " must be zero-trip guard If node projection of the post loop" );
14561448 DEBUG_ONLY (ensure_zero_trip_guard_proj (outer_main_head->in (LoopNode::EntryControl), true );)
14571449 if (UseLoopPredicate) {
1458- initialize_assertion_predicates_for_main_loop (pre_head, main_head, first_node_index_in_pre_loop_body, old_new);
1450+ initialize_assertion_predicates_for_main_loop (pre_head, main_head, first_node_index_in_pre_loop_body,
1451+ last_node_index_in_pre_loop_body,
1452+ DEBUG_ONLY (last_node_index_from_backedge_goo COMMA) old_new);
14591453 }
14601454
14611455 // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
@@ -1729,10 +1723,15 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(CountedLoop
17291723// Target Loop: Original - main_loop_head
17301724void PhaseIdealLoop::initialize_assertion_predicates_for_main_loop (CountedLoopNode* pre_loop_head,
17311725 CountedLoopNode* main_loop_head,
1732- const uint first_node_index_in_cloned_loop_body,
1726+ const uint first_node_index_in_pre_loop_body,
1727+ const uint last_node_index_in_pre_loop_body,
1728+ DEBUG_ONLY (const uint last_node_index_from_backedge_goo COMMA)
17331729 const Node_List& old_new) {
1734- const NodeInOriginalLoopBody node_in_original_loop_body (first_node_index_in_cloned_loop_body, old_new);
1735- create_assertion_predicates_at_loop (pre_loop_head, main_loop_head, node_in_original_loop_body, true );
1730+ assert (first_node_index_in_pre_loop_body < last_node_index_in_pre_loop_body, " cloned some nodes" );
1731+ const NodeInMainLoopBody node_in_main_loop_body (first_node_index_in_pre_loop_body,
1732+ last_node_index_in_pre_loop_body,
1733+ DEBUG_ONLY (last_node_index_from_backedge_goo COMMA) old_new);
1734+ create_assertion_predicates_at_main_or_post_loop (pre_loop_head, main_loop_head, node_in_main_loop_body, true );
17361735}
17371736
17381737// Source Loop: Original - main_loop_head
@@ -1741,7 +1740,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_post_loop(CountedLoopNo
17411740 CountedLoopNode* post_loop_head,
17421741 const uint first_node_index_in_cloned_loop_body) {
17431742 const NodeInClonedLoopBody node_in_cloned_loop_body (first_node_index_in_cloned_loop_body);
1744- create_assertion_predicates_at_loop (main_loop_head, post_loop_head, node_in_cloned_loop_body, false );
1743+ create_assertion_predicates_at_main_or_post_loop (main_loop_head, post_loop_head, node_in_cloned_loop_body, false );
17451744}
17461745
17471746void PhaseIdealLoop::create_assertion_predicates_at_loop (CountedLoopNode* source_loop_head,
@@ -1754,6 +1753,47 @@ void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source
17541753 PredicateIterator predicate_iterator (source_loop_entry);
17551754 predicate_iterator.for_each (create_assertion_predicates_visitor);
17561755}
1756+
1757+ void PhaseIdealLoop::create_assertion_predicates_at_main_or_post_loop (CountedLoopNode* source_loop_head,
1758+ CountedLoopNode* target_loop_head,
1759+ const NodeInLoopBody& _node_in_loop_body,
1760+ bool clone_template) {
1761+ Node* old_target_loop_head_entry = target_loop_head->skip_strip_mined ()->in (LoopNode::EntryControl);
1762+ const uint node_index_before_new_assertion_predicate_nodes = C->unique ();
1763+ const bool need_to_rewire_old_target_loop_entry_dependencies = old_target_loop_head_entry->outcnt () > 1 ;
1764+ create_assertion_predicates_at_loop (source_loop_head, target_loop_head, _node_in_loop_body, clone_template);
1765+ if (need_to_rewire_old_target_loop_entry_dependencies) {
1766+ rewire_old_target_loop_entry_dependency_to_new_entry (target_loop_head, old_target_loop_head_entry,
1767+ node_index_before_new_assertion_predicate_nodes);
1768+ }
1769+ }
1770+
1771+ // Rewire any control dependent nodes on the old target loop entry before adding Assertion Predicate related nodes.
1772+ // These have been added by PhaseIdealLoop::clone_up_backedge_goo() and assume to be ending up at the target loop entry
1773+ // which is no longer the case when adding additional Assertion Predicates. Fix this by rewiring these nodes to the new
1774+ // target loop entry which corresponds to the tail of the last Assertion Predicate before the target loop. This is safe
1775+ // to do because these control dependent nodes on the old target loop entry created by clone_up_backedge_goo() were
1776+ // pinned on the loop backedge before. The Assertion Predicates are not control dependent on these nodes in any way.
1777+ void PhaseIdealLoop::rewire_old_target_loop_entry_dependency_to_new_entry (
1778+ LoopNode* target_loop_head, const Node* old_target_loop_entry,
1779+ const uint node_index_before_new_assertion_predicate_nodes) {
1780+ Node* new_main_loop_entry = target_loop_head->skip_strip_mined ()->in (LoopNode::EntryControl);
1781+ if (new_main_loop_entry == old_target_loop_entry) {
1782+ // No Assertion Predicates added.
1783+ return ;
1784+ }
1785+
1786+ for (DUIterator_Fast imax, i = old_target_loop_entry->fast_outs (imax); i < imax; i++) {
1787+ Node* out = old_target_loop_entry->fast_out (i);
1788+ if (!out->is_CFG () && out->_idx < node_index_before_new_assertion_predicate_nodes) {
1789+ _igvn.replace_input_of (out, 0 , new_main_loop_entry);
1790+ set_ctrl (out, new_main_loop_entry);
1791+ --i;
1792+ --imax;
1793+ }
1794+ }
1795+ }
1796+
17571797// ------------------------------do_unroll--------------------------------------
17581798// Unroll the loop body one step - make each trip do 2 iterations.
17591799void PhaseIdealLoop::do_unroll (IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
0 commit comments