< prev index next >
src/share/vm/opto/loopTransform.cpp
Print this page
rev 9032 : 8215265: C2: range check elimination may allow illegal out of bound access
Reviewed-by: thartmann, kvn
*** 1535,1551 ****
return _phase->dom_lca_internal(ctrl, backedge) == ctrl;
}
//------------------------------adjust_limit-----------------------------------
// Helper function for add_constraint().
! Node* PhaseIdealLoop::adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl) {
// Compute "I :: (limit-offset)/scale"
Node *con = new (C) SubINode(rc_limit, offset);
register_new_node(con, pre_ctrl);
Node *X = new (C) DivINode(0, con, scale);
register_new_node(X, pre_ctrl);
// Adjust loop limit
loop_limit = (stride_con > 0)
? (Node*)(new (C) MinINode(loop_limit, X))
: (Node*)(new (C) MaxINode(loop_limit, X));
register_new_node(loop_limit, pre_ctrl);
--- 1535,1558 ----
return _phase->dom_lca_internal(ctrl, backedge) == ctrl;
}
//------------------------------adjust_limit-----------------------------------
// Helper function for add_constraint().
! Node* PhaseIdealLoop::adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl, bool round_up) {
// Compute "I :: (limit-offset)/scale"
Node *con = new (C) SubINode(rc_limit, offset);
register_new_node(con, pre_ctrl);
Node *X = new (C) DivINode(0, con, scale);
register_new_node(X, pre_ctrl);
+ // When the absolute value of scale is greater than one, the integer
+ // division may round limit down so add one to the limit.
+ if (round_up) {
+ X = new (C) AddINode(X, _igvn.intcon(1));
+ register_new_node(X, pre_ctrl);
+ }
+
// Adjust loop limit
loop_limit = (stride_con > 0)
? (Node*)(new (C) MinINode(loop_limit, X))
: (Node*)(new (C) MaxINode(loop_limit, X));
register_new_node(loop_limit, pre_ctrl);
*** 1582,1592 ****
// )
//
// (upper_limit-offset) may overflow or underflow.
// But it is fine since main loop will either have
// less iterations or will be skipped in such case.
! *main_limit = adjust_limit(stride_con, scale, offset, upper_limit, *main_limit, pre_ctrl);
// The underflow limit: low_limit <= scale*I+offset.
// For pre-loop compute
// NOT(scale*I+offset >= low_limit)
// scale*I+offset < low_limit
--- 1589,1599 ----
// )
//
// (upper_limit-offset) may overflow or underflow.
// But it is fine since main loop will either have
// less iterations or will be skipped in such case.
! *main_limit = adjust_limit(stride_con, scale, offset, upper_limit, *main_limit, pre_ctrl, false);
// The underflow limit: low_limit <= scale*I+offset.
// For pre-loop compute
// NOT(scale*I+offset >= low_limit)
// scale*I+offset < low_limit
*** 1618,1628 ****
// since (0-min_int) == min_int. It may be fine for stride > 0
// but for stride < 0 X will be < original_limit. To avoid it
// max(pre_limit, original_limit) is used in do_range_check().
}
// Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
! *pre_limit = adjust_limit((-stride_con), scale, offset, low_limit, *pre_limit, pre_ctrl);
} else { // stride_con*scale_con < 0
// For negative stride*scale pre-loop checks for overflow and
// post-loop for underflow.
//
--- 1625,1636 ----
// since (0-min_int) == min_int. It may be fine for stride > 0
// but for stride < 0 X will be < original_limit. To avoid it
// max(pre_limit, original_limit) is used in do_range_check().
}
// Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
! *pre_limit = adjust_limit((-stride_con), scale, offset, low_limit, *pre_limit, pre_ctrl,
! scale_con > 1 && stride_con > 0);
} else { // stride_con*scale_con < 0
// For negative stride*scale pre-loop checks for overflow and
// post-loop for underflow.
//
*** 1644,1654 ****
set_ctrl(one, C->root());
Node *plus_one = new (C) AddINode(offset, one);
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
--- 1652,1663 ----
set_ctrl(one, C->root());
Node *plus_one = new (C) AddINode(offset, one);
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,
! scale_con < -1 && stride_con > 0);
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
*** 1679,1689 ****
// I < (low_limit-(offset+1))/scale
// else /* scale > 0 and stride < 0 */
// I > (low_limit-(offset+1))/scale
// )
! *main_limit = adjust_limit(stride_con, scale, plus_one, low_limit, *main_limit, pre_ctrl);
}
}
//------------------------------is_scaled_iv---------------------------------
--- 1688,1699 ----
// I < (low_limit-(offset+1))/scale
// else /* scale > 0 and stride < 0 */
// I > (low_limit-(offset+1))/scale
// )
! *main_limit = adjust_limit(stride_con, scale, plus_one, low_limit, *main_limit, pre_ctrl,
! false);
}
}
//------------------------------is_scaled_iv---------------------------------
< prev index next >