8349584: Improve compiler processing

Reviewed-by: rhalade, ahgross, epeter, thartmann
This commit is contained in:
Christian Hagedorn 2025-03-03 09:29:11 +00:00 committed by bchristi
parent d3429ada8f
commit a56cd371a2
3 changed files with 60 additions and 2 deletions

View File

@ -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) <u (m + 1))".
// If any of the inputs on the level (%%) change, we need to revisit Bool because we could have prematurely found that
// the Bool is constant (i.e. case (1b) can be applied) which could become invalid with new type information during CCP.
//
// m x m 1 (%%)
// \ / \ /
// AndI AddI
// \ /
// CmpU
// |
// Bool
//
void PhaseCCP::push_bool_with_cmpu_and_mask(Unique_Node_List& worklist, const Node* use) const {
uint use_op = use->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 "<u"
continue;
}
Node* andI = cmpu->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) {

View File

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

View File

@ -1880,7 +1880,7 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const {
// (1b) "(x & m) <u m + 1" and "(m & x) <u m + 1", cmp2 = m + 1
Node* rhs_m = cmp2->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