< prev index next > src/hotspot/share/opto/subnode.cpp
Print this page
}
}
return NULL; // No change
}
- Node *CmpLNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
+ //------------------------------Ideal------------------------------------------
+ Node* CmpLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* a = NULL;
+ Node* b = NULL;
+ if (is_double_null_check(phase, a, b) && (phase->type(a)->is_zero_type() || phase->type(b)->is_zero_type())) {
+ // Degraded to a simple null check, use old acmp
+ return new CmpPNode(a, b);
+ }
const TypeLong *t2 = phase->type(in(2))->isa_long();
if (Opcode() == Op_CmpL && in(1)->Opcode() == Op_ConvI2L && t2 && t2->is_con()) {
const jlong con = t2->get_con();
if (con >= min_jint && con <= max_jint) {
return new CmpINode(in(1)->in(1), phase->intcon((jint)con));
}
}
return NULL;
}
+ // Match double null check emitted by Compile::optimize_acmp()
+ bool CmpLNode::is_double_null_check(PhaseGVN* phase, Node*& a, Node*& b) const {
+ if (in(1)->Opcode() == Op_OrL &&
+ in(1)->in(1)->Opcode() == Op_CastP2X &&
+ in(1)->in(2)->Opcode() == Op_CastP2X &&
+ in(2)->bottom_type()->is_zero_type()) {
+ assert(EnableValhalla, "unexpected double null check");
+ a = in(1)->in(1)->in(1);
+ b = in(1)->in(2)->in(1);
+ return true;
+ }
+ return false;
+ }
+
+ //------------------------------Value------------------------------------------
+ const Type* CmpLNode::Value(PhaseGVN* phase) const {
+ Node* a = NULL;
+ Node* b = NULL;
+ if (is_double_null_check(phase, a, b) && (!phase->type(a)->maybe_null() || !phase->type(b)->maybe_null())) {
+ // One operand is never NULL, emit constant false
+ return TypeInt::CC_GT;
+ }
+ return SubNode::Value(phase);
+ }
+
//=============================================================================
// Simplify a CmpL (compare 2 longs ) node, based on local information.
// If both inputs are constants, compare them.
const Type *CmpLNode::sub( const Type *t1, const Type *t2 ) const {
const TypeLong *r0 = t1->is_long(); // Handy access
// If klass0's type is PRECISE, then classes are unrelated.
unrelated_classes = xklass0;
} else { // Neither subtypes the other
unrelated_classes = true;
}
+ if (!unrelated_classes) {
+ // Handle inline type arrays
+ if ((r0->flatten_array() && (!r1->can_be_inline_type() || (klass1->is_inlinetype() && !klass1->flatten_array()))) ||
+ (r1->flatten_array() && (!r0->can_be_inline_type() || (klass0->is_inlinetype() && !klass0->flatten_array())))) {
+ // One type is flattened in arrays but the other type is not. Must be unrelated.
+ unrelated_classes = true;
+ }
+ }
if (unrelated_classes) {
// The oops classes are known to be unrelated. If the joined PTRs of
// two oops is not Null and not Bottom, then we are sure that one
// of the two oops is non-null, and the comparison will always fail.
TypePtr::PTR jp = r0->join_ptr(r1->_ptr);
//
// Also check for the case of comparing an unknown klass loaded from the primary
// super-type array vs a known klass with no subtypes. This amounts to
// 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* CmpPNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Normalize comparisons between Java mirrors into comparisons of the low-
// level klass, where a dependent load could be shortened.
//
// The new pattern has a nice effect of matching the same pattern used in the
// fast path of instanceof/checkcast/Class.isInstance(), which allows
< prev index next >