< prev index next >

src/hotspot/share/opto/loopopts.cpp

Print this page

        

@@ -44,11 +44,11 @@
 #include "utilities/macros.hpp"
 
 //=============================================================================
 //------------------------------split_thru_phi---------------------------------
 // Split Node 'n' through merge point if there is enough win.
-Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
+Node* PhaseIdealLoop::split_thru_phi(Node* n, Node* region, int policy) {
   if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::LONG) {
     // ConvI2L may have type information on it which is unsafe to push up
     // so disable this for now
     return NULL;
   }

@@ -59,45 +59,72 @@
   if (n->Opcode() == Op_CastII && n->as_CastII()->has_range_check() &&
       region->is_CountedLoop() && n->in(1) == region->as_CountedLoop()->phi()) {
     return NULL;
   }
 
+  // Bail out if 'n' is a Div or Mod node whose zero check was removed earlier (i.e. control is NULL) and its divisor is a phi node d_phi whose
+  // inputs could be zero (include zero in their type range). This can only happen if d_phi is an induction variable of a trip-counted (integer)
+  // loop. d_phi could have a more precise type range that does not necessarily include all values of its inputs. Since each of these inputs will
+  // be a divisor of the newly cloned nodes of 'n', we need to bail out of one of these divisors could be zero (zero in its type range).
+  if ((n->Opcode() == Op_DivI || n->Opcode() == Op_ModI) && n->in(0) == NULL
+      && region->is_CountedLoop() && n->in(2) == region->as_CountedLoop()->phi()) {
+    Node* phi = region->as_CountedLoop()->phi();
+    for (uint i = 1; i < phi->req(); i++) {
+      if (_igvn.type(phi->in(i))->filter_speculative(TypeInt::ZERO) != Type::TOP) {
+        // Zero could be a possible value but we already removed the zero check. Bail out to avoid a possible division by zero at a later point.
+        return NULL;
+      }
+    }
+  }
+
+#ifdef ASSERT
+  // A phi only has a more precise type than its inputs if it is an induction variable of a trip-counted integer loop. Verify that this is the
+  // case and we are not about to split a Mod or Div node without zero check that could end up with a new divisor that can be zero.
+  // A split of a division by a floating point zero, on the other hand, is not a problem since the result would just be INFINITY as floating point
+  // representation and does not result in an exception.
+  if ((n->Opcode() == Op_DivI || n->Opcode() == Op_ModI)) {
+    check_divide_by_zero(n, TypeInt::ZERO);
+  } else if ((n->Opcode() == Op_DivL || n->Opcode() == Op_ModL)) {
+    check_divide_by_zero(n, TypeLong::ZERO);
+  }
+#endif
+
   int wins = 0;
   assert(!n->is_CFG(), "");
   assert(region->is_Region(), "");
 
   const Type* type = n->bottom_type();
-  const TypeOopPtr *t_oop = _igvn.type(n)->isa_oopptr();
-  Node *phi;
+  const TypeOopPtr* t_oop = _igvn.type(n)->isa_oopptr();
+  Node* phi;
   if (t_oop != NULL && t_oop->is_known_instance_field()) {
     int iid    = t_oop->instance_id();
     int index  = C->get_alias_index(t_oop);
     int offset = t_oop->offset();
     phi = new PhiNode(region, type, NULL, iid, index, offset);
   } else {
     phi = PhiNode::make_blank(region, n);
   }
   uint old_unique = C->unique();
   for (uint i = 1; i < region->req(); i++) {
-    Node *x;
+    Node* x;
     Node* the_clone = NULL;
     if (region->in(i) == C->top()) {
       x = C->top();             // Dead path?  Use a dead data op
     } else {
       x = n->clone();           // Else clone up the data op
       the_clone = x;            // Remember for possible deletion.
       // Alter data node to use pre-phi inputs
       if (n->in(0) == region)
         x->set_req( 0, region->in(i) );
       for (uint j = 1; j < n->req(); j++) {
-        Node *in = n->in(j);
+        Node* in = n->in(j);
         if (in->is_Phi() && in->in(0) == region)
-          x->set_req( j, in->in(i) ); // Use pre-Phi input for the clone
+          x->set_req(j, in->in(i)); // Use pre-Phi input for the clone
       }
     }
     // Check for a 'win' on some paths
-    const Type *t = x->Value(&_igvn);
+    const Type* t = x->Value(&_igvn);
 
     bool singleton = t->singleton();
 
     // A TOP singleton indicates that there are no possible values incoming
     // along a particular edge. In most cases, this is OK, and the Phi will

@@ -208,10 +235,26 @@
   }
 
   return phi;
 }
 
+#ifdef ASSERT
+void PhaseIdealLoop::check_divide_by_zero(const Node* n, const Type* zero) const {
+  if (n->in(0) == NULL && n->in(2)->is_Phi()) {
+    Node* phi = n->in(2);
+    for (uint i = 1; i < phi->req(); i++) {
+      if (_igvn.type(phi->in(i))->filter_speculative(zero) != Type::TOP) {
+        // Zero could be a possible value
+        n->dump(2);
+        phi->dump(2);
+        assert(false, "should not happen that pre-phi type includes zero as possible value but zero check was already removed");
+      }
+    }
+  }
+}
+#endif
+
 //------------------------------dominated_by------------------------------------
 // Replace the dominated test with an obvious true or false.  Place it on the
 // IGVN worklist for later cleanup.  Move control-dependent data Nodes on the
 // live path up to the dominating control.
 void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exclude_loop_predicate ) {
< prev index next >