< prev index next >

src/hotspot/share/opto/subnode.cpp

Print this page
*** 745,21 ***
      }
    }
    return NULL;                  // No change
  }
  
! Node *CmpLNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
    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;
  }
  
  //=============================================================================
  // 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
--- 745,53 ---
      }
    }
    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);
+   }
    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

*** 914,10 ***
--- 946,18 ---
          // 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);

*** 999,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 ) {
    // 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
--- 1039,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) {
    // 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 >