src/share/vm/opto/loopTransform.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/opto/loopTransform.cpp

src/share/vm/opto/loopTransform.cpp

Print this page
rev 8543 : 8085832: Optimize main and post loop out when pre loop is found empty
Summary: Eliminate main loop and post loop if pre loop becomes empty
Reviewed-by:

*** 473,483 **** // void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { C->set_major_progress(); // Peeling a 'main' loop in a pre/main/post situation obfuscates the ! // 'pre' loop from the main and the 'pre' can no longer have it's // iterations adjusted. Therefore, we need to declare this loop as // no longer a 'main' loop; it will need new pre and post loops before // we can do further RCE. #ifndef PRODUCT if (TraceLoopOpts) { --- 473,483 ---- // void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { C->set_major_progress(); // Peeling a 'main' loop in a pre/main/post situation obfuscates the ! // 'pre' loop from the main and the 'pre' can no longer have its // iterations adjusted. Therefore, we need to declare this loop as // no longer a 'main' loop; it will need new pre and post loops before // we can do further RCE. #ifndef PRODUCT if (TraceLoopOpts) {
*** 1909,1919 **** // away and then another round of loop opts attempted. if (opqzm->Opcode() != Op_Opaque1) return; assert(opqzm->in(1) == main_limit, "do not understand situation"); ! // Find the pre-loop limit; we will expand it's iterations to // not ever trip low tests. Node *p_f = iffm->in(0); assert(p_f->Opcode() == Op_IfFalse, ""); CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); assert(pre_end->loopnode()->is_pre_loop(), ""); --- 1909,1919 ---- // away and then another round of loop opts attempted. if (opqzm->Opcode() != Op_Opaque1) return; assert(opqzm->in(1) == main_limit, "do not understand situation"); ! // Find the pre-loop limit; we will expand its iterations to // not ever trip low tests. Node *p_f = iffm->in(0); assert(p_f->Opcode() == Op_IfFalse, ""); CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); assert(pre_end->loopnode()->is_pre_loop(), "");
*** 2213,2222 **** --- 2213,2263 ---- } test = phase->idom(test); } } + #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, ""); + CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); + assert(pre_end->loopnode()->is_pre_loop(), ""); + return pre_end->loopnode(); + } + #endif + + // Remove the main and post loops and make the pre loop execute all + // iterations. Useful when the pre loop is found empty. + void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase) { + CountedLoopEndNode* pre_end = cl->loopexit(); + Node* pre_cmp = pre_end->cmp_node(); + if (pre_cmp->in(2)->Opcode() != Op_Opaque1) { + // Only safe to remove the main loop if the compiler optimized it + // out based on an unknown number of iterations + return; + } + + if (_next == NULL || !_next->_head->is_CountedLoop() || !_next->_head->as_CountedLoop()->is_main_loop()) { + // Can't find the main loop + return; + } + + CountedLoopNode* main_head = _next->_head->as_CountedLoop();; + 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); + assert(main_cmp->in(2)->Opcode() == Op_Opaque1, "main loop has no opaque node?"); + phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1)); + } //------------------------------policy_do_remove_empty_loop-------------------- // Micro-benchmark spamming. Policy is to always remove empty loops. // The 'DO' part is to replace the trip counter with the value it will // have on the last iteration. This will break the loop.
*** 2231,2240 **** --- 2272,2287 ---- if (!cl->is_valid_counted_loop()) return false; // Malformed loop if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) return false; // Infinite loop + if (cl->is_pre_loop()) { + // If the loop we are removing is a pre-loop then the main and + // post loop can be removed as well + remove_main_post_loops(cl, phase); + } + #ifdef ASSERT // Ensure only one phi which is the iv. Node* iv = NULL; for (DUIterator_Fast imax, i = cl->fast_outs(imax); i < imax; i++) { Node* n = cl->fast_out(i);
src/share/vm/opto/loopTransform.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File