changeset 2825:670a74b863fc

7107042: assert(no_dead_loop) failed: dead loop detected Summary: Use dead nodes elimination code in PhaseIdealLoop before executing EA. Reviewed-by: never, twisti
author kvn
date Wed, 09 Nov 2011 07:25:51 -0800
parents 7e0e43cf86d6
children 78bef05801ca
files src/share/vm/compiler/compileBroker.cpp src/share/vm/opto/compile.cpp src/share/vm/opto/loopnode.cpp src/share/vm/opto/loopnode.hpp src/share/vm/opto/loopopts.cpp src/share/vm/opto/matcher.cpp src/share/vm/opto/memnode.cpp src/share/vm/opto/phaseX.cpp src/share/vm/runtime/globals.hpp
diffstat 9 files changed, 57 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/compiler/compileBroker.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -1743,11 +1743,12 @@
 
   collect_statistics(thread, time, task);
 
-  if (PrintCompilation && PrintInlining) {
+  if (PrintCompilation && PrintCompilation2) {
     tty->print("%7d ", (int) tty->time_stamp().milliseconds());  // print timestamp
     tty->print("%4d ", compile_id);    // print compilation number
     tty->print("%s ", (is_osr ? "%" : " "));
-    tty->print_cr("size: %d time: %d inlined: %d bytes", task->code()->total_size(), time.milliseconds(), task->num_inlined_bytecodes());
+    int code_size = (task->code() == NULL) ? 0 : task->code()->total_size();
+    tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, time.milliseconds(), task->num_inlined_bytecodes());
   }
 
   if (compilable == ciEnv::MethodCompilable_never) {
--- a/src/share/vm/opto/compile.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/compile.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -346,15 +346,15 @@
 // Disconnect all useless nodes by disconnecting those at the boundary.
 void Compile::remove_useless_nodes(Unique_Node_List &useful) {
   uint next = 0;
-  while( next < useful.size() ) {
+  while (next < useful.size()) {
     Node *n = useful.at(next++);
     // Use raw traversal of out edges since this code removes out edges
     int max = n->outcnt();
-    for (int j = 0; j < max; ++j ) {
+    for (int j = 0; j < max; ++j) {
       Node* child = n->raw_out(j);
-      if( ! useful.member(child) ) {
-        assert( !child->is_top() || child != top(),
-                "If top is cached in Compile object it is in useful list");
+      if (! useful.member(child)) {
+        assert(!child->is_top() || child != top(),
+               "If top is cached in Compile object it is in useful list");
         // Only need to remove this out-edge to the useless node
         n->raw_del_out(j);
         --j;
@@ -362,7 +362,14 @@
       }
     }
     if (n->outcnt() == 1 && n->has_special_unique_user()) {
-      record_for_igvn( n->unique_out() );
+      record_for_igvn(n->unique_out());
+    }
+  }
+  // Remove useless macro and predicate opaq nodes
+  for (int i = C->macro_count()-1; i >= 0; i--) {
+    Node* n = C->macro_node(i);
+    if (!useful.member(n)) {
+      remove_macro_node(n);
     }
   }
   debug_only(verify_graph_edges(true/*check for no_dead_code*/);)
@@ -719,6 +726,7 @@
       while (_late_inlines.length() > 0) {
         CallGenerator* cg = _late_inlines.pop();
         cg->do_late_inline();
+        if (failing())  return;
       }
     }
     assert(_late_inlines.length() == 0, "should have been processed");
@@ -1691,13 +1699,20 @@
 
   // Perform escape analysis
   if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
+    if (has_loops()) {
+      // Cleanup graph (remove dead nodes).
+      TracePhase t2("idealLoop", &_t_idealLoop, true);
+      PhaseIdealLoop ideal_loop( igvn, false, true );
+      if (major_progress()) print_method("PhaseIdealLoop before EA", 2);
+      if (failing())  return;
+    }
     TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
     ConnectionGraph::do_analysis(this, &igvn);
 
     if (failing())  return;
 
     igvn.optimize();
-    print_method("Iter GVN 3", 2);
+    print_method("Iter GVN after EA", 2);
 
     if (failing())  return;
 
--- a/src/share/vm/opto/loopnode.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/loopnode.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -1883,7 +1883,7 @@
 //----------------------------build_and_optimize-------------------------------
 // Create a PhaseLoop.  Build the ideal Loop tree.  Map each Ideal Node to
 // its corresponding LoopNode.  If 'optimize' is true, do some loop cleanups.
-void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) {
+void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) {
   ResourceMark rm;
 
   int old_progress = C->major_progress();
@@ -2072,6 +2072,16 @@
   }
 #endif
 
+  if (skip_loop_opts) {
+    // Cleanup any modified bits
+    _igvn.optimize();
+
+    if (C->log() != NULL) {
+      log_loop_tree(_ltree_root, _ltree_root, C->log());
+    }
+    return;
+  }
+
   if (ReassociateInvariants) {
     // Reassociate invariants and prep for split_thru_phi
     for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
--- a/src/share/vm/opto/loopnode.hpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/loopnode.hpp	Wed Nov 09 07:25:51 2011 -0800
@@ -747,11 +747,11 @@
     _dom_lca_tags(arena()), // Thread::resource_area
     _verify_me(NULL),
     _verify_only(true) {
-    build_and_optimize(false);
+    build_and_optimize(false, false);
   }
 
   // build the loop tree and perform any requested optimizations
-  void build_and_optimize(bool do_split_if);
+  void build_and_optimize(bool do_split_if, bool skip_loop_opts);
 
 public:
   // Dominators for the sea of nodes
@@ -762,13 +762,13 @@
   Node *dom_lca_internal( Node *n1, Node *n2 ) const;
 
   // Compute the Ideal Node to Loop mapping
-  PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs) :
+  PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool skip_loop_opts = false) :
     PhaseTransform(Ideal_Loop),
     _igvn(igvn),
     _dom_lca_tags(arena()), // Thread::resource_area
     _verify_me(NULL),
     _verify_only(false) {
-    build_and_optimize(do_split_ifs);
+    build_and_optimize(do_split_ifs, skip_loop_opts);
   }
 
   // Verify that verify_me made the same decisions as a fresh run.
@@ -778,7 +778,7 @@
     _dom_lca_tags(arena()), // Thread::resource_area
     _verify_me(verify_me),
     _verify_only(false) {
-    build_and_optimize(false);
+    build_and_optimize(false, false);
   }
 
   // Build and verify the loop tree without modifying the graph.  This
--- a/src/share/vm/opto/loopopts.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/loopopts.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -629,9 +629,10 @@
     if (TraceLoopOpts) {
       tty->print("CMOV  ");
       r_loop->dump_head();
-      if (Verbose)
+      if (Verbose) {
         bol->in(1)->dump(1);
         cmov->dump(1);
+      }
     }
     if (VerifyLoopOptimizations) verify();
 #endif
--- a/src/share/vm/opto/matcher.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/matcher.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -1915,7 +1915,7 @@
         set_dontcare(n);
         break;
       case Op_Jump:
-        mstack.push(n->in(1), Visit);         // Switch Value
+        mstack.push(n->in(1), Pre_Visit);     // Switch Value (could be shared)
         mstack.push(n->in(0), Pre_Visit);     // Visit Control input
         continue;                             // while (mstack.is_nonempty())
       case Op_StrComp:
--- a/src/share/vm/opto/memnode.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/memnode.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -1421,6 +1421,12 @@
     const TypeOopPtr *t_oop = addr_t->isa_oopptr();
     if (can_reshape && opt_mem->is_Phi() &&
         (t_oop != NULL) && t_oop->is_known_instance_field()) {
+      PhaseIterGVN *igvn = phase->is_IterGVN();
+      if (igvn != NULL && igvn->_worklist.member(opt_mem)) {
+        // Delay this transformation until memory Phi is processed.
+        phase->is_IterGVN()->_worklist.push(this);
+        return NULL;
+      }
       // Split instance field load through Phi.
       Node* result = split_through_phi(phase);
       if (result != NULL) return result;
--- a/src/share/vm/opto/phaseX.cpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/opto/phaseX.cpp	Wed Nov 09 07:25:51 2011 -0800
@@ -322,11 +322,12 @@
 void NodeHash::dump() {
   _total_inserts       += _inserts;
   _total_insert_probes += _insert_probes;
-  if( PrintCompilation && PrintOptoStatistics && Verbose && (_inserts > 0) ) { // PrintOptoGVN
-    if( PrintCompilation2 ) {
-      for( uint i=0; i<_max; i++ )
-      if( _table[i] )
-        tty->print("%d/%d/%d ",i,_table[i]->hash()&(_max-1),_table[i]->_idx);
+  if (PrintCompilation && PrintOptoStatistics && Verbose && (_inserts > 0)) {
+    if (WizardMode) {
+      for (uint i=0; i<_max; i++) {
+        if (_table[i])
+          tty->print("%d/%d/%d ",i,_table[i]->hash()&(_max-1),_table[i]->_idx);
+      }
     }
     tty->print("\nGVN Hash stats:  %d grows to %d max_size\n", _grows, _max);
     tty->print("  %d/%d (%8.1f%% full)\n", _inserts, _max, (double)_inserts/_max*100.0);
--- a/src/share/vm/runtime/globals.hpp	Wed Nov 09 06:14:32 2011 -0800
+++ b/src/share/vm/runtime/globals.hpp	Wed Nov 09 07:25:51 2011 -0800
@@ -904,7 +904,7 @@
   product(bool, AlwaysRestoreFPU, false,                                    \
           "Restore the FPU control word after every JNI call (expensive)")  \
                                                                             \
-  notproduct(bool, PrintCompilation2, false,                                \
+  diagnostic(bool, PrintCompilation2, false,                                \
           "Print additional statistics per compilation")                    \
                                                                             \
   diagnostic(bool, PrintAdapterHandlers, false,                             \