< prev index next >

src/hotspot/share/opto/subnode.cpp

Print this page

        

@@ -715,10 +715,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 {

@@ -797,10 +832,18 @@
 //=============================================================================
 //------------------------------sub--------------------------------------------
 // Simplify an CmpP (compare 2 pointers) node, based on local information.
 // If both inputs are constants, compare them.
 const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
+  if (ACmpOnValues != 3 &&
+      (t1->isa_valuetype() || t2->isa_valuetype() ||
+       ((t1->is_valuetypeptr() || t2->is_valuetypeptr()) &&
+        (!t1->maybe_null() || !t2->maybe_null())))) {
+    // One operand is a value type and one operand is never null, fold to constant false
+    return TypeInt::CC_GT;
+  }
+
   const TypePtr *r0 = t1->is_ptr(); // Handy access
   const TypePtr *r1 = t2->is_ptr();
 
   // Undefined inputs makes for an undefined result
   if( TypePtr::above_centerline(r0->_ptr) ||

@@ -934,11 +977,22 @@
 //
 // 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) {
+  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;
+    }
+  }
+
   // 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

@@ -1041,10 +1095,26 @@
   this->set_req(1,ldk2);
 
   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(EnableValhalla && ACmpOnValues == 1, "unexpected perturbed oop");
+    return in(1);
+  }
+  return NULL;
+}
+
 //=============================================================================
 //------------------------------sub--------------------------------------------
 // Simplify an CmpN (compare 2 pointers) node, based on local information.
 // If both inputs are constants, compare them.
 const Type *CmpNNode::sub( const Type *t1, const Type *t2 ) const {
< prev index next >