8072422: Cleanup: Remove some unused flags/code in loop optimizations

Remove unused flags, change test using them.

Reviewed-by: kvn, twisti
This commit is contained in:
Zoltan Majo 2016-04-04 12:52:11 +02:00
parent fa667c5409
commit 69d14c811b
8 changed files with 179 additions and 373 deletions

View File

@ -229,21 +229,12 @@
develop(bool, TraceLoopOpts, false, \
"Trace executed loop optimizations") \
\
diagnostic(bool, LoopLimitCheck, true, \
"Generate a loop limits check for overflow") \
\
develop(bool, TraceLoopLimitCheck, false, \
"Trace generation of loop limits checks") \
\
diagnostic(bool, RangeLimitCheck, true, \
"Additional overflow checks during range check elimination") \
\
develop(bool, TraceRangeLimitCheck, false, \
"Trace additional overflow checks in RCE") \
\
diagnostic(bool, UnrollLimitCheck, true, \
"Additional overflow checks during loop unroll") \
\
/* OptimizeFill not yet supported on PowerPC. */ \
product(bool, OptimizeFill, true PPC64_ONLY(&& false), \
"convert fill/copy loops into intrinsic") \

View File

@ -3773,9 +3773,7 @@ void GraphKit::add_predicate(int nargs) {
add_predicate_impl(Deoptimization::Reason_predicate, nargs);
}
// loop's limit check predicate should be near the loop.
if (LoopLimitCheck) {
add_predicate_impl(Deoptimization::Reason_loop_limit_check, nargs);
}
add_predicate_impl(Deoptimization::Reason_loop_limit_check, nargs);
}
//----------------------------- store barriers ----------------------------

View File

@ -313,11 +313,9 @@ Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry,
// Search original predicates
Node* entry = old_entry;
ProjNode* limit_check_proj = NULL;
if (LoopLimitCheck) {
limit_check_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (limit_check_proj != NULL) {
entry = entry->in(0)->in(0);
}
limit_check_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (limit_check_proj != NULL) {
entry = entry->in(0)->in(0);
}
if (UseLoopPredicate) {
ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
@ -353,11 +351,9 @@ Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry,
// Skip related predicates.
Node* PhaseIdealLoop::skip_loop_predicates(Node* entry) {
Node* predicate = NULL;
if (LoopLimitCheck) {
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL) {
entry = entry->in(0)->in(0);
}
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL) {
entry = entry->in(0)->in(0);
}
if (UseLoopPredicate) {
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
@ -393,11 +389,9 @@ ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimi
// Find a predicate
Node* PhaseIdealLoop::find_predicate(Node* entry) {
Node* predicate = NULL;
if (LoopLimitCheck) {
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL) { // right pattern that can be used by loop predication
return entry;
}
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL) { // right pattern that can be used by loop predication
return entry;
}
if (UseLoopPredicate) {
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
@ -646,19 +640,13 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
Node* max_idx_expr = init;
int stride_con = stride->get_int();
if ((stride_con > 0) == (scale > 0) == upper) {
if (LoopLimitCheck) {
// With LoopLimitCheck limit is not exact.
// Calculate exact limit here.
// Note, counted loop's test is '<' or '>'.
limit = exact_limit(loop);
max_idx_expr = new SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
if (TraceLoopPredicate) predString->print("(limit - stride) ");
} else {
max_idx_expr = new SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
if (TraceLoopPredicate) predString->print("(limit - stride) ");
}
// Limit is not exact.
// Calculate exact limit here.
// Note, counted loop's test is '<' or '>'.
limit = exact_limit(loop);
max_idx_expr = new SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
if (TraceLoopPredicate) predString->print("(limit - stride) ");
} else {
if (TraceLoopPredicate) predString->print("init ");
}
@ -721,12 +709,9 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
Node* entry = head->in(LoopNode::EntryControl);
ProjNode *predicate_proj = NULL;
// Loop limit check predicate should be near the loop.
if (LoopLimitCheck) {
predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate_proj != NULL)
entry = predicate_proj->in(0)->in(0);
}
predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate_proj != NULL)
entry = predicate_proj->in(0)->in(0);
predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
if (!predicate_proj) {
#ifndef PRODUCT

View File

@ -1468,209 +1468,156 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
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 &&
(!adjust_min_trip || stride_p <= (1<<3)*loop_head->unrolled_count()), "sanity");
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 &&
(!adjust_min_trip || stride_p <= (1<<3)*loop_head->unrolled_count()), "sanity");
// Adjust loop limit to keep valid iterations number after unroll.
// Use (limit - stride) instead of (((limit - init)/stride) & (-2))*stride
// which may overflow.
if (!adjust_min_trip) {
assert(old_trip_count > 1 && (old_trip_count & 1) == 0,
"odd trip count for maximally unroll");
// Don't need to adjust limit for maximally unroll since trip count is even.
} else if (loop_head->has_exact_trip_count() && init->is_Con()) {
// Loop's limit is constant. Loop's init could be constant when pre-loop
// become peeled iteration.
jlong init_con = init->get_int();
// We can keep old loop limit if iterations count stays the same:
// old_trip_count == new_trip_count * 2
// Note: since old_trip_count >= 2 then new_trip_count >= 1
// so we also don't need to adjust zero trip test.
jlong limit_con = limit->get_int();
// (stride_con*2) not overflow since stride_con <= 8.
int new_stride_con = stride_con * 2;
int stride_m = new_stride_con - (stride_con > 0 ? 1 : -1);
jlong trip_count = (limit_con - init_con + stride_m)/new_stride_con;
// New trip count should satisfy next conditions.
assert(trip_count > 0 && (julong)trip_count < (julong)max_juint/2, "sanity");
uint new_trip_count = (uint)trip_count;
adjust_min_trip = (old_trip_count != new_trip_count*2);
}
// Adjust loop limit to keep valid iterations number after unroll.
// Use (limit - stride) instead of (((limit - init)/stride) & (-2))*stride
// which may overflow.
if (!adjust_min_trip) {
assert(old_trip_count > 1 && (old_trip_count & 1) == 0,
"odd trip count for maximally unroll");
// Don't need to adjust limit for maximally unroll since trip count is even.
} else if (loop_head->has_exact_trip_count() && init->is_Con()) {
// Loop's limit is constant. Loop's init could be constant when pre-loop
// become peeled iteration.
jlong init_con = init->get_int();
// We can keep old loop limit if iterations count stays the same:
// old_trip_count == new_trip_count * 2
// Note: since old_trip_count >= 2 then new_trip_count >= 1
// so we also don't need to adjust zero trip test.
jlong limit_con = limit->get_int();
// (stride_con*2) not overflow since stride_con <= 8.
int new_stride_con = stride_con * 2;
int stride_m = new_stride_con - (stride_con > 0 ? 1 : -1);
jlong trip_count = (limit_con - init_con + stride_m)/new_stride_con;
// New trip count should satisfy next conditions.
assert(trip_count > 0 && (julong)trip_count < (julong)max_juint/2, "sanity");
uint new_trip_count = (uint)trip_count;
adjust_min_trip = (old_trip_count != new_trip_count*2);
}
if (adjust_min_trip) {
// Step 2: Adjust the trip limit if it is called for.
// The adjustment amount is -stride. Need to make sure if the
// adjustment underflows or overflows, then the main loop is skipped.
Node* cmp = loop_end->cmp_node();
assert(cmp->in(2) == limit, "sanity");
assert(opaq != NULL && opaq->in(1) == limit, "sanity");
if (adjust_min_trip) {
// Step 2: Adjust the trip limit if it is called for.
// The adjustment amount is -stride. Need to make sure if the
// adjustment underflows or overflows, then the main loop is skipped.
Node* cmp = loop_end->cmp_node();
assert(cmp->in(2) == limit, "sanity");
assert(opaq != NULL && opaq->in(1) == limit, "sanity");
// Verify that policy_unroll result is still valid.
const TypeInt* limit_type = _igvn.type(limit)->is_int();
assert(stride_con > 0 && ((limit_type->_hi - stride_con) < limit_type->_hi) ||
stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo), "sanity");
// Verify that policy_unroll result is still valid.
const TypeInt* limit_type = _igvn.type(limit)->is_int();
assert(stride_con > 0 && ((limit_type->_hi - stride_con) < limit_type->_hi) ||
stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo), "sanity");
if (limit->is_Con()) {
// The check in policy_unroll and the assert above guarantee
// no underflow if limit is constant.
new_limit = _igvn.intcon(limit->get_int() - stride_con);
set_ctrl(new_limit, C->root());
if (limit->is_Con()) {
// The check in policy_unroll and the assert above guarantee
// no underflow if limit is constant.
new_limit = _igvn.intcon(limit->get_int() - stride_con);
set_ctrl(new_limit, C->root());
} else {
// Limit is not constant.
if (loop_head->unrolled_count() == 1) { // only for first unroll
// Separate limit by Opaque node in case it is an incremented
// variable from previous loop to avoid using pre-incremented
// value which could increase register pressure.
// Otherwise reorg_offsets() optimization will create a separate
// Opaque node for each use of trip-counter and as result
// zero trip guard limit will be different from loop limit.
assert(has_ctrl(opaq), "should have it");
Node* opaq_ctrl = get_ctrl(opaq);
limit = new Opaque2Node( C, limit );
register_new_node( limit, opaq_ctrl );
}
if (stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo) ||
stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi)) {
// No underflow.
new_limit = new SubINode(limit, stride);
} else {
// Limit is not constant.
if (loop_head->unrolled_count() == 1) { // only for first unroll
// Separate limit by Opaque node in case it is an incremented
// variable from previous loop to avoid using pre-incremented
// value which could increase register pressure.
// Otherwise reorg_offsets() optimization will create a separate
// Opaque node for each use of trip-counter and as result
// zero trip guard limit will be different from loop limit.
assert(has_ctrl(opaq), "should have it");
Node* opaq_ctrl = get_ctrl(opaq);
limit = new Opaque2Node( C, limit );
register_new_node( limit, opaq_ctrl );
}
if (stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo) ||
stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi)) {
// No underflow.
new_limit = new SubINode(limit, stride);
// (limit - stride) may underflow.
// Clamp the adjustment value with MININT or MAXINT:
//
// new_limit = limit-stride
// if (stride > 0)
// new_limit = (limit < new_limit) ? MININT : new_limit;
// else
// new_limit = (limit > new_limit) ? MAXINT : new_limit;
//
BoolTest::mask bt = loop_end->test_trip();
assert(bt == BoolTest::lt || bt == BoolTest::gt, "canonical test is expected");
Node* adj_max = _igvn.intcon((stride_con > 0) ? min_jint : max_jint);
set_ctrl(adj_max, C->root());
Node* old_limit = NULL;
Node* adj_limit = NULL;
Node* bol = limit->is_CMove() ? limit->in(CMoveNode::Condition) : NULL;
if (loop_head->unrolled_count() > 1 &&
limit->is_CMove() && limit->Opcode() == Op_CMoveI &&
limit->in(CMoveNode::IfTrue) == adj_max &&
bol->as_Bool()->_test._test == bt &&
bol->in(1)->Opcode() == Op_CmpI &&
bol->in(1)->in(2) == limit->in(CMoveNode::IfFalse)) {
// Loop was unrolled before.
// Optimize the limit to avoid nested CMove:
// use original limit as old limit.
old_limit = bol->in(1)->in(1);
// Adjust previous adjusted limit.
adj_limit = limit->in(CMoveNode::IfFalse);
adj_limit = new SubINode(adj_limit, stride);
} else {
// (limit - stride) may underflow.
// Clamp the adjustment value with MININT or MAXINT:
//
// new_limit = limit-stride
// if (stride > 0)
// new_limit = (limit < new_limit) ? MININT : new_limit;
// else
// new_limit = (limit > new_limit) ? MAXINT : new_limit;
//
BoolTest::mask bt = loop_end->test_trip();
assert(bt == BoolTest::lt || bt == BoolTest::gt, "canonical test is expected");
Node* adj_max = _igvn.intcon((stride_con > 0) ? min_jint : max_jint);
set_ctrl(adj_max, C->root());
Node* old_limit = NULL;
Node* adj_limit = NULL;
Node* bol = limit->is_CMove() ? limit->in(CMoveNode::Condition) : NULL;
if (loop_head->unrolled_count() > 1 &&
limit->is_CMove() && limit->Opcode() == Op_CMoveI &&
limit->in(CMoveNode::IfTrue) == adj_max &&
bol->as_Bool()->_test._test == bt &&
bol->in(1)->Opcode() == Op_CmpI &&
bol->in(1)->in(2) == limit->in(CMoveNode::IfFalse)) {
// Loop was unrolled before.
// Optimize the limit to avoid nested CMove:
// use original limit as old limit.
old_limit = bol->in(1)->in(1);
// Adjust previous adjusted limit.
adj_limit = limit->in(CMoveNode::IfFalse);
adj_limit = new SubINode(adj_limit, stride);
} else {
old_limit = limit;
adj_limit = new SubINode(limit, stride);
}
assert(old_limit != NULL && adj_limit != NULL, "");
register_new_node( adj_limit, ctrl ); // adjust amount
Node* adj_cmp = new CmpINode(old_limit, adj_limit);
register_new_node( adj_cmp, ctrl );
Node* adj_bool = new BoolNode(adj_cmp, bt);
register_new_node( adj_bool, ctrl );
new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT);
old_limit = limit;
adj_limit = new SubINode(limit, stride);
}
register_new_node(new_limit, ctrl);
assert(old_limit != NULL && adj_limit != NULL, "");
register_new_node( adj_limit, ctrl ); // adjust amount
Node* adj_cmp = new CmpINode(old_limit, adj_limit);
register_new_node( adj_cmp, ctrl );
Node* adj_bool = new BoolNode(adj_cmp, bt);
register_new_node( adj_bool, ctrl );
new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT);
}
assert(new_limit != NULL, "");
// Replace in loop test.
assert(loop_end->in(1)->in(1) == cmp, "sanity");
if (cmp->outcnt() == 1 && loop_end->in(1)->outcnt() == 1) {
// Don't need to create new test since only one user.
_igvn.hash_delete(cmp);
cmp->set_req(2, new_limit);
} else {
// Create new test since it is shared.
Node* ctrl2 = loop_end->in(0);
Node* cmp2 = cmp->clone();
cmp2->set_req(2, new_limit);
register_new_node(cmp2, ctrl2);
Node* bol2 = loop_end->in(1)->clone();
bol2->set_req(1, cmp2);
register_new_node(bol2, ctrl2);
_igvn.replace_input_of(loop_end, 1, bol2);
}
// Step 3: Find the min-trip test guaranteed before a 'main' loop.
// Make it a 1-trip test (means at least 2 trips).
// 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.replace_input_of(opaq, 1, new_limit);
register_new_node(new_limit, ctrl);
}
assert(new_limit != NULL, "");
// Replace in loop test.
assert(loop_end->in(1)->in(1) == cmp, "sanity");
if (cmp->outcnt() == 1 && loop_end->in(1)->outcnt() == 1) {
// Don't need to create new test since only one user.
_igvn.hash_delete(cmp);
cmp->set_req(2, new_limit);
} else {
// Create new test since it is shared.
Node* ctrl2 = loop_end->in(0);
Node* cmp2 = cmp->clone();
cmp2->set_req(2, new_limit);
register_new_node(cmp2, ctrl2);
Node* bol2 = loop_end->in(1)->clone();
bol2->set_req(1, cmp2);
register_new_node(bol2, ctrl2);
_igvn.replace_input_of(loop_end, 1, bol2);
}
// 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(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
// 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.replace_input_of(opaq, 1, new_limit);
}
// 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(old_trip_count / 2);
// Double the count of original iterations in the unrolled loop body.
loop_head->double_unrolled_count();
// ---------
// Step 4: Clone the loop body. Move it inside the loop. This loop body
@ -1904,7 +1851,6 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
// )
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
@ -1956,7 +1902,6 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
*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
@ -2258,7 +2203,7 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
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;
conditional_rc = !loop->dominates_backedge(iff);
}
} else {
if (PrintOpto) {
@ -2294,7 +2239,7 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
// ((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;
conditional_rc = !loop->dominates_backedge(iff);
}
break;
default:
@ -2340,26 +2285,6 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
// 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

View File

@ -138,7 +138,7 @@ void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) {
Node* uniqc = proj_true->unique_ctrl_out();
Node* entry = head->in(LoopNode::EntryControl);
Node* predicate = find_predicate(entry);
if (predicate != NULL && LoopLimitCheck && UseLoopPredicate) {
if (predicate != NULL && UseLoopPredicate) {
// We may have two predicates, find first.
entry = find_predicate(entry->in(0)->in(0));
if (entry != NULL) predicate = entry;

View File

@ -463,8 +463,6 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
Node *hook = new Node(6);
if (LoopLimitCheck) {
// ===================================================
// Generate loop limit check to avoid integer overflow
// in cases like next (cyclic loops):
@ -593,103 +591,6 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
}
set_subtree_ctrl( limit );
} else { // LoopLimitCheck
// If compare points to incr, we are ok. Otherwise the compare
// can directly point to the phi; in this case adjust the compare so that
// it points to the incr by adjusting the limit.
if (cmp->in(1) == phi || cmp->in(2) == phi)
limit = gvn->transform(new AddINode(limit,stride));
// trip-count for +-tive stride should be: (limit - init_trip + stride - 1)/stride.
// Final value for iterator should be: trip_count * stride + init_trip.
Node *one_p = gvn->intcon( 1);
Node *one_m = gvn->intcon(-1);
Node *trip_count = NULL;
switch( bt ) {
case BoolTest::eq:
ShouldNotReachHere();
case BoolTest::ne: // Ahh, the case we desire
if (stride_con == 1)
trip_count = gvn->transform(new SubINode(limit,init_trip));
else if (stride_con == -1)
trip_count = gvn->transform(new SubINode(init_trip,limit));
else
ShouldNotReachHere();
set_subtree_ctrl(trip_count);
//_loop.map(trip_count->_idx,loop(limit));
break;
case BoolTest::le: // Maybe convert to '<' case
limit = gvn->transform(new AddINode(limit,one_p));
set_subtree_ctrl( limit );
hook->init_req(4, limit);
bt = BoolTest::lt;
// Make the new limit be in the same loop nest as the old limit
//_loop.map(limit->_idx,limit_loop);
// Fall into next case
case BoolTest::lt: { // Maybe convert to '!=' case
if (stride_con < 0) // Count down loop rolls through MAXINT
ShouldNotReachHere();
Node *range = gvn->transform(new SubINode(limit,init_trip));
set_subtree_ctrl( range );
hook->init_req(0, range);
Node *bias = gvn->transform(new AddINode(range,stride));
set_subtree_ctrl( bias );
hook->init_req(1, bias);
Node *bias1 = gvn->transform(new AddINode(bias,one_m));
set_subtree_ctrl( bias1 );
hook->init_req(2, bias1);
trip_count = gvn->transform(new DivINode(0,bias1,stride));
set_subtree_ctrl( trip_count );
hook->init_req(3, trip_count);
break;
}
case BoolTest::ge: // Maybe convert to '>' case
limit = gvn->transform(new AddINode(limit,one_m));
set_subtree_ctrl( limit );
hook->init_req(4 ,limit);
bt = BoolTest::gt;
// Make the new limit be in the same loop nest as the old limit
//_loop.map(limit->_idx,limit_loop);
// Fall into next case
case BoolTest::gt: { // Maybe convert to '!=' case
if (stride_con > 0) // count up loop rolls through MININT
ShouldNotReachHere();
Node *range = gvn->transform(new SubINode(limit,init_trip));
set_subtree_ctrl( range );
hook->init_req(0, range);
Node *bias = gvn->transform(new AddINode(range,stride));
set_subtree_ctrl( bias );
hook->init_req(1, bias);
Node *bias1 = gvn->transform(new AddINode(bias,one_p));
set_subtree_ctrl( bias1 );
hook->init_req(2, bias1);
trip_count = gvn->transform(new DivINode(0,bias1,stride));
set_subtree_ctrl( trip_count );
hook->init_req(3, trip_count);
break;
}
} // switch( bt )
Node *span = gvn->transform(new MulINode(trip_count,stride));
set_subtree_ctrl( span );
hook->init_req(5, span);
limit = gvn->transform(new AddINode(span,init_trip));
set_subtree_ctrl( limit );
} // LoopLimitCheck
if (!UseCountedLoopSafepoints) {
// Check for SafePoint on backedge and remove
Node *sfpt = x->in(LoopNode::LoopBackControl);
@ -829,7 +730,7 @@ Node* PhaseIdealLoop::exact_limit( IdealLoopTree *loop ) {
CountedLoopNode *cl = loop->_head->as_CountedLoop();
assert(cl->is_valid_counted_loop(), "");
if (!LoopLimitCheck || ABS(cl->stride_con()) == 1 ||
if (ABS(cl->stride_con()) == 1 ||
cl->limit()->Opcode() == Op_LoopLimit) {
// Old code has exact limit (it could be incorrect in case of int overflow).
// Loop limit is exact with stride == 1. And loop may already have exact limit.
@ -1897,12 +1798,10 @@ void IdealLoopTree::dump_head( ) const {
tty->print("Loop: N%d/N%d ",_head->_idx,_tail->_idx);
if (_irreducible) tty->print(" IRREDUCIBLE");
Node* entry = _head->in(LoopNode::EntryControl);
if (LoopLimitCheck) {
Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL ) {
tty->print(" limit_check");
entry = entry->in(0)->in(0);
}
Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL ) {
tty->print(" limit_check");
entry = entry->in(0)->in(0);
}
if (UseLoopPredicate) {
entry = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
@ -2322,7 +2221,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
// Some parser-inserted loop predicates could never be used by loop
// predication or they were moved away from loop during some optimizations.
// For example, peeling. Eliminate them before next loop optimizations.
if (UseLoopPredicate || LoopLimitCheck) {
if (UseLoopPredicate) {
eliminate_useless_predicates();
}

View File

@ -661,8 +661,7 @@ void Parse::do_all_blocks() {
// (Note that dead locals do not get phis built, ever.)
ensure_phis_everywhere();
if (block->is_SEL_head() &&
(UseLoopPredicate || LoopLimitCheck)) {
if (block->is_SEL_head() && UseLoopPredicate) {
// Add predicate to single entry (not irreducible) loop head.
assert(!block->has_merged_backedge(), "only entry paths should be merged for now");
// Need correct bci for predicate.

View File

@ -26,10 +26,19 @@
* @test
* @bug 8073184
* @summary CastII that guards counted loops confuses range check elimination with LoopLimitCheck off
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-LoopLimitCheck -XX:CompileOnly=TestCastIINoLoopLimitCheck.m -Xcomp TestCastIINoLoopLimitCheck
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:CompileOnly=TestCastIINoLoopLimitCheck.m -Xcomp TestCastIINoLoopLimitCheck
*
*/
/*
* The test was originally run with
*
* -XX:+UnlockDiagnosticVMOptions -XX:-LoopLimitCheck
*
* to trigger a problem with code guarded with !LoopLimitCheck.
* JDK-8072422 has removed that code but kept the test because the
* test generates an interesting graph shape.
*/
public class TestCastIINoLoopLimitCheck {
static void m(int i, int index, char[] buf) {