changeset 2608:c96c3eb1efae

7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post Summary: Removed predicate cloning from loop peeling optimization and from split fall-in paths. Reviewed-by: never
author kvn
date Fri, 29 Jul 2011 09:16:29 -0700
parents ce3e1d4dc416
children 4aa5974a06dd
files src/share/vm/opto/cfgnode.cpp src/share/vm/opto/ifnode.cpp src/share/vm/opto/loopPredicate.cpp src/share/vm/opto/loopTransform.cpp src/share/vm/opto/loopUnswitch.cpp src/share/vm/opto/loopnode.cpp src/share/vm/opto/loopnode.hpp src/share/vm/opto/phaseX.hpp
diffstat 8 files changed, 33 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/cfgnode.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/cfgnode.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -1349,17 +1349,9 @@
 static void split_once(PhaseIterGVN *igvn, Node *phi, Node *val, Node *n, Node *newn) {
   igvn->hash_delete(n);         // Remove from hash before hacking edges
 
-  Node* predicate_proj = NULL;
   uint j = 1;
   for (uint i = phi->req()-1; i > 0; i--) {
     if (phi->in(i) == val) {   // Found a path with val?
-      if (n->is_Region()) {
-        Node* proj = PhaseIdealLoop::find_predicate(n->in(i));
-        if (proj != NULL) {
-          assert(predicate_proj == NULL, "only one predicate entry expected");
-          predicate_proj = proj;
-        }
-      }
       // Add to NEW Region/Phi, no DU info
       newn->set_req( j++, n->in(i) );
       // Remove from OLD Region/Phi
@@ -1371,11 +1363,6 @@
   // entire Region/Phi conglomerate has been hacked as a single huge transform.
   igvn->register_new_node_with_optimizer( newn );
 
-  // Clone loop predicates
-  if (predicate_proj != NULL) {
-    newn = igvn->clone_loop_predicates(predicate_proj, newn, !n->is_CountedLoop());
-  }
-
   // Now I can point to the new node.
   n->add_req(newn);
   igvn->_worklist.push(n);
@@ -1404,13 +1391,18 @@
 
   Node *val = phi->in(i);       // Constant to split for
   uint hit = 0;                 // Number of times it occurs
+  Node *r = phi->region();
 
   for( ; i < phi->req(); i++ ){ // Count occurrences of constant
     Node *n = phi->in(i);
     if( !n ) return NULL;
     if( phase->type(n) == Type::TOP ) return NULL;
-    if( phi->in(i) == val )
+    if( phi->in(i) == val ) {
       hit++;
+      if (PhaseIdealLoop::find_predicate(r->in(i)) != NULL) {
+        return NULL;            // don't split loop entry path
+      }
+    }
   }
 
   if( hit <= 1 ||               // Make sure we find 2 or more
@@ -1420,7 +1412,6 @@
   // Now start splitting out the flow paths that merge the same value.
   // Split first the RegionNode.
   PhaseIterGVN *igvn = phase->is_IterGVN();
-  Node *r = phi->region();
   RegionNode *newr = new (phase->C, hit+1) RegionNode(hit+1);
   split_once(igvn, phi, val, r, newr);
 
--- a/src/share/vm/opto/ifnode.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/ifnode.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -255,6 +255,14 @@
         predicate_x = predicate_proj;
     }
   }
+  if (predicate_c != NULL && (req_c > 1)) {
+    assert(predicate_x == NULL, "only one predicate entry expected");
+    predicate_c = NULL; // Do not clone predicate below merge point
+  }
+  if (predicate_x != NULL && ((len - req_c) > 2)) {
+    assert(predicate_c == NULL, "only one predicate entry expected");
+    predicate_x = NULL; // Do not clone predicate below merge point
+  }
 
   // Register the new RegionNodes but do not transform them.  Cannot
   // transform until the entire Region/Phi conglomerate has been hacked
--- a/src/share/vm/opto/loopPredicate.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/loopPredicate.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -327,81 +327,20 @@
   return new_predicate_proj;
 }
 
-//--------------------------move_predicate-----------------------
-// Cut predicate from old place and move it to new.
-ProjNode* PhaseIdealLoop::move_predicate(ProjNode* predicate_proj, Node* new_entry,
-                                         Deoptimization::DeoptReason reason,
-                                         PhaseIdealLoop* loop_phase,
-                                         PhaseIterGVN* igvn) {
-  assert(new_entry != NULL, "must be");
-  assert(predicate_proj->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be");
-  IfNode* iff = predicate_proj->in(0)->as_If();
-  Node* old_entry = iff->in(0);
-
-  // Cut predicate from old place.
-  Node* old = predicate_proj;
-  igvn->_worklist.push(old);
-  for (DUIterator_Last imin, i = old->last_outs(imin); i >= imin;) {
-    Node* use = old->last_out(i);  // for each use...
-    igvn->hash_delete(use);
-    igvn->_worklist.push(use);
-    // Update use-def info
-    uint uses_found = 0;
-    for (uint j = 0; j < use->req(); j++) {
-      if (use->in(j) == old) {
-        use->set_req(j, old_entry);
-        uses_found++;
-        if (loop_phase != NULL) {
-          if (use->is_CFG()) {
-            // When called from beautify_loops() idom is not constructed yet.
-            if (loop_phase->_idom != NULL)
-              loop_phase->set_idom(use, old_entry, loop_phase->dom_depth(use));
-          } else {
-            loop_phase->set_ctrl(use, old_entry);
-          }
-        }
-      }
-    }
-    i -= uses_found;    // we deleted 1 or more copies of this edge
-  }
-
-  // Move predicate.
-  igvn->hash_delete(iff);
-  iff->set_req(0, new_entry);
-  igvn->_worklist.push(iff);
-
-  if (loop_phase != NULL) {
-    // Fix up idom and ctrl.
-    loop_phase->set_ctrl(iff->in(1), new_entry);
-    loop_phase->set_ctrl(iff->in(1)->in(1), new_entry);
-    // When called from beautify_loops() idom is not constructed yet.
-    if (loop_phase->_idom != NULL)
-      loop_phase->set_idom(iff, new_entry, loop_phase->dom_depth(iff));
-  }
-
-  return predicate_proj;
-}
 
 //--------------------------clone_loop_predicates-----------------------
 // Interface from IGVN
 Node* PhaseIterGVN::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) {
-  return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, false, clone_limit_check, NULL, this);
-}
-Node* PhaseIterGVN::move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) {
-  return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, true, clone_limit_check, NULL, this);
+  return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, clone_limit_check, NULL, this);
 }
 
 // Interface from PhaseIdealLoop
 Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) {
-  return clone_loop_predicates(old_entry, new_entry, false, clone_limit_check, this, &this->_igvn);
-}
-Node* PhaseIdealLoop::move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) {
-  return clone_loop_predicates(old_entry, new_entry, true, clone_limit_check, this, &this->_igvn);
+  return clone_loop_predicates(old_entry, new_entry, clone_limit_check, this, &this->_igvn);
 }
 
 // Clone loop predicates to cloned loops (peeled, unswitched, split_if).
 Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry,
-                                                bool move_predicates,
                                                 bool clone_limit_check,
                                                 PhaseIdealLoop* loop_phase,
                                                 PhaseIterGVN* igvn) {
@@ -424,20 +363,13 @@
   if (UseLoopPredicate) {
     ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
     if (predicate_proj != NULL) { // right pattern that can be used by loop predication
-      if (move_predicates) {
-        new_entry =  move_predicate(predicate_proj, new_entry,
-                                    Deoptimization::Reason_predicate,
-                                    loop_phase, igvn);
-        assert(new_entry == predicate_proj, "old predicate fall through projection");
-      } else {
-        // clone predicate
-        new_entry = clone_predicate(predicate_proj, new_entry,
-                                    Deoptimization::Reason_predicate,
-                                    loop_phase, igvn);
-        assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate");
-      }
+      // clone predicate
+      new_entry = clone_predicate(predicate_proj, new_entry,
+                                  Deoptimization::Reason_predicate,
+                                  loop_phase, igvn);
+      assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate");
       if (TraceLoopPredicate) {
-        tty->print_cr("Loop Predicate %s: ", move_predicates ? "moved" : "cloned");
+        tty->print("Loop Predicate cloned: ");
         debug_only( new_entry->in(0)->dump(); )
       }
     }
@@ -446,45 +378,18 @@
     // Clone loop limit check last to insert it before loop.
     // Don't clone a limit check which was already finalized
     // for this counted loop (only one limit check is needed).
-    if (move_predicates) {
-      new_entry =  move_predicate(limit_check_proj, new_entry,
-                                  Deoptimization::Reason_loop_limit_check,
-                                  loop_phase, igvn);
-      assert(new_entry == limit_check_proj, "old limit check fall through projection");
-    } else {
-      new_entry = clone_predicate(limit_check_proj, new_entry,
-                                  Deoptimization::Reason_loop_limit_check,
-                                  loop_phase, igvn);
-      assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone limit check");
-    }
+    new_entry = clone_predicate(limit_check_proj, new_entry,
+                                Deoptimization::Reason_loop_limit_check,
+                                loop_phase, igvn);
+    assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone limit check");
     if (TraceLoopLimitCheck) {
-      tty->print_cr("Loop Limit Check %s: ", move_predicates ? "moved" : "cloned");
+      tty->print("Loop Limit Check cloned: ");
       debug_only( new_entry->in(0)->dump(); )
     }
   }
   return new_entry;
 }
 
-//--------------------------eliminate_loop_predicates-----------------------
-void PhaseIdealLoop::eliminate_loop_predicates(Node* entry) {
-  if (LoopLimitCheck) {
-    Node* predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
-    if (predicate != NULL) {
-      entry = entry->in(0)->in(0);
-    }
-  }
-  if (UseLoopPredicate) {
-    ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
-    if (predicate_proj != NULL) { // right pattern that can be used by loop predication
-      Node* n = entry->in(0)->in(1)->in(1);
-      assert(n->Opcode()==Op_Opaque1, "must be");
-      // Remove Opaque1 node from predicates list.
-      // IGVN will remove this predicate check.
-      _igvn.replace_node(n, n->in(1));
-    }
-  }
-}
-
 //--------------------------skip_loop_predicates------------------------------
 // Skip related predicates.
 Node* PhaseIdealLoop::skip_loop_predicates(Node* entry) {
--- a/src/share/vm/opto/loopTransform.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/loopTransform.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -509,14 +509,13 @@
   //         backedges) and then map to the new peeled iteration.  This leaves
   //         the pre-loop with only 1 user (the new peeled iteration), but the
   //         peeled-loop backedge has 2 users.
-  Node* new_exit_value = old_new[head->in(LoopNode::LoopBackControl)->_idx];
-  new_exit_value = move_loop_predicates(entry, new_exit_value, !counted_loop);
+  Node* new_entry = old_new[head->in(LoopNode::LoopBackControl)->_idx];
   _igvn.hash_delete(head);
-  head->set_req(LoopNode::EntryControl, new_exit_value);
+  head->set_req(LoopNode::EntryControl, new_entry);
   for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {
     Node* old = head->fast_out(j);
     if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) {
-      new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
+      Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
       if (!new_exit_value )     // Backedge value is ALSO loop invariant?
         // Then loop body backedge value remains the same.
         new_exit_value = old->in(LoopNode::LoopBackControl);
--- a/src/share/vm/opto/loopUnswitch.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/loopUnswitch.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -255,7 +255,7 @@
   _igvn._worklist.push(head);
 
   // Slow (false) control
-  Node* ifslow_pred = move_loop_predicates(entry, ifslow, !counted_loop);
+  Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop);
   LoopNode* slow_head = old_new[head->_idx]->as_Loop();
   _igvn.hash_delete(slow_head);
   slow_head->set_req(LoopNode::EntryControl, ifslow_pred);
--- a/src/share/vm/opto/loopnode.cpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/loopnode.cpp	Fri Jul 29 09:16:29 2011 -0700
@@ -1167,9 +1167,8 @@
   outer = igvn.register_new_node_with_optimizer(outer, _head);
   phase->set_created_loop_node();
 
-  Node* pred = phase->clone_loop_predicates(ctl, outer, true);
   // Outermost loop falls into '_head' loop
-  _head->set_req(LoopNode::EntryControl, pred);
+  _head->set_req(LoopNode::EntryControl, outer);
   _head->del_req(outer_idx);
   // Split all the Phis up between '_head' loop and 'outer' loop.
   for (DUIterator_Fast jmax, j = _head->fast_outs(jmax); j < jmax; j++) {
--- a/src/share/vm/opto/loopnode.hpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/loopnode.hpp	Fri Jul 29 09:16:29 2011 -0700
@@ -877,19 +877,13 @@
                                    Deoptimization::DeoptReason reason,
                                    PhaseIdealLoop* loop_phase,
                                    PhaseIterGVN* igvn);
-  static ProjNode*  move_predicate(ProjNode* predicate_proj, Node* new_entry,
-                                   Deoptimization::DeoptReason reason,
-                                   PhaseIdealLoop* loop_phase,
-                                   PhaseIterGVN* igvn);
+
   static Node* clone_loop_predicates(Node* old_entry, Node* new_entry,
-                                         bool move_predicates,
                                          bool clone_limit_check,
                                          PhaseIdealLoop* loop_phase,
                                          PhaseIterGVN* igvn);
   Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check);
-  Node*  move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check);
 
-  void eliminate_loop_predicates(Node* entry);
   static Node* skip_loop_predicates(Node* entry);
 
   // Find a good location to insert a predicate
--- a/src/share/vm/opto/phaseX.hpp	Thu Jul 28 13:03:39 2011 -0700
+++ b/src/share/vm/opto/phaseX.hpp	Fri Jul 29 09:16:29 2011 -0700
@@ -473,7 +473,6 @@
 
   // Clone loop predicates. Defined in loopTransform.cpp.
   Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check);
-  Node*  move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check);
   // Create a new if below new_entry for the predicate to be cloned
   ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                         Deoptimization::DeoptReason reason);