hotspot/src/share/vm/opto/loopnode.cpp
changeset 10544 e323817a5fe0
parent 10263 fa58671dde31
child 10988 a3b2bd43ef4f
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Fri Sep 09 12:44:37 2011 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Fri Sep 09 13:47:11 2011 -0700
@@ -582,20 +582,25 @@
 
   // Build a canonical trip test.
   // Clone code, as old values may be in use.
-  Node* nphi = PhiNode::make(x, init_trip, TypeInt::INT);
-  nphi = _igvn.register_new_node_with_optimizer(nphi);
-  set_ctrl(nphi, get_ctrl(phi));
-
   incr = incr->clone();
-  incr->set_req(1,nphi);
+  incr->set_req(1,phi);
   incr->set_req(2,stride);
   incr = _igvn.register_new_node_with_optimizer(incr);
   set_early_ctrl( incr );
-
-  nphi->set_req(LoopNode::LoopBackControl, incr);
-  _igvn.replace_node(phi, nphi);
-  phi = nphi->as_Phi();
-
+  _igvn.hash_delete(phi);
+  phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn );
+
+  // If phi type is more restrictive than Int, raise to
+  // Int to prevent (almost) infinite recursion in igvn
+  // which can only handle integer types for constants or minint..maxint.
+  if (!TypeInt::INT->higher_equal(phi->bottom_type())) {
+    Node* nphi = PhiNode::make(phi->in(0), phi->in(LoopNode::EntryControl), TypeInt::INT);
+    nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl));
+    nphi = _igvn.register_new_node_with_optimizer(nphi);
+    set_ctrl(nphi, get_ctrl(phi));
+    _igvn.replace_node(phi, nphi);
+    phi = nphi->as_Phi();
+  }
   cmp = cmp->clone();
   cmp->set_req(1,incr);
   cmp->set_req(2,limit);
@@ -1618,8 +1623,6 @@
   Node *phi  = cl->phi();
   int stride_con = cl->stride_con();
 
-  PhaseGVN *gvn = &_igvn;
-
   // Visit all children, looking for Phis
   for (DUIterator i = cl->outs(); cl->has_out(i); i++) {
     Node *out = cl->out(i);
@@ -1655,25 +1658,31 @@
     int ratio_con = stride_con2/stride_con;
 
     if ((ratio_con * stride_con) == stride_con2) { // Check for exact
+#ifndef PRODUCT
+      if (TraceLoopOpts) {
+        tty->print("Parallel IV: %d ", phi2->_idx);
+        loop->dump_head();
+      }
+#endif
       // Convert to using the trip counter.  The parallel induction
       // variable differs from the trip counter by a loop-invariant
       // amount, the difference between their respective initial values.
       // It is scaled by the 'ratio_con'.
-      // Perform local Ideal transformation since in most cases ratio == 1.
       Node* ratio = _igvn.intcon(ratio_con);
       set_ctrl(ratio, C->root());
-      Node* hook = new (C, 3) Node(3);
-      Node* ratio_init = gvn->transform(new (C, 3) MulINode(init, ratio));
-      hook->init_req(0, ratio_init);
-      Node* diff = gvn->transform(new (C, 3) SubINode(init2, ratio_init));
-      hook->init_req(1, diff);
-      Node* ratio_idx = gvn->transform(new (C, 3) MulINode(phi, ratio));
-      hook->init_req(2, ratio_idx);
-      Node* add  = gvn->transform(new (C, 3) AddINode(ratio_idx, diff));
-      set_subtree_ctrl(add);
+      Node* ratio_init = new (C, 3) MulINode(init, ratio);
+      _igvn.register_new_node_with_optimizer(ratio_init, init);
+      set_early_ctrl(ratio_init);
+      Node* diff = new (C, 3) SubINode(init2, ratio_init);
+      _igvn.register_new_node_with_optimizer(diff, init2);
+      set_early_ctrl(diff);
+      Node* ratio_idx = new (C, 3) MulINode(phi, ratio);
+      _igvn.register_new_node_with_optimizer(ratio_idx, phi);
+      set_ctrl(ratio_idx, cl);
+      Node* add = new (C, 3) AddINode(ratio_idx, diff);
+      _igvn.register_new_node_with_optimizer(add);
+      set_ctrl(add, cl);
       _igvn.replace_node( phi2, add );
-      // Free up intermediate goo
-      _igvn.remove_dead_node(hook);
       // Sometimes an induction variable is unused
       if (add->outcnt() == 0) {
         _igvn.remove_dead_node(add);