@@ -2871,6 +2871,7 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
28712871 // Must know if its a count-up or count-down loop
28722872
28732873 int stride_con = cl->stride_con ();
2874+ bool abs_stride_is_one = stride_con == 1 || stride_con == -1 ;
28742875 Node* zero = _igvn.longcon (0 );
28752876 Node* one = _igvn.longcon (1 );
28762877 // Use symmetrical int range [-max_jint,max_jint]
@@ -2882,6 +2883,15 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
28822883 Node* loop_entry = cl->skip_strip_mined ()->in (LoopNode::EntryControl);
28832884 assert (loop_entry->is_Proj () && loop_entry->in (0 )->is_If (), " if projection only" );
28842885
2886+ // if abs(stride) == 1, an Assertion Predicate for the final iv value is added. We don't know the final iv value until
2887+ // we're done with range check elimination so use a place holder.
2888+ Node* final_iv_placeholder = nullptr ;
2889+ if (abs_stride_is_one) {
2890+ final_iv_placeholder = new Node (1 );
2891+ _igvn.set_type (final_iv_placeholder, TypeInt::INT);
2892+ final_iv_placeholder->init_req (0 , loop_entry);
2893+ }
2894+
28852895 // Check loop body for tests of trip-counter plus loop-invariant vs loop-variant.
28862896 for (uint i = 0 ; i < loop->_body .size (); i++) {
28872897 Node *iff = loop->_body [i];
@@ -2985,6 +2995,20 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
29852995 Node* opaque_init = new OpaqueLoopInitNode (C, init);
29862996 register_new_node (opaque_init, loop_entry);
29872997
2998+ if (abs_stride_is_one) {
2999+ // If the main loop becomes empty and the array access for this range check is sunk out of the loop, the index
3000+ // for the array access will be set to the index value of the final iteration which could be out of loop.
3001+ // Add an Assertion Predicate for that corner case. The final iv is computed from LoopLimit which is the
3002+ // LoopNode::limit() only if abs(stride) == 1 otherwise the computation depends on LoopNode::init_trip() as
3003+ // well. When LoopLimit only depends on LoopNode::limit(), there are cases where the zero trip guard for the
3004+ // main loop doesn't constant fold after range check elimination but, the array access for the final
3005+ // iteration of the main loop is out of bound and the index for that access is out of range for the range
3006+ // check CastII.
3007+ loop_entry = add_range_check_elimination_assertion_predicate (loop, loop_entry, scale_con, int_offset,
3008+ int_limit, stride_con, final_iv_placeholder, false );
3009+ assert (!assertion_predicate_has_loop_opaque_node (loop_entry->in (0 )->as_If ()), " unexpected" );
3010+ }
3011+
29883012 // Initialized Assertion Predicate for the value of the initial main-loop.
29893013 loop_entry = add_range_check_elimination_assertion_predicate (loop, loop_entry, scale_con, int_offset,
29903014 int_limit, stride_con, init, false );
@@ -3116,11 +3140,14 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
31163140 register_new_node (main_limit, pre_ctrl);
31173141 // Hack the now-private loop bounds
31183142 _igvn.replace_input_of (main_cmp, 2 , main_limit);
3143+ if (abs_stride_is_one) {
3144+ Node* final_iv = new SubINode (main_limit, cl->stride ());
3145+ register_new_node (final_iv, loop_entry);
3146+ _igvn.replace_node (final_iv_placeholder, final_iv);
3147+ }
31193148 // The OpaqueNode is unshared by design
31203149 assert (opqzm->outcnt () == 1 , " cannot hack shared node" );
31213150 _igvn.replace_input_of (opqzm, 1 , main_limit);
3122-
3123- return ;
31243151}
31253152
31263153bool IdealLoopTree::compute_has_range_checks () const {
0 commit comments