src/share/vm/opto/loopTransform.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/loopTransform.cpp Fri Apr 1 14:29:04 2016
--- new/src/share/vm/opto/loopTransform.cpp Fri Apr 1 14:29:04 2016
*** 1466,1476 ****
--- 1466,1475 ----
}
C->set_major_progress();
Node* new_limit = NULL;
if (UnrollLimitCheck) {
int stride_con = stride->get_int();
int stride_p = (stride_con > 0) ? stride_con : -stride_con;
uint old_trip_count = loop_head->trip_count();
// Verify that unroll policy result is still valid.
assert(old_trip_count > 1 &&
*** 1618,1679 ****
--- 1617,1626 ----
loop_head->set_trip_count(old_trip_count / 2);
// Double the count of original iterations in the unrolled loop body.
loop_head->double_unrolled_count();
} else { // LoopLimitCheck
// Adjust max trip count. The trip count is intentionally rounded
// down here (e.g. 15-> 7-> 3-> 1) because if we unwittingly over-unroll,
// the main, unrolled, part of the loop will never execute as it is protected
// by the min-trip test. See bug 4834191 for a case where we over-unrolled
// and later determined that part of the unrolled loop was dead.
loop_head->set_trip_count(loop_head->trip_count() / 2);
// Double the count of original iterations in the unrolled loop body.
loop_head->double_unrolled_count();
// -----------
// Step 2: Cut back the trip counter for an unroll amount of 2.
// Loop will normally trip (limit - init)/stride_con. Since it's a
// CountedLoop this is exact (stride divides limit-init exactly).
// We are going to double the loop body, so we want to knock off any
// odd iteration: (trip_cnt & ~1). Then back compute a new limit.
Node *span = new SubINode( limit, init );
register_new_node( span, ctrl );
Node *trip = new DivINode( 0, span, stride );
register_new_node( trip, ctrl );
Node *mtwo = _igvn.intcon(-2);
set_ctrl(mtwo, C->root());
Node *rond = new AndINode( trip, mtwo );
register_new_node( rond, ctrl );
Node *spn2 = new MulINode( rond, stride );
register_new_node( spn2, ctrl );
new_limit = new AddINode( spn2, init );
register_new_node( new_limit, ctrl );
// Hammer in the new limit
Node *ctrl2 = loop_end->in(0);
Node *cmp2 = new CmpINode( loop_head->incr(), new_limit );
register_new_node( cmp2, ctrl2 );
Node *bol2 = new BoolNode( cmp2, loop_end->test_trip() );
register_new_node( bol2, ctrl2 );
_igvn.replace_input_of(loop_end, CountedLoopEndNode::TestValue, bol2);
// Step 3: Find the min-trip test guaranteed before a 'main' loop.
// Make it a 1-trip test (means at least 2 trips).
if( adjust_min_trip ) {
assert( new_limit != NULL, "" );
// Guard test uses an 'opaque' node which is not shared. Hence I
// can edit it's inputs directly. Hammer in the new limit for the
// minimum-trip guard.
assert( opaq->outcnt() == 1, "" );
_igvn.hash_delete(opaq);
opaq->set_req(1, new_limit);
}
} // LoopLimitCheck
// ---------
// 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);
*** 1902,1912 ****
--- 1849,1858 ----
// else /* scale < 0 and stride < 0 */
// I > (low_limit-offset)/scale
// )
if (low_limit->get_int() == -max_jint) {
if (!RangeLimitCheck) return;
// We need this guard when scale*pre_limit+offset >= limit
// due to underflow. So we need execute pre-loop until
// scale*I+offset >= min_int. But (min_int-offset) will
// underflow when offset > 0 and X will be > original_limit
// when stride > 0. To avoid it we replace positive offset with 0.
*** 1954,1964 ****
--- 1900,1909 ----
register_new_node( plus_one, pre_ctrl );
// Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
*pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl);
if (low_limit->get_int() == -max_jint) {
if (!RangeLimitCheck) return;
// We need this guard when scale*main_limit+offset >= limit
// due to underflow. So we need execute main-loop while
// scale*I+offset+1 > min_int. But (min_int-offset-1) will
// underflow when (offset+1) > 0 and X will be < main_limit
// when scale < 0 (and stride > 0). To avoid it we replace
*** 2256,2266 ****
--- 2201,2211 ----
if( b_test._test == BoolTest::lt ) { // Range checks always use lt
// The underflow and overflow limits: 0 <= scale*I+offset < limit
add_constraint( stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit );
if (!conditional_rc) {
// (0-offset)/scale could be outside of loop iterations range.
- conditional_rc = !loop->dominates_backedge(iff) || RangeLimitCheck;
}
} else {
if (PrintOpto) {
tty->print_cr("missed RCE opportunity");
}
*** 2292,2302 ****
--- 2237,2247 ----
add_constraint( stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit );
if (!conditional_rc) {
// ((MIN_INT+1)-offset)/scale could be outside of loop iterations range.
// Note: negative offset is replaced with 0 but (MIN_INT+1)/scale could
// still be outside of loop range.
- conditional_rc = !loop->dominates_backedge(iff) || RangeLimitCheck;
}
break;
default:
if (PrintOpto) {
tty->print_cr("missed RCE opportunity");
*** 2338,2367 ****
--- 2283,2292 ----
_igvn.replace_input_of(pre_opaq, 1, pre_limit);
// Note:: we are making the main loop limit no longer precise;
// need to round up based on stride.
cl->set_nonexact_trip_count();
if (!LoopLimitCheck && stride_con != 1 && stride_con != -1) { // Cutout for common case
// "Standard" round-up logic: ([main_limit-init+(y-1)]/y)*y+init
// Hopefully, compiler will optimize for powers of 2.
Node *ctrl = get_ctrl(main_limit);
Node *stride = cl->stride();
Node *init = cl->init_trip()->uncast();
Node *span = new SubINode(main_limit,init);
register_new_node(span,ctrl);
Node *rndup = _igvn.intcon(stride_con + ((stride_con>0)?-1:1));
Node *add = new AddINode(span,rndup);
register_new_node(add,ctrl);
Node *div = new DivINode(0,add,stride);
register_new_node(div,ctrl);
Node *mul = new MulINode(div,stride);
register_new_node(mul,ctrl);
Node *newlim = new AddINode(mul,init);
register_new_node(newlim,ctrl);
main_limit = newlim;
}
Node *main_cle = cl->loopexit();
Node *main_bol = main_cle->in(1);
// Hacking loop bounds; need private copies of exit test
if( main_bol->outcnt() > 1 ) {// BoolNode shared?
main_bol = main_bol->clone();// Clone a private BoolNode
src/share/vm/opto/loopTransform.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File