< 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 >