comparison src/share/vm/opto/loopopts.cpp @ 10322:1682bec79205

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
author kvn
date Wed, 22 May 2013 09:02:43 -0700
parents 3b9368710f08
children c9ccd7b85f20
comparison
equal deleted inserted replaced
10319:91eba9f82325 10322:1682bec79205
1937 } 1937 }
1938 1938
1939 1939
1940 //------------------------------ clone_for_use_outside_loop ------------------------------------- 1940 //------------------------------ clone_for_use_outside_loop -------------------------------------
1941 // clone "n" for uses that are outside of loop 1941 // clone "n" for uses that are outside of loop
1942 void PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) { 1942 int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) {
1943 1943 int cloned = 0;
1944 assert(worklist.size() == 0, "should be empty"); 1944 assert(worklist.size() == 0, "should be empty");
1945 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { 1945 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
1946 Node* use = n->fast_out(j); 1946 Node* use = n->fast_out(j);
1947 if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) { 1947 if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) {
1948 worklist.push(use); 1948 worklist.push(use);
1958 assert(j < use->req(), "must be there"); 1958 assert(j < use->req(), "must be there");
1959 1959
1960 // clone "n" and insert it between the inputs of "n" and the use outside the loop 1960 // clone "n" and insert it between the inputs of "n" and the use outside the loop
1961 Node* n_clone = n->clone(); 1961 Node* n_clone = n->clone();
1962 _igvn.replace_input_of(use, j, n_clone); 1962 _igvn.replace_input_of(use, j, n_clone);
1963 cloned++;
1963 Node* use_c; 1964 Node* use_c;
1964 if (!use->is_Phi()) { 1965 if (!use->is_Phi()) {
1965 use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); 1966 use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0);
1966 } else { 1967 } else {
1967 // Use in a phi is considered a use in the associated predecessor block 1968 // Use in a phi is considered a use in the associated predecessor block
1975 if (TracePartialPeeling) { 1976 if (TracePartialPeeling) {
1976 tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx); 1977 tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx);
1977 } 1978 }
1978 #endif 1979 #endif
1979 } 1980 }
1981 return cloned;
1980 } 1982 }
1981 1983
1982 1984
1983 //------------------------------ clone_for_special_use_inside_loop ------------------------------------- 1985 //------------------------------ clone_for_special_use_inside_loop -------------------------------------
1984 // clone "n" for special uses that are in the not_peeled region. 1986 // clone "n" for special uses that are in the not_peeled region.
2493 } 2495 }
2494 #endif 2496 #endif
2495 2497
2496 // Evacuate nodes in peel region into the not_peeled region if possible 2498 // Evacuate nodes in peel region into the not_peeled region if possible
2497 uint new_phi_cnt = 0; 2499 uint new_phi_cnt = 0;
2500 uint cloned_for_outside_use = 0;
2498 for (i = 0; i < peel_list.size();) { 2501 for (i = 0; i < peel_list.size();) {
2499 Node* n = peel_list.at(i); 2502 Node* n = peel_list.at(i);
2500 #if !defined(PRODUCT) 2503 #if !defined(PRODUCT)
2501 if (TracePartialPeeling) n->dump(); 2504 if (TracePartialPeeling) n->dump();
2502 #endif 2505 #endif
2511 if ( !has_use_internal_to_set(n, peel, loop) ) { 2514 if ( !has_use_internal_to_set(n, peel, loop) ) {
2512 2515
2513 // if not pinned and not a load (which maybe anti-dependent on a store) 2516 // if not pinned and not a load (which maybe anti-dependent on a store)
2514 // and not a CMove (Matcher expects only bool->cmove). 2517 // and not a CMove (Matcher expects only bool->cmove).
2515 if ( n->in(0) == NULL && !n->is_Load() && !n->is_CMove() ) { 2518 if ( n->in(0) == NULL && !n->is_Load() && !n->is_CMove() ) {
2516 clone_for_use_outside_loop( loop, n, worklist ); 2519 cloned_for_outside_use += clone_for_use_outside_loop( loop, n, worklist );
2517
2518 sink_list.push(n); 2520 sink_list.push(n);
2519 peel >>= n->_idx; // delete n from peel set. 2521 peel >>= n->_idx; // delete n from peel set.
2520 not_peel <<= n->_idx; // add n to not_peel set. 2522 not_peel <<= n->_idx; // add n to not_peel set.
2521 peel_list.remove(i); 2523 peel_list.remove(i);
2522 incr = false; 2524 incr = false;
2549 remove_cmpi_loop_exit(new_peel_if, loop); 2551 remove_cmpi_loop_exit(new_peel_if, loop);
2550 } 2552 }
2551 // Inhibit more partial peeling on this loop 2553 // Inhibit more partial peeling on this loop
2552 assert(!head->is_partial_peel_loop(), "not partial peeled"); 2554 assert(!head->is_partial_peel_loop(), "not partial peeled");
2553 head->mark_partial_peel_failed(); 2555 head->mark_partial_peel_failed();
2556 if (cloned_for_outside_use > 0) {
2557 // Terminate this round of loop opts because
2558 // the graph outside this loop was changed.
2559 C->set_major_progress();
2560 return true;
2561 }
2554 return false; 2562 return false;
2555 } 2563 }
2556 2564
2557 // Step 3: clone loop, retarget control, and insert new phis 2565 // Step 3: clone loop, retarget control, and insert new phis
2558 2566