--- old/src/hotspot/share/opto/subnode.cpp 2018-02-22 16:36:25.756507852 +0100 +++ new/src/hotspot/share/opto/subnode.cpp 2018-02-22 16:36:25.560509122 +0100 @@ -715,6 +715,27 @@ return NULL; // No change } +//------------------------------Ideal------------------------------------------ +Node* CmpLNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (in(1)->Opcode() == Op_OrL && in(1)->in(1)->Opcode() == Op_CastP2X && in(1)->in(2)->Opcode() == Op_CastP2X) { + Node* a = in(1)->in(1)->in(1); + Node* b = in(1)->in(2)->in(1); + const Type* ta = phase->type(a); + const Type* tb = phase->type(b); + if (ta->is_zero_type() || tb->is_zero_type()) { + if (Verbose) tty->print_cr("\n# NULL CHECK (CmpLNode::Ideal)"); + return new CmpPNode(a, b); + } else if (!TypePtr::NULL_PTR->higher_equal(ta) || !TypePtr::NULL_PTR->higher_equal(tb)) { + // One operand is never NULL, emit constant false + if (Verbose) tty->print_cr("\n# CONSTANT FALSE (CmpLNode::Ideal)"); + set_req(1, phase->longcon(0)); + set_req(2, phase->longcon(1)); + return this; + } + } + return NULL; +} + //============================================================================= // Simplify a CmpL (compare 2 longs ) node, based on local information. @@ -932,6 +953,35 @@ // checking to see an unknown klass subtypes a known klass with no subtypes; // this only happens on an exact match. We can shorten this test by 1 load. Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) { + Node* pert = has_perturbed_operand(); + if (pert != NULL) { + // Optimize new acmp + Node* a = pert->in(AddPNode::Base); // unperturbed a + Node* b = in(2); + Node* cmp = phase->C->optimize_acmp(phase, a, b); + if (cmp != NULL) { + return cmp; + } + if ( TypePtr::NULL_PTR->higher_equal(phase->type(a)) && + !TypePtr::NULL_PTR->higher_equal(phase->type(b))) { + // Operand 'b' is never null, swap operands to avoid null check + Node* is_value = phase->C->load_is_value_bit(phase, b); + set_req(1, phase->transform(new AddPNode(b, b, is_value))); + set_req(2, a); + return this; + } + } else { + // Optimize old acmp with value type operands + const TypeInstPtr* ta = phase->type(in(1))->isa_instptr(); + const TypeInstPtr* tb = phase->type(in(2))->isa_instptr(); + if (((ta != NULL && ta->is_loaded() && ta->is_value_based()) || (tb != NULL && tb->is_loaded() && tb->is_value_based())) && + (!TypePtr::NULL_PTR->higher_equal(phase->type(in(1))) || !TypePtr::NULL_PTR->higher_equal(phase->type(in(2))))) { + // One operand is a value type and one operand is never null, fold to constant false + if (Verbose) tty->print_cr("\n# CONSTANT FALSE"); + return new CmpINode(phase->intcon(0), phase->intcon(1)); + } + } + // Normalize comparisons between Java mirrors into comparisons of the low- // level klass, where a dependent load could be shortened. // @@ -1032,6 +1082,22 @@ return this; } +// Checks if one operand is perturbed and returns it +Node* CmpPNode::has_perturbed_operand() const { + // We always perturbe the first operand + AddPNode* addP = in(1)->isa_AddP(); + if (addP != NULL) { + Node* base = addP->in(AddPNode::Base); + if (base->is_top()) { + // RawPtr comparison + return NULL; + } + assert(UseNewAcmp, "unexpected perturbed oop"); + return in(1); + } + return NULL; +} + //============================================================================= //------------------------------sub-------------------------------------------- // Simplify an CmpN (compare 2 pointers) node, based on local information.