< 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 >