8373513: C2: Move ProjNode::other_if_proj() to IfProjNode

Reviewed-by: epeter, roland
This commit is contained in:
Christian Hagedorn 2025-12-17 13:38:37 +00:00
parent 39306d7ab9
commit 9862f8f0d3
8 changed files with 49 additions and 51 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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() &&

View File

@ -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) {

View File

@ -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)

View File

@ -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()

View File

@ -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;
}