Mercurial > hg > truffle
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 |