src/share/vm/opto/loopopts.cpp

Print this page
rev 4533 : 8014811: loopTransform.cpp assert(cmp_end->in(2) == limit) failed
Summary: Stop current iteration of loop opts if partial_peel() failed and it created node clones outside processed loop.
Reviewed-by: roland

*** 1924,1935 **** } //------------------------------ clone_for_use_outside_loop ------------------------------------- // clone "n" for uses that are outside of loop ! void PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) { ! assert(worklist.size() == 0, "should be empty"); for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* use = n->fast_out(j); if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) { worklist.push(use); --- 1924,1935 ---- } //------------------------------ clone_for_use_outside_loop ------------------------------------- // clone "n" for uses that are outside of loop ! int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) { ! int cloned = 0; assert(worklist.size() == 0, "should be empty"); for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* use = n->fast_out(j); if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) { worklist.push(use);
*** 1945,1954 **** --- 1945,1955 ---- assert(j < use->req(), "must be there"); // clone "n" and insert it between the inputs of "n" and the use outside the loop Node* n_clone = n->clone(); _igvn.replace_input_of(use, j, n_clone); + cloned++; Node* use_c; if (!use->is_Phi()) { use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); } else { // Use in a phi is considered a use in the associated predecessor block
*** 1962,1971 **** --- 1963,1973 ---- if (TracePartialPeeling) { tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx); } #endif } + return cloned; } //------------------------------ clone_for_special_use_inside_loop ------------------------------------- // clone "n" for special uses that are in the not_peeled region.
*** 2480,2489 **** --- 2482,2492 ---- } #endif // Evacuate nodes in peel region into the not_peeled region if possible uint new_phi_cnt = 0; + uint cloned_for_outside_use = 0; for (i = 0; i < peel_list.size();) { Node* n = peel_list.at(i); #if !defined(PRODUCT) if (TracePartialPeeling) n->dump(); #endif
*** 2498,2509 **** if ( !has_use_internal_to_set(n, peel, loop) ) { // if not pinned and not a load (which maybe anti-dependent on a store) // and not a CMove (Matcher expects only bool->cmove). if ( n->in(0) == NULL && !n->is_Load() && !n->is_CMove() ) { ! clone_for_use_outside_loop( loop, n, worklist ); ! sink_list.push(n); peel >>= n->_idx; // delete n from peel set. not_peel <<= n->_idx; // add n to not_peel set. peel_list.remove(i); incr = false; --- 2501,2511 ---- if ( !has_use_internal_to_set(n, peel, loop) ) { // if not pinned and not a load (which maybe anti-dependent on a store) // and not a CMove (Matcher expects only bool->cmove). if ( n->in(0) == NULL && !n->is_Load() && !n->is_CMove() ) { ! cloned_for_outside_use += clone_for_use_outside_loop( loop, n, worklist ); sink_list.push(n); peel >>= n->_idx; // delete n from peel set. not_peel <<= n->_idx; // add n to not_peel set. peel_list.remove(i); incr = false;
*** 2536,2545 **** --- 2538,2553 ---- remove_cmpi_loop_exit(new_peel_if, loop); } // Inhibit more partial peeling on this loop assert(!head->is_partial_peel_loop(), "not partial peeled"); head->mark_partial_peel_failed(); + if (cloned_for_outside_use > 0) { + // Terminate this round of loop opts because + // the graph outside this loop was changed. + C->set_major_progress(); + return true; + } return false; } // Step 3: clone loop, retarget control, and insert new phis