< prev index next >

src/hotspot/share/opto/subnode.cpp

Print this page

        

@@ -721,10 +721,45 @@
     }
   }
   return NULL;                  // No change
 }
 
+//------------------------------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);
+  }
+  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 {

@@ -940,11 +975,11 @@
 //
 // 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

@@ -1018,10 +1053,20 @@
 
   // Verify that we understand the situation
   if (con2 != (intptr_t) superklass->super_check_offset())
     return NULL;                // Might be element-klass loading from array klass
 
+  // Do not fold the subtype check to an array klass pointer comparison for [V? arrays.
+  // [V is a subtype of [V? but the klass for [V is not equal to the klass for [V?. Perform a full test.
+  if (superklass->is_obj_array_klass()) {
+    ciObjArrayKlass* ak = superklass->as_obj_array_klass();
+    if (!ak->storage_properties().is_null_free() && ak->element_klass()->is_valuetype()) {
+      // Do not bypass the klass load from the primary supertype array
+      return NULL;
+    }
+  }
+
   // If 'superklass' has no subklasses and is not an interface, then we are
   // assured that the only input which will pass the type check is
   // 'superklass' itself.
   //
   // We could be more liberal here, and allow the optimization on interfaces
< prev index next >