--- old/src/share/vm/opto/loopnode.hpp 2015-06-04 16:44:58.736561883 +0200 +++ new/src/share/vm/opto/loopnode.hpp 2015-06-04 16:44:57.542319564 +0200 @@ -485,6 +485,8 @@ bool is_inner() { return is_loop() && _child == NULL; } bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); } + void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); + #ifndef PRODUCT void dump_head( ) const; // Dump loop head only void dump() const; // Dump this loop recursively --- old/src/share/vm/opto/loopTransform.cpp 2015-06-04 16:44:58.738264341 +0200 +++ new/src/share/vm/opto/loopTransform.cpp 2015-06-04 16:44:57.517902475 +0200 @@ -475,7 +475,7 @@ 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 + // '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. @@ -1911,7 +1911,7 @@ return; assert(opqzm->in(1) == main_limit, "do not understand situation"); - // Find the pre-loop limit; we will expand it's iterations to + // 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, ""); @@ -2215,6 +2215,47 @@ } } +#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. @@ -2233,6 +2274,12 @@ 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;