From a56cd371a2c497e4323756f8b8a08a0bba059bf2 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 3 Mar 2025 09:29:11 +0000 Subject: [PATCH] 8349584: Improve compiler processing Reviewed-by: rhalade, ahgross, epeter, thartmann --- src/hotspot/share/opto/phaseX.cpp | 52 ++++++++++++++++++++++++++++++ src/hotspot/share/opto/phaseX.hpp | 2 ++ src/hotspot/share/opto/subnode.cpp | 8 +++-- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index f3435fa2b61..edddd1797b1 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -2851,6 +2851,7 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No push_and(worklist, parent, use); push_cast_ii(worklist, parent, use); push_opaque_zero_trip_guard(worklist, use); + push_bool_with_cmpu_and_mask(worklist, use); } @@ -2897,6 +2898,57 @@ void PhaseCCP::push_cmpu(Unique_Node_List& worklist, const Node* use) const { } } +// Look for the following shape, which can be optimized by BoolNode::Value_cmpu_and_mask() (i.e. corresponds to case +// (1b): "(m & x) Opcode(); + if (use_op != Op_AndI && (use_op != Op_AddI || use->in(2)->find_int_con(0) != 1)) { + // Not "m & x" or "m + 1" + return; + } + for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { + Node* cmpu = use->fast_out(i); + if (cmpu->Opcode() == Op_CmpU) { + push_bool_matching_case1b(worklist, cmpu); + } + } +} + +// Push any Bool below 'cmpu' that matches case (1b) of BoolNode::Value_cmpu_and_mask(). +void PhaseCCP::push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const { + assert(cmpu->Opcode() == Op_CmpU, "must be"); + for (DUIterator_Fast imax, i = cmpu->fast_outs(imax); i < imax; i++) { + Node* bol = cmpu->fast_out(i); + if (!bol->is_Bool() || bol->as_Bool()->_test._test != BoolTest::lt) { + // Not a Bool with "in(1); + Node* addI = cmpu->in(2); + if (andI->Opcode() != Op_AndI || addI->Opcode() != Op_AddI || addI->in(2)->find_int_con(0) != 1) { + // Not "m & x" and "m + 1" + continue; + } + + Node* m = addI->in(1); + if (m == andI->in(1) || m == andI->in(2)) { + // Is "m" shared? Matched (1b) and thus we revisit Bool. + push_if_not_bottom_type(worklist, bol); + } + } +} + // If n is used in a counted loop exit condition, then the type of the counted loop's Phi depends on the type of 'n'. // Seem PhiNode::Value(). void PhaseCCP::push_counted_loop_phi(Unique_Node_List& worklist, Node* parent, const Node* use) { diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 648e911e783..aeba5e8662d 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -638,6 +638,8 @@ class PhaseCCP : public PhaseIterGVN { void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const; void push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const; + void push_bool_with_cmpu_and_mask(Unique_Node_List& worklist, const Node* use) const; + void push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const; public: PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index cc3c9f3bc96..43461075cff 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1880,7 +1880,7 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { // (1b) "(x & m) in(1); const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int(); - if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) { + if (rhs_m_type != nullptr && (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1)) { // Exclude any case where m == -1 is possible. m = rhs_m; } @@ -1898,12 +1898,16 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { // Simplify a Bool (convert condition codes to boolean (1 or 0)) node, // based on local information. If the input is constant, do it. const Type* BoolNode::Value(PhaseGVN* phase) const { + const Type* input_type = phase->type(in(1)); + if (input_type == Type::TOP) { + return Type::TOP; + } const Type* t = Value_cmpu_and_mask(phase); if (t != nullptr) { return t; } - return _test.cc2logical( phase->type( in(1) ) ); + return _test.cc2logical(input_type); } #ifndef PRODUCT