--- old/src/share/vm/opto/loopnode.cpp Fri Sep 9 09:42:21 2011 +++ new/src/share/vm/opto/loopnode.cpp Fri Sep 9 09:42:21 2011 @@ -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 ); + _igvn.hash_delete(phi); + phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn ); - nphi->set_req(LoopNode::LoopBackControl, incr); - _igvn.replace_node(phi, nphi); - phi = nphi->as_Phi(); - + // 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);