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