< prev index next >
src/hotspot/share/opto/loopTransform.cpp
Print this page
*** 65,74 ****
--- 65,87 ----
void IdealLoopTree::record_for_igvn() {
for( uint i = 0; i < _body.size(); i++ ) {
Node *n = _body.at(i);
_phase->_igvn._worklist.push(n);
}
+ // put body of outer strip mined loop on igvn work list as well
+ if (_head->is_CountedLoop() && _head->as_Loop()->is_strip_mined()) {
+ CountedLoopNode* l = _head->as_CountedLoop();
+ _phase->_igvn._worklist.push(l->outer_loop());
+ _phase->_igvn._worklist.push(l->outer_loop_tail());
+ _phase->_igvn._worklist.push(l->outer_loop_end());
+ _phase->_igvn._worklist.push(l->outer_safepoint());
+ _phase->_igvn._worklist.push(l->outer_bol());
+ _phase->_igvn._worklist.push(l->outer_cmp());
+ _phase->_igvn._worklist.push(l->outer_opaq());
+ Node* cle_out = _head->as_CountedLoop()->loopexit()->proj_out(false);
+ _phase->_igvn._worklist.push(cle_out);
+ }
}
//------------------------------compute_exact_trip_count-----------------------
// Compute loop trip count if possible. Do not recalculate trip count for
// split loops (pre-main-post) which have their limits and inits behind Opaque node.
*** 492,502 ****
if (TraceLoopOpts) {
tty->print("Peel ");
loop->dump_head();
}
#endif
! Node* head = loop->_head;
bool counted_loop = head->is_CountedLoop();
if (counted_loop) {
CountedLoopNode *cl = head->as_CountedLoop();
assert(cl->trip_count() > 0, "peeling a fully unrolled loop");
cl->set_trip_count(cl->trip_count() - 1);
--- 505,515 ----
if (TraceLoopOpts) {
tty->print("Peel ");
loop->dump_head();
}
#endif
! LoopNode* head = loop->_head->as_Loop();
bool counted_loop = head->is_CountedLoop();
if (counted_loop) {
CountedLoopNode *cl = head->as_CountedLoop();
assert(cl->trip_count() > 0, "peeling a fully unrolled loop");
cl->set_trip_count(cl->trip_count() - 1);
*** 512,532 ****
}
Node* entry = head->in(LoopNode::EntryControl);
// Step 1: Clone the loop body. The clone becomes the peeled iteration.
// The pre-loop illegally has 2 control users (old & new loops).
! clone_loop( loop, old_new, dom_depth(head) );
// Step 2: Make the old-loop fall-in edges point to the peeled iteration.
// Do this by making the old-loop fall-in edges act as if they came
// around the loopback from the prior iteration (follow the old-loop
// backedges) and then map to the new peeled iteration. This leaves
// the pre-loop with only 1 user (the new peeled iteration), but the
// peeled-loop backedge has 2 users.
Node* new_entry = old_new[head->in(LoopNode::LoopBackControl)->_idx];
! _igvn.hash_delete(head);
! head->set_req(LoopNode::EntryControl, new_entry);
for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {
Node* old = head->fast_out(j);
if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) {
Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
if (!new_exit_value ) // Backedge value is ALSO loop invariant?
--- 525,545 ----
}
Node* entry = head->in(LoopNode::EntryControl);
// Step 1: Clone the loop body. The clone becomes the peeled iteration.
// The pre-loop illegally has 2 control users (old & new loops).
! clone_loop(loop, old_new, dom_depth(head->skip_strip_mined()), ControlAroundStripMined);
// Step 2: Make the old-loop fall-in edges point to the peeled iteration.
// Do this by making the old-loop fall-in edges act as if they came
// around the loopback from the prior iteration (follow the old-loop
// backedges) and then map to the new peeled iteration. This leaves
// the pre-loop with only 1 user (the new peeled iteration), but the
// peeled-loop backedge has 2 users.
Node* new_entry = old_new[head->in(LoopNode::LoopBackControl)->_idx];
! _igvn.hash_delete(head->skip_strip_mined());
! head->skip_strip_mined()->set_req(LoopNode::EntryControl, new_entry);
for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {
Node* old = head->fast_out(j);
if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) {
Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
if (!new_exit_value ) // Backedge value is ALSO loop invariant?
*** 1007,1018 ****
CountedLoopNode *main_head = loop->_head->as_CountedLoop();
assert( main_head->is_normal_loop(), "" );
CountedLoopEndNode *main_end = main_head->loopexit();
guarantee(main_end != NULL, "no loop exit node");
assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
- uint dd_main_head = dom_depth(main_head);
- uint max = main_head->outcnt();
Node *pre_header= main_head->in(LoopNode::EntryControl);
Node *init = main_head->init_trip();
Node *incr = main_end ->incr();
Node *limit = main_end ->limit();
--- 1020,1029 ----
*** 1041,1051 ****
//------------------------------
// Step B: Create Pre-Loop.
// Step B1: Clone the loop body. The clone becomes the pre-loop. The main
// loop pre-header illegally has 2 control users (old & new loops).
! clone_loop( loop, old_new, dd_main_head );
CountedLoopNode* pre_head = old_new[main_head->_idx]->as_CountedLoop();
CountedLoopEndNode* pre_end = old_new[main_end ->_idx]->as_CountedLoopEnd();
pre_head->set_pre_loop(main_head);
Node *pre_incr = old_new[incr->_idx];
--- 1052,1071 ----
//------------------------------
// Step B: Create Pre-Loop.
// Step B1: Clone the loop body. The clone becomes the pre-loop. The main
// loop pre-header illegally has 2 control users (old & new loops).
! LoopNode* outer_main_head = main_head;
! IdealLoopTree* outer_loop = loop;
! if (main_head->is_strip_mined()) {
! main_head->verify_strip_mined(1);
! outer_main_head = main_head->outer_loop();
! outer_loop = loop->_parent;
! assert(outer_loop->_head == outer_main_head, "broken loop tree");
! }
! uint dd_main_head = dom_depth(outer_main_head);
! clone_loop(loop, old_new, dd_main_head, ControlAroundStripMined);
CountedLoopNode* pre_head = old_new[main_head->_idx]->as_CountedLoop();
CountedLoopEndNode* pre_end = old_new[main_end ->_idx]->as_CountedLoopEnd();
pre_head->set_pre_loop(main_head);
Node *pre_incr = old_new[incr->_idx];
*** 1056,1066 ****
Node* pre_exit = pre_end->proj_out(false);
assert( pre_exit->Opcode() == Op_IfFalse, "" );
IfFalseNode *new_pre_exit = new IfFalseNode(pre_end);
_igvn.register_new_node_with_optimizer( new_pre_exit );
set_idom(new_pre_exit, pre_end, dd_main_head);
! set_loop(new_pre_exit, loop->_parent);
// Step B2: Build a zero-trip guard for the main-loop. After leaving the
// pre-loop, the main-loop may not execute at all. Later in life this
// zero-trip guard will become the minimum-trip guard when we unroll
// the main-loop.
--- 1076,1086 ----
Node* pre_exit = pre_end->proj_out(false);
assert( pre_exit->Opcode() == Op_IfFalse, "" );
IfFalseNode *new_pre_exit = new IfFalseNode(pre_end);
_igvn.register_new_node_with_optimizer( new_pre_exit );
set_idom(new_pre_exit, pre_end, dd_main_head);
! set_loop(new_pre_exit, outer_loop->_parent);
// Step B2: Build a zero-trip guard for the main-loop. After leaving the
// pre-loop, the main-loop may not execute at all. Later in life this
// zero-trip guard will become the minimum-trip guard when we unroll
// the main-loop.
*** 1073,1098 ****
// Build the IfNode (assume the main-loop is executed always).
IfNode *min_iff = new IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN );
_igvn.register_new_node_with_optimizer( min_iff );
set_idom(min_iff, new_pre_exit, dd_main_head);
! set_loop(min_iff, loop->_parent);
// Plug in the false-path, taken if we need to skip main-loop
_igvn.hash_delete( pre_exit );
pre_exit->set_req(0, min_iff);
set_idom(pre_exit, min_iff, dd_main_head);
! set_idom(pre_exit->unique_out(), min_iff, dd_main_head);
// Make the true-path, must enter the main loop
Node *min_taken = new IfTrueNode( min_iff );
_igvn.register_new_node_with_optimizer( min_taken );
set_idom(min_taken, min_iff, dd_main_head);
! set_loop(min_taken, loop->_parent);
// Plug in the true path
! _igvn.hash_delete( main_head );
! main_head->set_req(LoopNode::EntryControl, min_taken);
! set_idom(main_head, min_taken, dd_main_head);
Arena *a = Thread::current()->resource_area();
VectorSet visited(a);
Node_Stack clones(a, main_head->back_control()->outcnt());
// Step B3: Make the fall-in values to the main-loop come from the
--- 1093,1118 ----
// Build the IfNode (assume the main-loop is executed always).
IfNode *min_iff = new IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN );
_igvn.register_new_node_with_optimizer( min_iff );
set_idom(min_iff, new_pre_exit, dd_main_head);
! set_loop(min_iff, outer_loop->_parent);
// Plug in the false-path, taken if we need to skip main-loop
_igvn.hash_delete( pre_exit );
pre_exit->set_req(0, min_iff);
set_idom(pre_exit, min_iff, dd_main_head);
! set_idom(pre_exit->unique_ctrl_out(), min_iff, dd_main_head);
// Make the true-path, must enter the main loop
Node *min_taken = new IfTrueNode( min_iff );
_igvn.register_new_node_with_optimizer( min_taken );
set_idom(min_taken, min_iff, dd_main_head);
! set_loop(min_taken, outer_loop->_parent);
// Plug in the true path
! _igvn.hash_delete(outer_main_head);
! outer_main_head->set_req(LoopNode::EntryControl, min_taken);
! set_idom(outer_main_head, min_taken, dd_main_head);
Arena *a = Thread::current()->resource_area();
VectorSet visited(a);
Node_Stack clones(a, main_head->back_control()->outcnt());
// Step B3: Make the fall-in values to the main-loop come from the
*** 1100,1110 ****
for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) {
Node* main_phi = main_head->fast_out(i2);
if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) {
Node *pre_phi = old_new[main_phi->_idx];
Node *fallpre = clone_up_backedge_goo(pre_head->back_control(),
! main_head->init_control(),
pre_phi->in(LoopNode::LoopBackControl),
visited, clones);
_igvn.hash_delete(main_phi);
main_phi->set_req( LoopNode::EntryControl, fallpre );
}
--- 1120,1130 ----
for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) {
Node* main_phi = main_head->fast_out(i2);
if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) {
Node *pre_phi = old_new[main_phi->_idx];
Node *fallpre = clone_up_backedge_goo(pre_head->back_control(),
! main_head->skip_strip_mined()->in(LoopNode::EntryControl),
pre_phi->in(LoopNode::LoopBackControl),
visited, clones);
_igvn.hash_delete(main_phi);
main_phi->set_req( LoopNode::EntryControl, fallpre );
}
*** 1169,1178 ****
--- 1189,1206 ----
// Modify main loop end condition
BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool();
BoolNode* new_bol2 = new BoolNode(main_bol->in(1), new_test);
register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) );
_igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, new_bol2);
+ if (main_head->is_strip_mined()) {
+ Node* le = outer_main_head->outer_loop_end();
+ Node* bol = outer_main_head->outer_bol();
+ Node* new_bol3 = new_bol2->clone();
+ new_bol3->set_req(1, bol->in(1));
+ register_new_node(new_bol3, le->in(0));
+ _igvn.replace_input_of(le, 1, new_bol3);
+ }
}
// Flag main loop
main_head->set_main_loop();
if( peel_only ) main_head->set_main_no_pre_loop();
*** 1303,1336 ****
//------------------------------insert_post_loop-------------------------------
// Insert post loops. Add a post loop to the given loop passed.
Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new,
CountedLoopNode *main_head, CountedLoopEndNode *main_end,
Node *incr, Node *limit, CountedLoopNode *&post_head) {
//------------------------------
// Step A: Create a new post-Loop.
! Node* main_exit = main_end->proj_out(false);
assert(main_exit->Opcode() == Op_IfFalse, "");
int dd_main_exit = dom_depth(main_exit);
// Step A1: Clone the loop body of main. The clone becomes the post-loop.
// The main loop pre-header illegally has 2 control users (old & new loops).
! clone_loop(loop, old_new, dd_main_exit);
assert(old_new[main_end->_idx]->Opcode() == Op_CountedLoopEnd, "");
post_head = old_new[main_head->_idx]->as_CountedLoop();
post_head->set_normal_loop();
post_head->set_post_loop(main_head);
// Reduce the post-loop trip count.
CountedLoopEndNode* post_end = old_new[main_end->_idx]->as_CountedLoopEnd();
post_end->_prob = PROB_FAIR;
// Build the main-loop normal exit.
! IfFalseNode *new_main_exit = new IfFalseNode(main_end);
_igvn.register_new_node_with_optimizer(new_main_exit);
! set_idom(new_main_exit, main_end, dd_main_exit);
! set_loop(new_main_exit, loop->_parent);
// Step A2: Build a zero-trip guard for the post-loop. After leaving the
// main-loop, the post-loop may not execute at all. We 'opaque' the incr
// (the previous loop trip-counter exit value) because we will be changing
// the exit value (via additional unrolling) so we cannot constant-fold away the zero
--- 1331,1372 ----
//------------------------------insert_post_loop-------------------------------
// Insert post loops. Add a post loop to the given loop passed.
Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new,
CountedLoopNode *main_head, CountedLoopEndNode *main_end,
Node *incr, Node *limit, CountedLoopNode *&post_head) {
+ IfNode* outer_main_end = main_end;
+ IdealLoopTree* outer_loop = loop;
+ if (main_head->is_strip_mined()) {
+ main_head->verify_strip_mined(1);
+ outer_main_end = main_head->outer_loop_end();
+ outer_loop = loop->_parent;
+ assert(outer_loop->_head == main_head->in(LoopNode::EntryControl), "broken loop tree");
+ }
//------------------------------
// Step A: Create a new post-Loop.
! Node* main_exit = outer_main_end->proj_out(false);
assert(main_exit->Opcode() == Op_IfFalse, "");
int dd_main_exit = dom_depth(main_exit);
// Step A1: Clone the loop body of main. The clone becomes the post-loop.
// The main loop pre-header illegally has 2 control users (old & new loops).
! clone_loop(loop, old_new, dd_main_exit, ControlAroundStripMined);
assert(old_new[main_end->_idx]->Opcode() == Op_CountedLoopEnd, "");
post_head = old_new[main_head->_idx]->as_CountedLoop();
post_head->set_normal_loop();
post_head->set_post_loop(main_head);
// Reduce the post-loop trip count.
CountedLoopEndNode* post_end = old_new[main_end->_idx]->as_CountedLoopEnd();
post_end->_prob = PROB_FAIR;
// Build the main-loop normal exit.
! IfFalseNode *new_main_exit = new IfFalseNode(outer_main_end);
_igvn.register_new_node_with_optimizer(new_main_exit);
! set_idom(new_main_exit, outer_main_end, dd_main_exit);
! set_loop(new_main_exit, outer_loop->_parent);
// Step A2: Build a zero-trip guard for the post-loop. After leaving the
// main-loop, the post-loop may not execute at all. We 'opaque' the incr
// (the previous loop trip-counter exit value) because we will be changing
// the exit value (via additional unrolling) so we cannot constant-fold away the zero
*** 1344,1364 ****
// Build the IfNode
IfNode *zer_iff = new IfNode(new_main_exit, zer_bol, PROB_FAIR, COUNT_UNKNOWN);
_igvn.register_new_node_with_optimizer(zer_iff);
set_idom(zer_iff, new_main_exit, dd_main_exit);
! set_loop(zer_iff, loop->_parent);
// Plug in the false-path, taken if we need to skip this post-loop
_igvn.replace_input_of(main_exit, 0, zer_iff);
set_idom(main_exit, zer_iff, dd_main_exit);
set_idom(main_exit->unique_out(), zer_iff, dd_main_exit);
// Make the true-path, must enter this post loop
Node *zer_taken = new IfTrueNode(zer_iff);
_igvn.register_new_node_with_optimizer(zer_taken);
set_idom(zer_taken, zer_iff, dd_main_exit);
! set_loop(zer_taken, loop->_parent);
// Plug in the true path
_igvn.hash_delete(post_head);
post_head->set_req(LoopNode::EntryControl, zer_taken);
set_idom(post_head, zer_taken, dd_main_exit);
--- 1380,1400 ----
// Build the IfNode
IfNode *zer_iff = new IfNode(new_main_exit, zer_bol, PROB_FAIR, COUNT_UNKNOWN);
_igvn.register_new_node_with_optimizer(zer_iff);
set_idom(zer_iff, new_main_exit, dd_main_exit);
! set_loop(zer_iff, outer_loop->_parent);
// Plug in the false-path, taken if we need to skip this post-loop
_igvn.replace_input_of(main_exit, 0, zer_iff);
set_idom(main_exit, zer_iff, dd_main_exit);
set_idom(main_exit->unique_out(), zer_iff, dd_main_exit);
// Make the true-path, must enter this post loop
Node *zer_taken = new IfTrueNode(zer_iff);
_igvn.register_new_node_with_optimizer(zer_taken);
set_idom(zer_taken, zer_iff, dd_main_exit);
! set_loop(zer_taken, outer_loop->_parent);
// Plug in the true path
_igvn.hash_delete(post_head);
post_head->set_req(LoopNode::EntryControl, zer_taken);
set_idom(post_head, zer_taken, dd_main_exit);
*** 1429,1439 ****
// Remember loop node count before unrolling to detect
// if rounds of unroll,optimize are making progress
loop_head->set_node_count_before_unroll(loop->_body.size());
! Node *ctrl = loop_head->in(LoopNode::EntryControl);
Node *limit = loop_head->limit();
Node *init = loop_head->init_trip();
Node *stride = loop_head->stride();
Node *opaq = NULL;
--- 1465,1475 ----
// Remember loop node count before unrolling to detect
// if rounds of unroll,optimize are making progress
loop_head->set_node_count_before_unroll(loop->_body.size());
! Node *ctrl = loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
Node *limit = loop_head->limit();
Node *init = loop_head->init_trip();
Node *stride = loop_head->stride();
Node *opaq = NULL;
*** 1608,1618 ****
// ---------
// Step 4: Clone the loop body. Move it inside the loop. This loop body
// represents the odd iterations; since the loop trips an even number of
// times its backedge is never taken. Kill the backedge.
uint dd = dom_depth(loop_head);
! clone_loop( loop, old_new, dd );
// Make backedges of the clone equal to backedges of the original.
// Make the fall-in from the original come from the fall-out of the clone.
for (DUIterator_Fast jmax, j = loop_head->fast_outs(jmax); j < jmax; j++) {
Node* phi = loop_head->fast_out(j);
--- 1644,1654 ----
// ---------
// Step 4: Clone the loop body. Move it inside the loop. This loop body
// represents the odd iterations; since the loop trips an even number of
// times its backedge is never taken. Kill the backedge.
uint dd = dom_depth(loop_head);
! clone_loop(loop, old_new, dd, IgnoreStripMined);
// Make backedges of the clone equal to backedges of the original.
// Make the fall-in from the original come from the fall-out of the clone.
for (DUIterator_Fast jmax, j = loop_head->fast_outs(jmax); j < jmax; j++) {
Node* phi = loop_head->fast_out(j);
*** 1651,1660 ****
--- 1687,1697 ----
if (!has_ctrl(old))
set_loop(nnn, loop);
}
loop->record_for_igvn();
+ loop_head->clear_strip_mined();
#ifndef PRODUCT
if (C->do_vector_loop() && (PrintOpto && (VerifyLoopOptimizations || TraceLoopOpts))) {
tty->print("\nnew loop after unroll\n"); loop->dump_head();
for (uint i = 0; i < loop->_body.size(); i++) {
*** 2045,2055 ****
if (!is_canonical_loop_entry(cl)) {
return closed_range_checks;
}
// Need to find the main-loop zero-trip guard
! Node *ctrl = cl->in(LoopNode::EntryControl);
Node *iffm = ctrl->in(0);
Node *opqzm = iffm->in(1)->in(1)->in(2);
assert(opqzm->in(1) == main_limit, "do not understand situation");
// Find the pre-loop limit; we will expand its iterations to
--- 2082,2092 ----
if (!is_canonical_loop_entry(cl)) {
return closed_range_checks;
}
// Need to find the main-loop zero-trip guard
! Node *ctrl = cl->skip_strip_mined()->in(LoopNode::EntryControl);
Node *iffm = ctrl->in(0);
Node *opqzm = iffm->in(1)->in(1)->in(2);
assert(opqzm->in(1) == main_limit, "do not understand situation");
// Find the pre-loop limit; we will expand its iterations to
*** 2411,2421 ****
if (last_min && multi_version_succeeded) {
Node *cur_min = new MinINode(last_min, limit);
_igvn.register_new_node_with_optimizer(cur_min);
Node *cmp_node = rce_loop_end->cmp_node();
_igvn.replace_input_of(cmp_node, 2, cur_min);
- set_idom(cmp_node, cur_min, dom_depth(ctrl));
set_ctrl(cur_min, ctrl);
set_loop(cur_min, rce_loop->_parent);
legacy_cl->mark_is_multiversioned();
rce_cl->mark_is_multiversioned();
--- 2448,2457 ----
*** 2517,2527 ****
}
}
#ifdef ASSERT
static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) {
! Node *ctrl = cl->in(LoopNode::EntryControl);
assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "");
Node *iffm = ctrl->in(0);
assert(iffm->Opcode() == Op_If, "");
Node *p_f = iffm->in(0);
assert(p_f->Opcode() == Op_IfFalse, "");
--- 2553,2563 ----
}
}
#ifdef ASSERT
static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) {
! Node *ctrl = cl->skip_strip_mined()->in(LoopNode::EntryControl);
assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "");
Node *iffm = ctrl->in(0);
assert(iffm->Opcode() == Op_If, "");
Node *p_f = iffm->in(0);
assert(p_f->Opcode() == Op_IfFalse, "");
*** 2556,2566 ****
if (!main_head->is_main_loop()) {
return;
}
assert(locate_pre_from_main(main_head) == cl, "bad main loop");
! Node* main_iff = main_head->in(LoopNode::EntryControl)->in(0);
// Remove the Opaque1Node of the pre loop and make it execute all iterations
phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2));
// Remove the Opaque1Node of the main loop so it can be optimized out
Node* main_cmp = main_iff->in(1)->in(1);
--- 2592,2602 ----
if (!main_head->is_main_loop()) {
return;
}
assert(locate_pre_from_main(main_head) == cl, "bad main loop");
! Node* main_iff = main_head->skip_strip_mined()->in(LoopNode::EntryControl)->in(0);
// Remove the Opaque1Node of the pre loop and make it execute all iterations
phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2));
// Remove the Opaque1Node of the main loop so it can be optimized out
Node* main_cmp = main_iff->in(1)->in(1);
*** 2617,2627 ****
needs_guard = (init_t->_lo <= limit_t->_hi);
}
}
if (needs_guard) {
// Check for an obvious zero trip guard.
! Node* inctrl = PhaseIdealLoop::skip_loop_predicates(cl->in(LoopNode::EntryControl));
if (inctrl->Opcode() == Op_IfTrue || inctrl->Opcode() == Op_IfFalse) {
bool maybe_swapped = (inctrl->Opcode() == Op_IfFalse);
// The test should look like just the backedge of a CountedLoop
Node* iff = inctrl->in(0);
if (iff->is_If()) {
--- 2653,2663 ----
needs_guard = (init_t->_lo <= limit_t->_hi);
}
}
if (needs_guard) {
// Check for an obvious zero trip guard.
! Node* inctrl = PhaseIdealLoop::skip_loop_predicates(cl->skip_strip_mined()->in(LoopNode::EntryControl));
if (inctrl->Opcode() == Op_IfTrue || inctrl->Opcode() == Op_IfFalse) {
bool maybe_swapped = (inctrl->Opcode() == Op_IfFalse);
// The test should look like just the backedge of a CountedLoop
Node* iff = inctrl->in(0);
if (iff->is_If()) {
*** 3165,3174 ****
--- 3201,3212 ----
CountedLoopNode* head = lpt->_head->as_CountedLoop();
if (!head->is_valid_counted_loop() || !head->is_normal_loop()) {
return false;
}
+ head->verify_strip_mined(1);
+
// Check that the body only contains a store of a loop invariant
// value that is indexed by the loop phi.
Node* store = NULL;
Node* store_value = NULL;
Node* shift = NULL;
*** 3286,3295 ****
--- 3324,3343 ----
#endif
}
}
*/
+ if (head->is_strip_mined()) {
+ // Inner strip mined loop goes away so get rid of outer strip
+ // mined loop
+ Node* outer_sfpt = head->outer_safepoint();
+ Node* in = outer_sfpt->in(0);
+ Node* outer_out = head->outer_loop_exit();
+ lazy_replace(outer_out, in);
+ _igvn.replace_input_of(outer_sfpt, 0, C->top());
+ }
+
// Redirect the old control and memory edges that are outside the loop.
// Sometimes the memory phi of the head is used as the outgoing
// state of the loop. It's safe in this case to replace it with the
// result_mem.
_igvn.replace_node(store->in(MemNode::Memory), result_mem);
< prev index next >