From 9862f8f0d351448803f8930333d5a7286e6c3565 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Wed, 17 Dec 2025 13:38:37 +0000 Subject: [PATCH] 8373513: C2: Move ProjNode::other_if_proj() to IfProjNode Reviewed-by: epeter, roland --- src/hotspot/share/opto/cfgnode.cpp | 4 +- src/hotspot/share/opto/cfgnode.hpp | 21 +++++---- src/hotspot/share/opto/ifnode.cpp | 57 +++++++++++++------------ src/hotspot/share/opto/library_call.cpp | 2 +- src/hotspot/share/opto/memnode.cpp | 2 +- src/hotspot/share/opto/multnode.cpp | 7 +-- src/hotspot/share/opto/multnode.hpp | 3 -- src/hotspot/share/opto/predicates.cpp | 4 +- 8 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 776a2d4c90b..ad5adfca8e5 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -933,8 +933,8 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) { } // At this point we know that region->in(idx1) and region->(idx2) map to the same // value and control flow. Now search for ifs that feed into these region inputs. - ProjNode* proj1 = region->in(idx1)->isa_Proj(); - ProjNode* proj2 = region->in(idx2)->isa_Proj(); + IfProjNode* proj1 = region->in(idx1)->isa_IfProj(); + IfProjNode* proj2 = region->in(idx2)->isa_IfProj(); if (proj1 == nullptr || proj1->outcnt() != 1 || proj2 == nullptr || proj2->outcnt() != 1) { return false; // No projection inputs with region as unique user found diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 5f7f4790443..fd40123078a 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -342,15 +342,15 @@ class IfNode : public MultiBranchNode { // Helper methods for fold_compares bool cmpi_folds(PhaseIterGVN* igvn, bool fold_ne = false); bool is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn); - bool has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fail); - bool has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn); - Node* merge_uncommon_traps(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn); + bool has_shared_region(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail) const; + bool has_only_uncommon_traps(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail, PhaseIterGVN* igvn) const; + Node* merge_uncommon_traps(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn); static void improve_address_types(Node* l, Node* r, ProjNode* fail, PhaseIterGVN* igvn); - bool is_cmp_with_loadrange(ProjNode* proj); - bool is_null_check(ProjNode* proj, PhaseIterGVN* igvn); - bool is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn); - void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn); - bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn); + bool is_cmp_with_loadrange(IfProjNode* proj) const; + bool is_null_check(IfProjNode* proj, PhaseIterGVN* igvn) const; + bool is_side_effect_free_test(IfProjNode* proj, PhaseIterGVN* igvn) const; + static void reroute_side_effect_free_unc(IfProjNode* proj, IfProjNode* dom_proj, PhaseIterGVN* igvn); + bool fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn); static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc); protected: @@ -559,6 +559,11 @@ public: IfProjNode(IfNode *ifnode, uint idx) : CProjNode(ifnode,idx) {} virtual Node* Identity(PhaseGVN* phase); + // Return the other IfProj node. + IfProjNode* other_if_proj() const { + return in(0)->as_If()->proj_out(1 - _con)->as_IfProj(); + } + void pin_array_access_nodes(PhaseIterGVN* igvn); protected: diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 763888b65b2..cd8017f9fb3 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -771,7 +771,7 @@ bool IfNode::cmpi_folds(PhaseIterGVN* igvn, bool fold_ne) { // Is a dominating control suitable for folding with this if? bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) { return ctrl != nullptr && - ctrl->is_Proj() && + ctrl->is_IfProj() && ctrl->outcnt() == 1 && // No side-effects ctrl->in(0) != nullptr && ctrl->in(0)->Opcode() == Op_If && @@ -784,8 +784,8 @@ bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) { } // Do this If and the dominating If share a region? -bool IfNode::has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fail) { - ProjNode* otherproj = proj->other_if_proj(); +bool IfNode::has_shared_region(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail) const { + IfProjNode* otherproj = proj->other_if_proj(); Node* otherproj_ctrl_use = otherproj->unique_ctrl_out_or_null(); RegionNode* region = (otherproj_ctrl_use != nullptr && otherproj_ctrl_use->is_Region()) ? otherproj_ctrl_use->as_Region() : nullptr; success = nullptr; @@ -793,13 +793,14 @@ bool IfNode::has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fa if (otherproj->outcnt() == 1 && region != nullptr && !region->has_phi()) { for (int i = 0; i < 2; i++) { - ProjNode* proj = proj_out(i); - if (success == nullptr && proj->outcnt() == 1 && proj->unique_out() == region) { - success = proj; + IfProjNode* next_proj = proj_out(i)->as_IfProj(); + if (success == nullptr && next_proj->outcnt() == 1 && next_proj->unique_out() == region) { + success = next_proj; } else if (fail == nullptr) { - fail = proj; + fail = next_proj; } else { - success = fail = nullptr; + success = nullptr; + fail = nullptr; } } } @@ -850,8 +851,8 @@ ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization:: } // Do this If and the dominating If both branch out to an uncommon trap -bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn) { - ProjNode* otherproj = proj->other_if_proj(); +bool IfNode::has_only_uncommon_traps(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail, PhaseIterGVN* igvn) const { + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(); if (otherproj->outcnt() == 1 && dom_unc != nullptr) { @@ -888,8 +889,8 @@ bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNod !igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_range_check) && // Return true if c2 manages to reconcile with UnstableIf optimization. See the comments for it. igvn->C->remove_unstable_if_trap(dom_unc, true/*yield*/)) { - success = unc_proj; - fail = unc_proj->other_if_proj(); + success = unc_proj->as_IfProj(); + fail = unc_proj->as_IfProj()->other_if_proj(); return true; } } @@ -898,7 +899,7 @@ bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNod } // Check that the 2 CmpI can be folded into as single CmpU and proceed with the folding -bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn) { +bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn) { Node* this_cmp = in(1)->in(1); BoolNode* this_bool = in(1)->as_Bool(); IfNode* dom_iff = proj->in(0)->as_If(); @@ -906,7 +907,7 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f Node* lo = dom_iff->in(1)->in(1)->in(2); Node* hi = this_cmp->in(2); Node* n = this_cmp->in(1); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); const TypeInt* lo_type = IfNode::filtered_int_type(igvn, n, otherproj); const TypeInt* hi_type = IfNode::filtered_int_type(igvn, n, success); @@ -1108,11 +1109,11 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f // Merge the branches that trap for this If and the dominating If into // a single region that branches to the uncommon trap for the // dominating If -Node* IfNode::merge_uncommon_traps(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn) { +Node* IfNode::merge_uncommon_traps(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn) { Node* res = this; assert(success->in(0) == this, "bad projection"); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* unc = success->is_uncommon_trap_proj(); CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(); @@ -1239,7 +1240,7 @@ void IfNode::improve_address_types(Node* l, Node* r, ProjNode* fail, PhaseIterGV #endif } -bool IfNode::is_cmp_with_loadrange(ProjNode* proj) { +bool IfNode::is_cmp_with_loadrange(IfProjNode* proj) const { if (in(1) != nullptr && in(1)->in(1) != nullptr && in(1)->in(1)->in(2) != nullptr) { @@ -1258,7 +1259,7 @@ bool IfNode::is_cmp_with_loadrange(ProjNode* proj) { return false; } -bool IfNode::is_null_check(ProjNode* proj, PhaseIterGVN* igvn) { +bool IfNode::is_null_check(IfProjNode* proj, PhaseIterGVN* igvn) const { Node* other = in(1)->in(1)->in(2); if (other->in(MemNode::Address) != nullptr && proj->in(0)->in(1) != nullptr && @@ -1275,7 +1276,7 @@ bool IfNode::is_null_check(ProjNode* proj, PhaseIterGVN* igvn) { // Check that the If that is in between the 2 integer comparisons has // no side effect -bool IfNode::is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn) { +bool IfNode::is_side_effect_free_test(IfProjNode* proj, PhaseIterGVN* igvn) const { if (proj == nullptr) { return false; } @@ -1315,9 +1316,9 @@ bool IfNode::is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn) { // won't be guarded by the first CmpI anymore. It can trap in cases // where the first CmpI would have prevented it from executing: on a // trap, we need to restart execution at the state of the first CmpI -void IfNode::reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn) { +void IfNode::reroute_side_effect_free_unc(IfProjNode* proj, IfProjNode* dom_proj, PhaseIterGVN* igvn) { CallStaticJavaNode* dom_unc = dom_proj->is_uncommon_trap_if_pattern(); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(); Node* call_proj = dom_unc->unique_ctrl_out(); Node* halt = call_proj->unique_ctrl_out(); @@ -1348,9 +1349,9 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) { if (is_ctrl_folds(ctrl, igvn)) { // A integer comparison immediately dominated by another integer // comparison - ProjNode* success = nullptr; - ProjNode* fail = nullptr; - ProjNode* dom_cmp = ctrl->as_Proj(); + IfProjNode* success = nullptr; + IfProjNode* fail = nullptr; + IfProjNode* dom_cmp = ctrl->as_IfProj(); if (has_shared_region(dom_cmp, success, fail) && // Next call modifies graph so must be last fold_compares_helper(dom_cmp, success, fail, igvn)) { @@ -1364,11 +1365,11 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) { return nullptr; } else if (ctrl->in(0) != nullptr && ctrl->in(0)->in(0) != nullptr) { - ProjNode* success = nullptr; - ProjNode* fail = nullptr; + IfProjNode* success = nullptr; + IfProjNode* fail = nullptr; Node* dom = ctrl->in(0)->in(0); - ProjNode* dom_cmp = dom->isa_Proj(); - ProjNode* other_cmp = ctrl->isa_Proj(); + IfProjNode* dom_cmp = dom->isa_IfProj(); + IfProjNode* other_cmp = ctrl->isa_IfProj(); // Check if it's an integer comparison dominated by another // integer comparison with another test in between diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 2263fa720ce..a057f66a989 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -6171,7 +6171,7 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr) { CallStaticJavaNode* LibraryCallKit::get_uncommon_trap_from_success_proj(Node* node) { if (node->is_IfProj()) { - Node* other_proj = node->as_IfProj()->other_if_proj(); + IfProjNode* other_proj = node->as_IfProj()->other_if_proj(); for (DUIterator_Fast jmax, j = other_proj->fast_outs(jmax); j < jmax; j++) { Node* obs = other_proj->fast_out(j); if (obs->in(0) == other_proj && obs->is_CallStaticJava() && diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 19ff90df5ed..5b76f5b42cf 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -3103,7 +3103,7 @@ MergePrimitiveStores::CFGStatus MergePrimitiveStores::cfg_status_for_pair(const ctrl_use->in(0)->outcnt() != 2) { return CFGStatus::Failure; // Not RangeCheck. } - ProjNode* other_proj = ctrl_use->as_IfProj()->other_if_proj(); + IfProjNode* other_proj = ctrl_use->as_IfProj()->other_if_proj(); Node* trap = other_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check); if (trap != merge_mem->unique_out() || ctrl_use->in(0)->in(0) != ctrl_def) { diff --git a/src/hotspot/share/opto/multnode.cpp b/src/hotspot/share/opto/multnode.cpp index 9409a2f6af3..05867a35268 100644 --- a/src/hotspot/share/opto/multnode.cpp +++ b/src/hotspot/share/opto/multnode.cpp @@ -260,12 +260,7 @@ CallStaticJavaNode* ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptR // Not a projection of an If or variation of a dead If node. return nullptr; } - return other_if_proj()->is_uncommon_trap_proj(reason); -} - -ProjNode* ProjNode::other_if_proj() const { - assert(_con == 0 || _con == 1, "not an if?"); - return in(0)->as_If()->proj_out(1-_con); + return as_IfProj()->other_if_proj()->is_uncommon_trap_proj(reason); } NarrowMemProjNode::NarrowMemProjNode(InitializeNode* src, const TypePtr* adr_type) diff --git a/src/hotspot/share/opto/multnode.hpp b/src/hotspot/share/opto/multnode.hpp index be1351cc5b1..692b69118c9 100644 --- a/src/hotspot/share/opto/multnode.hpp +++ b/src/hotspot/share/opto/multnode.hpp @@ -200,9 +200,6 @@ public: // other_proj->[region->..]call_uct" // null otherwise CallStaticJavaNode* is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason = Deoptimization::Reason_none) const; - - // Return other proj node when this is a If proj node - ProjNode* other_if_proj() const; }; // A ProjNode variant that captures an adr_type(). Used as a projection of InitializeNode to have the right adr_type() diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp index 2489ff563a9..89bc4374ca6 100644 --- a/src/hotspot/share/opto/predicates.cpp +++ b/src/hotspot/share/opto/predicates.cpp @@ -65,7 +65,7 @@ bool AssertionPredicate::has_assertion_predicate_opaque(const Node* predicate_pr // Check if the other projection (UCT projection) of `success_proj` has a Halt node as output. bool AssertionPredicate::has_halt(const IfTrueNode* success_proj) { - ProjNode* other_proj = success_proj->other_if_proj(); + IfProjNode* other_proj = success_proj->other_if_proj(); return other_proj->outcnt() == 1 && other_proj->unique_out()->Opcode() == Op_Halt; } @@ -396,7 +396,7 @@ bool InitializedAssertionPredicate::is_predicate(const Node* maybe_success_proj) #ifdef ASSERT bool InitializedAssertionPredicate::has_halt(const IfTrueNode* success_proj) { - ProjNode* other_proj = success_proj->other_if_proj(); + IfProjNode* other_proj = success_proj->other_if_proj(); if (other_proj->outcnt() != 1) { return false; }