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