hotspot/src/share/vm/opto/phaseX.cpp
changeset 24015 e54063b2eb53
parent 23528 8f1a7f5e8066
child 24016 2927072ed5fb
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Thu Apr 03 12:37:53 2014 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Mon Apr 14 10:57:07 2014 +0200
@@ -831,154 +831,111 @@
   }
 }
 
+/**
+ * Initialize worklist for each node.
+ */
+void PhaseIterGVN::init_worklist(Node* first) {
+  Unique_Node_List to_process;
+  to_process.push(first);
+
+  while (to_process.size() > 0) {
+    Node* n = to_process.pop();
+    if (!_worklist.member(n)) {
+      _worklist.push(n);
+
+      uint cnt = n->req();
+      for(uint i = 0; i < cnt; i++) {
+        Node* m = n->in(i);
+        if (m != NULL) {
+          to_process.push(m);
+        }
+      }
+    }
+  }
+}
 
 #ifndef PRODUCT
 void PhaseIterGVN::verify_step(Node* n) {
-  _verify_window[_verify_counter % _verify_window_size] = n;
-  ++_verify_counter;
-  ResourceMark rm;
-  ResourceArea *area = Thread::current()->resource_area();
-  VectorSet old_space(area), new_space(area);
-  if (C->unique() < 1000 ||
-      0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) {
-    ++_verify_full_passes;
-    Node::verify_recur(C->root(), -1, old_space, new_space);
-  }
-  const int verify_depth = 4;
-  for ( int i = 0; i < _verify_window_size; i++ ) {
-    Node* n = _verify_window[i];
-    if ( n == NULL )  continue;
-    if( n->in(0) == NodeSentinel ) {  // xform_idom
-      _verify_window[i] = n->in(1);
-      --i; continue;
+  if (VerifyIterativeGVN) {
+    _verify_window[_verify_counter % _verify_window_size] = n;
+    ++_verify_counter;
+    ResourceMark rm;
+    ResourceArea* area = Thread::current()->resource_area();
+    VectorSet old_space(area), new_space(area);
+    if (C->unique() < 1000 ||
+        0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) {
+      ++_verify_full_passes;
+      Node::verify_recur(C->root(), -1, old_space, new_space);
     }
-    // Typical fanout is 1-2, so this call visits about 6 nodes.
-    Node::verify_recur(n, verify_depth, old_space, new_space);
-  }
-}
-#endif
-
-
-//------------------------------init_worklist----------------------------------
-// Initialize worklist for each node.
-void PhaseIterGVN::init_worklist( Node *n ) {
-  if( _worklist.member(n) ) return;
-  _worklist.push(n);
-  uint cnt = n->req();
-  for( uint i =0 ; i < cnt; i++ ) {
-    Node *m = n->in(i);
-    if( m ) init_worklist(m);
+    const int verify_depth = 4;
+    for ( int i = 0; i < _verify_window_size; i++ ) {
+      Node* n = _verify_window[i];
+      if ( n == NULL )  continue;
+      if( n->in(0) == NodeSentinel ) {  // xform_idom
+        _verify_window[i] = n->in(1);
+        --i; continue;
+      }
+      // Typical fanout is 1-2, so this call visits about 6 nodes.
+      Node::verify_recur(n, verify_depth, old_space, new_space);
+    }
   }
 }
 
-//------------------------------optimize---------------------------------------
-void PhaseIterGVN::optimize() {
-  debug_only(uint num_processed  = 0;);
-#ifndef PRODUCT
-  {
-    _verify_counter = 0;
-    _verify_full_passes = 0;
-    for ( int i = 0; i < _verify_window_size; i++ ) {
-      _verify_window[i] = NULL;
+void PhaseIterGVN::trace_PhaseIterGVN(Node* n, Node* nn, const Type* oldtype) {
+  if (TraceIterativeGVN) {
+    uint wlsize = _worklist.size();
+    const Type* newtype = type_or_null(n);
+    if (nn != n) {
+      // print old node
+      tty->print("< ");
+      if (oldtype != newtype && oldtype != NULL) {
+        oldtype->dump();
+      }
+      do { tty->print("\t"); } while (tty->position() < 16);
+      tty->print("<");
+      n->dump();
+    }
+    if (oldtype != newtype || nn != n) {
+      // print new node and/or new type
+      if (oldtype == NULL) {
+        tty->print("* ");
+      } else if (nn != n) {
+        tty->print("> ");
+      } else {
+        tty->print("= ");
+      }
+      if (newtype == NULL) {
+        tty->print("null");
+      } else {
+        newtype->dump();
+      }
+      do { tty->print("\t"); } while (tty->position() < 16);
+      nn->dump();
+    }
+    if (Verbose && wlsize < _worklist.size()) {
+      tty->print("  Push {");
+      while (wlsize != _worklist.size()) {
+        Node* pushed = _worklist.at(wlsize++);
+        tty->print(" %d", pushed->_idx);
+      }
+      tty->print_cr(" }");
+    }
+    if (nn != n) {
+      // ignore n, it might be subsumed
+      verify_step((Node*) NULL);
     }
   }
-#endif
-
-#ifdef ASSERT
-  Node* prev = NULL;
-  uint rep_cnt = 0;
-#endif
-  uint loop_count = 0;
-
-  // Pull from worklist; transform node;
-  // If node has changed: update edge info and put uses on worklist.
-  while( _worklist.size() ) {
-    if (C->check_node_count(NodeLimitFudgeFactor * 2,
-                            "out of nodes optimizing method")) {
-      return;
-    }
-    Node *n  = _worklist.pop();
-    if (++loop_count >= K * C->live_nodes()) {
-      debug_only(n->dump(4);)
-      assert(false, "infinite loop in PhaseIterGVN::optimize");
-      C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize");
-      return;
-    }
-#ifdef ASSERT
-    if (n == prev) {
-      if (++rep_cnt > 3) {
-        n->dump(4);
-        assert(false, "loop in Ideal transformation");
-      }
-    } else {
-      rep_cnt = 0;
-    }
-    prev = n;
-#endif
-    if (TraceIterativeGVN && Verbose) {
-      tty->print("  Pop ");
-      NOT_PRODUCT( n->dump(); )
-      debug_only(if( (num_processed++ % 100) == 0 ) _worklist.print_set();)
-    }
-
-    if (n->outcnt() != 0) {
-
-#ifndef PRODUCT
-      uint wlsize = _worklist.size();
-      const Type* oldtype = type_or_null(n);
-#endif //PRODUCT
-
-      Node *nn = transform_old(n);
+}
 
-#ifndef PRODUCT
-      if (TraceIterativeGVN) {
-        const Type* newtype = type_or_null(n);
-        if (nn != n) {
-          // print old node
-          tty->print("< ");
-          if (oldtype != newtype && oldtype != NULL) {
-            oldtype->dump();
-          }
-          do { tty->print("\t"); } while (tty->position() < 16);
-          tty->print("<");
-          n->dump();
-        }
-        if (oldtype != newtype || nn != n) {
-          // print new node and/or new type
-          if (oldtype == NULL) {
-            tty->print("* ");
-          } else if (nn != n) {
-            tty->print("> ");
-          } else {
-            tty->print("= ");
-          }
-          if (newtype == NULL) {
-            tty->print("null");
-          } else {
-            newtype->dump();
-          }
-          do { tty->print("\t"); } while (tty->position() < 16);
-          nn->dump();
-        }
-        if (Verbose && wlsize < _worklist.size()) {
-          tty->print("  Push {");
-          while (wlsize != _worklist.size()) {
-            Node* pushed = _worklist.at(wlsize++);
-            tty->print(" %d", pushed->_idx);
-          }
-          tty->print_cr(" }");
-        }
-      }
-      if( VerifyIterativeGVN && nn != n ) {
-        verify_step((Node*) NULL);  // ignore n, it might be subsumed
-      }
-#endif
-    } else if (!n->is_top()) {
-      remove_dead_node(n);
-    }
+void PhaseIterGVN::init_verifyPhaseIterGVN() {
+  _verify_counter = 0;
+  _verify_full_passes = 0;
+  for (int i = 0; i < _verify_window_size; i++) {
+    _verify_window[i] = NULL;
   }
+}
 
-#ifndef PRODUCT
+void PhaseIterGVN::verify_PhaseIterGVN() {
   C->verify_graph_edges();
   if( VerifyOpto && allow_progress() ) {
     // Must turn off allow_progress to enable assert and break recursion
@@ -998,21 +955,78 @@
       igvn2.set_allow_progress(true);
     }
   }
-  if ( VerifyIterativeGVN && PrintOpto ) {
-    if ( _verify_counter == _verify_full_passes )
+  if (VerifyIterativeGVN && PrintOpto) {
+    if (_verify_counter == _verify_full_passes) {
       tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes",
                     _verify_full_passes);
-    else
+    } else {
       tty->print_cr("VerifyIterativeGVN: %d transforms, %d full verify passes",
                   _verify_counter, _verify_full_passes);
+    }
   }
-#endif
+}
+#endif /* PRODUCT */
+
+#ifdef ASSERT
+/**
+ * Dumps information that can help to debug the problem. A debug
+ * build fails with an assert.
+ */
+void PhaseIterGVN::dump_infinite_loop_info(Node* n) {
+  n->dump(4);
+  _worklist.dump();
+  assert(false, "infinite loop in PhaseIterGVN::optimize");
+}
+
+/**
+ * Prints out information about IGVN if the 'verbose' option is used.
+ */
+void PhaseIterGVN::trace_PhaseIterGVN_verbose(Node* n, int num_processed) {
+  if (TraceIterativeGVN && Verbose) {
+    tty->print("  Pop ");
+    n->dump();
+    if ((num_processed % 100) == 0) {
+      _worklist.print_set();
+    }
+  }
+}
+#endif /* ASSERT */
+
+void PhaseIterGVN::optimize() {
+  DEBUG_ONLY(uint num_processed  = 0;)
+  NOT_PRODUCT(init_verifyPhaseIterGVN();)
+
+  uint loop_count = 0;
+  // Pull from worklist and transform the node. If the node has changed,
+  // update edge info and put uses on worklist.
+  while(_worklist.size()) {
+    if (C->check_node_count(NodeLimitFudgeFactor * 2, "Out of nodes")) {
+      return;
+    }
+    Node* n  = _worklist.pop();
+    if (++loop_count >= K * C->live_nodes()) {
+      DEBUG_ONLY(dump_infinite_loop_info(n);)
+      C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize");
+      return;
+    }
+    DEBUG_ONLY(trace_PhaseIterGVN_verbose(n, num_processed++);)
+    if (n->outcnt() != 0) {
+      NOT_PRODUCT(const Type* oldtype = type_or_null(n));
+      // Do the transformation
+      Node* nn = transform_old(n);
+      NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);)
+    } else if (!n->is_top()) {
+      remove_dead_node(n);
+    }
+  }
+  NOT_PRODUCT(verify_PhaseIterGVN();)
 }
 
 
-//------------------register_new_node_with_optimizer---------------------------
-// Register a new node with the optimizer.  Update the types array, the def-use
-// info.  Put on worklist.
+/**
+ * Register a new node with the optimizer.  Update the types array, the def-use
+ * info.  Put on worklist.
+ */
 Node* PhaseIterGVN::register_new_node_with_optimizer(Node* n, Node* orig) {
   set_type_bottom(n);
   _worklist.push(n);
@@ -1038,32 +1052,29 @@
   return transform_old(n);
 }
 
-//------------------------------transform_old----------------------------------
-Node *PhaseIterGVN::transform_old( Node *n ) {
-#ifndef PRODUCT
-  debug_only(uint loop_count = 0;);
-  set_transforms();
-#endif
+Node *PhaseIterGVN::transform_old(Node* n) {
+  DEBUG_ONLY(uint loop_count = 0;);
+  NOT_PRODUCT(set_transforms());
+
   // Remove 'n' from hash table in case it gets modified
   _table.hash_delete(n);
-  if( VerifyIterativeGVN ) {
-   assert( !_table.find_index(n->_idx), "found duplicate entry in table");
+  if (VerifyIterativeGVN) {
+   assert(!_table.find_index(n->_idx), "found duplicate entry in table");
   }
 
   // Apply the Ideal call in a loop until it no longer applies
-  Node *k = n;
+  Node* k = n;
   DEBUG_ONLY(dead_loop_check(k);)
   DEBUG_ONLY(bool is_new = (k->outcnt() == 0);)
-  Node *i = k->Ideal(this, /*can_reshape=*/true);
+  Node* i = k->Ideal(this, /*can_reshape=*/true);
   assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes");
 #ifndef PRODUCT
-  if( VerifyIterativeGVN )
-    verify_step(k);
-  if( i && VerifyOpto ) {
-    if( !allow_progress() ) {
-      if (i->is_Add() && i->outcnt() == 1) {
+  verify_step(k);
+  if (i && VerifyOpto ) {
+    if (!allow_progress()) {
+      if (i->is_Add() && (i->outcnt() == 1)) {
         // Switched input to left side because this is the only use
-      } else if( i->is_If() && (i->in(0) == NULL) ) {
+      } else if (i->is_If() && (i->in(0) == NULL)) {
         // This IF is dead because it is dominated by an equivalent IF When
         // dominating if changed, info is not propagated sparsely to 'this'
         // Propagating this info further will spuriously identify other
@@ -1071,35 +1082,38 @@
         return i;
       } else
         set_progress();
-    } else
+    } else {
       set_progress();
+    }
   }
 #endif
 
-  while( i ) {
+  while (i != NULL) {
 #ifndef PRODUCT
-    debug_only( if( loop_count >= K ) i->dump(4); )
-    assert(loop_count < K, "infinite loop in PhaseIterGVN::transform");
-    debug_only( loop_count++; )
+    if (loop_count >= K) {
+      dump_infinite_loop_info(i);
+    }
+    loop_count++;
 #endif
     assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes");
     // Made a change; put users of original Node on worklist
-    add_users_to_worklist( k );
+    add_users_to_worklist(k);
     // Replacing root of transform tree?
-    if( k != i ) {
+    if (k != i) {
       // Make users of old Node now use new.
-      subsume_node( k, i );
+      subsume_node(k, i);
       k = i;
     }
     DEBUG_ONLY(dead_loop_check(k);)
     // Try idealizing again
     DEBUG_ONLY(is_new = (k->outcnt() == 0);)
     i = k->Ideal(this, /*can_reshape=*/true);
-    assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes");
+    assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes");
 #ifndef PRODUCT
-    if( VerifyIterativeGVN )
-      verify_step(k);
-    if( i && VerifyOpto ) set_progress();
+    verify_step(k);
+    if (i && VerifyOpto) {
+      set_progress();
+    }
 #endif
   }
 
@@ -1107,48 +1121,49 @@
   ensure_type_or_null(k);
 
   // See what kind of values 'k' takes on at runtime
-  const Type *t = k->Value(this);
+  const Type* t = k->Value(this);
   assert(t != NULL, "value sanity");
 
   // Since I just called 'Value' to compute the set of run-time values
   // for this Node, and 'Value' is non-local (and therefore expensive) I'll
   // cache Value.  Later requests for the local phase->type of this Node can
   // use the cached Value instead of suffering with 'bottom_type'.
-  if (t != type_or_null(k)) {
-    NOT_PRODUCT( set_progress(); )
-    NOT_PRODUCT( inc_new_values();)
+  if (type_or_null(k) != t) {
+#ifndef PRODUCT
+    inc_new_values();
+    set_progress();
+#endif
     set_type(k, t);
     // If k is a TypeNode, capture any more-precise type permanently into Node
     k->raise_bottom_type(t);
     // Move users of node to worklist
-    add_users_to_worklist( k );
+    add_users_to_worklist(k);
   }
-
   // If 'k' computes a constant, replace it with a constant
-  if( t->singleton() && !k->is_Con() ) {
-    NOT_PRODUCT( set_progress(); )
-    Node *con = makecon(t);     // Make a constant
-    add_users_to_worklist( k );
-    subsume_node( k, con );     // Everybody using k now uses con
+  if (t->singleton() && !k->is_Con()) {
+    NOT_PRODUCT(set_progress();)
+    Node* con = makecon(t);     // Make a constant
+    add_users_to_worklist(k);
+    subsume_node(k, con);       // Everybody using k now uses con
     return con;
   }
 
   // Now check for Identities
-  i = k->Identity(this);        // Look for a nearby replacement
-  if( i != k ) {                // Found? Return replacement!
-    NOT_PRODUCT( set_progress(); )
-    add_users_to_worklist( k );
-    subsume_node( k, i );       // Everybody using k now uses i
+  i = k->Identity(this);      // Look for a nearby replacement
+  if (i != k) {                // Found? Return replacement!
+    NOT_PRODUCT(set_progress();)
+    add_users_to_worklist(k);
+    subsume_node(k, i);       // Everybody using k now uses i
     return i;
   }
 
   // Global Value Numbering
   i = hash_find_insert(k);      // Check for pre-existing node
-  if( i && (i != k) ) {
+  if (i && (i != k)) {
     // Return the pre-existing node if it isn't dead
-    NOT_PRODUCT( set_progress(); )
-    add_users_to_worklist( k );
-    subsume_node( k, i );       // Everybody using k now uses i
+    NOT_PRODUCT(set_progress();)
+    add_users_to_worklist(k);
+    subsume_node(k, i);       // Everybody using k now uses i
     return i;
   }