8241114: Better range handling

Wed, 13 May 2020 15:59:17 +0200

author
dcherepanov
date
Wed, 13 May 2020 15:59:17 +0200
changeset 10010
824065fb8b18
parent 10009
8adf45218add
child 10011
c49a13526ba9

8241114: Better range handling
Reviewed-by: kvn, vlivanov, rhalade, ahgross, mbalao, andrew

src/share/vm/opto/addnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopTransform.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopnode.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/addnode.cpp	Wed Sep 23 16:26:20 2020 +0300
     1.2 +++ b/src/share/vm/opto/addnode.cpp	Wed May 13 15:59:17 2020 +0200
     1.3 @@ -844,6 +844,14 @@
     1.4    return TypeInt::make( MAX2(r0->_lo,r1->_lo), MAX2(r0->_hi,r1->_hi), MAX2(r0->_widen,r1->_widen) );
     1.5  }
     1.6  
     1.7 +// Check if addition of an integer with type 't' and a constant 'c' can overflow
     1.8 +static bool can_overflow(const TypeInt* t, jint c) {
     1.9 +  jint t_lo = t->_lo;
    1.10 +  jint t_hi = t->_hi;
    1.11 +  return ((c < 0 && (java_add(t_lo, c) > t_lo)) ||
    1.12 +          (c > 0 && (java_add(t_hi, c) < t_hi)));
    1.13 +}
    1.14 +
    1.15  //=============================================================================
    1.16  //------------------------------Idealize---------------------------------------
    1.17  // MINs show up in range-check loop limit calculations.  Look for
    1.18 @@ -866,7 +874,7 @@
    1.19  
    1.20    // Get left input & constant
    1.21    Node *x = l;
    1.22 -  int x_off = 0;
    1.23 +  jint x_off = 0;
    1.24    if( x->Opcode() == Op_AddI && // Check for "x+c0" and collect constant
    1.25        x->in(2)->is_Con() ) {
    1.26      const Type *t = x->in(2)->bottom_type();
    1.27 @@ -877,7 +885,7 @@
    1.28  
    1.29    // Scan a right-spline-tree for MINs
    1.30    Node *y = r;
    1.31 -  int y_off = 0;
    1.32 +  jint y_off = 0;
    1.33    // Check final part of MIN tree
    1.34    if( y->Opcode() == Op_AddI && // Check for "y+c1" and collect constant
    1.35        y->in(2)->is_Con() ) {
    1.36 @@ -891,6 +899,7 @@
    1.37      return this;
    1.38    }
    1.39  
    1.40 +  const TypeInt* tx = phase->type(x)->isa_int();
    1.41  
    1.42    if( r->Opcode() == Op_MinI ) {
    1.43      assert( r != r->in(2), "dead loop in MinINode::Ideal" );
    1.44 @@ -907,18 +916,23 @@
    1.45      if( x->_idx > y->_idx )
    1.46        return new (phase->C) MinINode(r->in(1),phase->transform(new (phase->C) MinINode(l,r->in(2))));
    1.47  
    1.48 -    // See if covers: MIN2(x+c0,MIN2(y+c1,z))
    1.49 -    if( !phase->eqv(x,y) ) return NULL;
    1.50 -    // If (y == x) transform MIN2(x+c0, MIN2(x+c1,z)) into
    1.51 -    // MIN2(x+c0 or x+c1 which less, z).
    1.52 -    return new (phase->C) MinINode(phase->transform(new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off)))),r->in(2));
    1.53 +    // Transform MIN2(x + c0, MIN2(x + c1, z)) into MIN2(x + MIN2(c0, c1), z)
    1.54 +    // if x == y and the additions can't overflow.
    1.55 +    if (phase->eqv(x,y) &&
    1.56 +        !can_overflow(tx, x_off) &&
    1.57 +        !can_overflow(tx, y_off)) {
    1.58 +      return new (phase->C) MinINode(phase->transform(new (phase->C) AddINode(x, phase->intcon(MIN2(x_off, y_off)))), r->in(2));
    1.59 +    }
    1.60    } else {
    1.61 -    // See if covers: MIN2(x+c0,y+c1)
    1.62 -    if( !phase->eqv(x,y) ) return NULL;
    1.63 -    // If (y == x) transform MIN2(x+c0,x+c1) into x+c0 or x+c1 which less.
    1.64 -    return new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off)));
    1.65 +    // Transform MIN2(x + c0, y + c1) into x + MIN2(c0, c1)
    1.66 +    // if x == y and the additions can't overflow.
    1.67 +    if (phase->eqv(x,y) &&
    1.68 +        !can_overflow(tx, x_off) &&
    1.69 +        !can_overflow(tx, y_off)) {
    1.70 +      return new (phase->C) AddINode(x,phase->intcon(MIN2(x_off,y_off)));
    1.71 +    }
    1.72    }
    1.73 -
    1.74 +  return NULL;
    1.75  }
    1.76  
    1.77  //------------------------------add_ring---------------------------------------
     2.1 --- a/src/share/vm/opto/loopTransform.cpp	Wed Sep 23 16:26:20 2020 +0300
     2.2 +++ b/src/share/vm/opto/loopTransform.cpp	Wed May 13 15:59:17 2020 +0200
     2.3 @@ -1530,65 +1530,78 @@
     2.4  }
     2.5  
     2.6  //------------------------------adjust_limit-----------------------------------
     2.7 -// Helper function for add_constraint().
     2.8 -Node* PhaseIdealLoop::adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl, bool round_up) {
     2.9 -  // Compute "I :: (limit-offset)/scale"
    2.10 -  Node *con = new (C) SubINode(rc_limit, offset);
    2.11 -  register_new_node(con, pre_ctrl);
    2.12 -  Node *X = new (C) DivINode(0, con, scale);
    2.13 -  register_new_node(X, pre_ctrl);
    2.14 +// Helper function that computes new loop limit as (rc_limit-offset)/scale
    2.15 +Node* PhaseIdealLoop::adjust_limit(bool is_positive_stride, Node* scale, Node* offset, Node* rc_limit, Node* old_limit, Node* pre_ctrl, bool round) {
    2.16 +  Node* sub = new (C) SubLNode(rc_limit, offset);
    2.17 +  register_new_node(sub, pre_ctrl);
    2.18 +  Node* limit = new (C) DivLNode(NULL, sub, scale);
    2.19 +  register_new_node(limit, pre_ctrl);
    2.20  
    2.21 -  // When the absolute value of scale is greater than one, the integer
    2.22 -  // division may round limit down so add one to the limit.
    2.23 -  if (round_up) {
    2.24 -    X = new (C) AddINode(X, _igvn.intcon(1));
    2.25 -    register_new_node(X, pre_ctrl);
    2.26 +  // When the absolute value of scale is greater than one, the division
    2.27 +  // may round limit down/up, so add/sub one to/from the limit.
    2.28 +  if (round) {
    2.29 +    limit = new (C) AddLNode(limit, _igvn.longcon(is_positive_stride ? -1 : 1));
    2.30 +    register_new_node(limit, pre_ctrl);
    2.31    }
    2.32  
    2.33 -  // Adjust loop limit
    2.34 -  loop_limit = (stride_con > 0)
    2.35 -               ? (Node*)(new (C) MinINode(loop_limit, X))
    2.36 -               : (Node*)(new (C) MaxINode(loop_limit, X));
    2.37 -  register_new_node(loop_limit, pre_ctrl);
    2.38 -  return loop_limit;
    2.39 +  // Clamp the limit to handle integer under-/overflows.
    2.40 +  // When reducing the limit, clamp to [min_jint, old_limit]:
    2.41 +  //   MIN(old_limit, MAX(limit, min_jint))
    2.42 +  // When increasing the limit, clamp to [old_limit, max_jint]:
    2.43 +  //   MAX(old_limit, MIN(limit, max_jint))
    2.44 +  Node* cmp = new (C) CmpLNode(limit, _igvn.longcon(is_positive_stride ? min_jint : max_jint));
    2.45 +  register_new_node(cmp, pre_ctrl);
    2.46 +  Node* bol = new (C) BoolNode(cmp, is_positive_stride ? BoolTest::lt : BoolTest::gt);
    2.47 +  register_new_node(bol, pre_ctrl);
    2.48 +  limit = new (C) ConvL2INode(limit);
    2.49 +  register_new_node(limit, pre_ctrl);
    2.50 +  limit = new (C) CMoveINode(bol, limit, _igvn.intcon(is_positive_stride ? min_jint : max_jint), TypeInt::INT);
    2.51 +  register_new_node(limit, pre_ctrl);
    2.52 +
    2.53 +  limit = is_positive_stride ? (Node*)(new (C) MinINode(old_limit, limit))
    2.54 +                             : (Node*)(new (C) MaxINode(old_limit, limit));
    2.55 +  register_new_node(limit, pre_ctrl);
    2.56 +  return limit;
    2.57  }
    2.58  
    2.59  //------------------------------add_constraint---------------------------------
    2.60  // Constrain the main loop iterations so the conditions:
    2.61 -//    low_limit <= scale_con * I + offset  <  upper_limit
    2.62 -// always holds true.  That is, either increase the number of iterations in
    2.63 -// the pre-loop or the post-loop until the condition holds true in the main
    2.64 -// loop.  Stride, scale, offset and limit are all loop invariant.  Further,
    2.65 -// stride and scale are constants (offset and limit often are).
    2.66 -void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit ) {
    2.67 -  // For positive stride, the pre-loop limit always uses a MAX function
    2.68 -  // and the main loop a MIN function.  For negative stride these are
    2.69 -  // reversed.
    2.70 +//    low_limit <= scale_con*I + offset < upper_limit
    2.71 +// always hold true. That is, either increase the number of iterations in the
    2.72 +// pre-loop or reduce the number of iterations in the main-loop until the condition
    2.73 +// holds true in the main-loop. Stride, scale, offset and limit are all loop
    2.74 +// invariant. Further, stride and scale are constants (offset and limit often are).
    2.75 +void PhaseIdealLoop::add_constraint(jlong stride_con, jlong scale_con, Node* offset, Node* low_limit, Node* upper_limit, Node* pre_ctrl, Node** pre_limit, Node** main_limit) {
    2.76 +  assert(_igvn.type(offset)->isa_long() != NULL && _igvn.type(low_limit)->isa_long() != NULL &&
    2.77 +         _igvn.type(upper_limit)->isa_long() != NULL, "arguments should be long values");
    2.78  
    2.79 -  // Also for positive stride*scale the affine function is increasing, so the
    2.80 -  // pre-loop must check for underflow and the post-loop for overflow.
    2.81 -  // Negative stride*scale reverses this; pre-loop checks for overflow and
    2.82 -  // post-loop for underflow.
    2.83 +  // For a positive stride, we need to reduce the main-loop limit and
    2.84 +  // increase the pre-loop limit. This is reversed for a negative stride.
    2.85 +  bool is_positive_stride = (stride_con > 0);
    2.86  
    2.87 -  Node *scale = _igvn.intcon(scale_con);
    2.88 +  // If the absolute scale value is greater one, division in 'adjust_limit' may require
    2.89 +  // rounding. Make sure the ABS method correctly handles min_jint.
    2.90 +  // Only do this for the pre-loop, one less iteration of the main loop doesn't hurt.
    2.91 +  bool round = ABS(scale_con) > 1;
    2.92 +
    2.93 +  Node* scale = _igvn.longcon(scale_con);
    2.94    set_ctrl(scale, C->root());
    2.95  
    2.96    if ((stride_con^scale_con) >= 0) { // Use XOR to avoid overflow
    2.97 +    // Positive stride*scale: the affine function is increasing,
    2.98 +    // the pre-loop checks for underflow and the post-loop for overflow.
    2.99 +
   2.100      // The overflow limit: scale*I+offset < upper_limit
   2.101 -    // For main-loop compute
   2.102 +    // For the main-loop limit compute:
   2.103      //   ( if (scale > 0) /* and stride > 0 */
   2.104      //       I < (upper_limit-offset)/scale
   2.105      //     else /* scale < 0 and stride < 0 */
   2.106      //       I > (upper_limit-offset)/scale
   2.107      //   )
   2.108 -    //
   2.109 -    // (upper_limit-offset) may overflow or underflow.
   2.110 -    // But it is fine since main loop will either have
   2.111 -    // less iterations or will be skipped in such case.
   2.112 -    *main_limit = adjust_limit(stride_con, scale, offset, upper_limit, *main_limit, pre_ctrl, false);
   2.113 +    *main_limit = adjust_limit(is_positive_stride, scale, offset, upper_limit, *main_limit, pre_ctrl, false);
   2.114  
   2.115 -    // The underflow limit: low_limit <= scale*I+offset.
   2.116 -    // For pre-loop compute
   2.117 +    // The underflow limit: low_limit <= scale*I+offset
   2.118 +    // For the pre-loop limit compute:
   2.119      //   NOT(scale*I+offset >= low_limit)
   2.120      //   scale*I+offset < low_limit
   2.121      //   ( if (scale > 0) /* and stride > 0 */
   2.122 @@ -1596,40 +1609,13 @@
   2.123      //     else /* scale < 0 and stride < 0 */
   2.124      //       I > (low_limit-offset)/scale
   2.125      //   )
   2.126 +    *pre_limit = adjust_limit(!is_positive_stride, scale, offset, low_limit, *pre_limit, pre_ctrl, round);
   2.127 +  } else {
   2.128 +    // Negative stride*scale: the affine function is decreasing,
   2.129 +    // the pre-loop checks for overflow and the post-loop for underflow.
   2.130  
   2.131 -    if (low_limit->get_int() == -max_jint) {
   2.132 -      if (!RangeLimitCheck) return;
   2.133 -      // We need this guard when scale*pre_limit+offset >= limit
   2.134 -      // due to underflow. So we need execute pre-loop until
   2.135 -      // scale*I+offset >= min_int. But (min_int-offset) will
   2.136 -      // underflow when offset > 0 and X will be > original_limit
   2.137 -      // when stride > 0. To avoid it we replace positive offset with 0.
   2.138 -      //
   2.139 -      // Also (min_int+1 == -max_int) is used instead of min_int here
   2.140 -      // to avoid problem with scale == -1 (min_int/(-1) == min_int).
   2.141 -      Node* shift = _igvn.intcon(31);
   2.142 -      set_ctrl(shift, C->root());
   2.143 -      Node* sign = new (C) RShiftINode(offset, shift);
   2.144 -      register_new_node(sign, pre_ctrl);
   2.145 -      offset = new (C) AndINode(offset, sign);
   2.146 -      register_new_node(offset, pre_ctrl);
   2.147 -    } else {
   2.148 -      assert(low_limit->get_int() == 0, "wrong low limit for range check");
   2.149 -      // The only problem we have here when offset == min_int
   2.150 -      // since (0-min_int) == min_int. It may be fine for stride > 0
   2.151 -      // but for stride < 0 X will be < original_limit. To avoid it
   2.152 -      // max(pre_limit, original_limit) is used in do_range_check().
   2.153 -    }
   2.154 -    // Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
   2.155 -    *pre_limit = adjust_limit((-stride_con), scale, offset, low_limit, *pre_limit, pre_ctrl,
   2.156 -                              scale_con > 1 && stride_con > 0);
   2.157 -
   2.158 -  } else { // stride_con*scale_con < 0
   2.159 -    // For negative stride*scale pre-loop checks for overflow and
   2.160 -    // post-loop for underflow.
   2.161 -    //
   2.162      // The overflow limit: scale*I+offset < upper_limit
   2.163 -    // For pre-loop compute
   2.164 +    // For the pre-loop limit compute:
   2.165      //   NOT(scale*I+offset < upper_limit)
   2.166      //   scale*I+offset >= upper_limit
   2.167      //   scale*I+offset+1 > upper_limit
   2.168 @@ -1638,58 +1624,24 @@
   2.169      //     else /* scale > 0 and stride < 0 */
   2.170      //       I > (upper_limit-(offset+1))/scale
   2.171      //   )
   2.172 -    //
   2.173 -    // (upper_limit-offset-1) may underflow or overflow.
   2.174 -    // To avoid it min(pre_limit, original_limit) is used
   2.175 -    // in do_range_check() for stride > 0 and max() for < 0.
   2.176 -    Node *one  = _igvn.intcon(1);
   2.177 +    Node* one = _igvn.longcon(1);
   2.178      set_ctrl(one, C->root());
   2.179 +    Node* plus_one = new (C) AddLNode(offset, one);
   2.180 +    register_new_node( plus_one, pre_ctrl );
   2.181 +    *pre_limit = adjust_limit(!is_positive_stride, scale, plus_one, upper_limit, *pre_limit, pre_ctrl, round);
   2.182  
   2.183 -    Node *plus_one = new (C) AddINode(offset, one);
   2.184 -    register_new_node( plus_one, pre_ctrl );
   2.185 -    // Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
   2.186 -    *pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl,
   2.187 -                              scale_con < -1 && stride_con > 0);
   2.188 -
   2.189 -    if (low_limit->get_int() == -max_jint) {
   2.190 -      if (!RangeLimitCheck) return;
   2.191 -      // We need this guard when scale*main_limit+offset >= limit
   2.192 -      // due to underflow. So we need execute main-loop while
   2.193 -      // scale*I+offset+1 > min_int. But (min_int-offset-1) will
   2.194 -      // underflow when (offset+1) > 0 and X will be < main_limit
   2.195 -      // when scale < 0 (and stride > 0). To avoid it we replace
   2.196 -      // positive (offset+1) with 0.
   2.197 -      //
   2.198 -      // Also (min_int+1 == -max_int) is used instead of min_int here
   2.199 -      // to avoid problem with scale == -1 (min_int/(-1) == min_int).
   2.200 -      Node* shift = _igvn.intcon(31);
   2.201 -      set_ctrl(shift, C->root());
   2.202 -      Node* sign = new (C) RShiftINode(plus_one, shift);
   2.203 -      register_new_node(sign, pre_ctrl);
   2.204 -      plus_one = new (C) AndINode(plus_one, sign);
   2.205 -      register_new_node(plus_one, pre_ctrl);
   2.206 -    } else {
   2.207 -      assert(low_limit->get_int() == 0, "wrong low limit for range check");
   2.208 -      // The only problem we have here when offset == max_int
   2.209 -      // since (max_int+1) == min_int and (0-min_int) == min_int.
   2.210 -      // But it is fine since main loop will either have
   2.211 -      // less iterations or will be skipped in such case.
   2.212 -    }
   2.213 -    // The underflow limit: low_limit <= scale*I+offset.
   2.214 -    // For main-loop compute
   2.215 +    // The underflow limit: low_limit <= scale*I+offset
   2.216 +    // For the main-loop limit compute:
   2.217      //   scale*I+offset+1 > low_limit
   2.218      //   ( if (scale < 0) /* and stride > 0 */
   2.219      //       I < (low_limit-(offset+1))/scale
   2.220      //     else /* scale > 0 and stride < 0 */
   2.221      //       I > (low_limit-(offset+1))/scale
   2.222      //   )
   2.223 -
   2.224 -    *main_limit = adjust_limit(stride_con, scale, plus_one, low_limit, *main_limit, pre_ctrl,
   2.225 -                               false);
   2.226 +    *main_limit = adjust_limit(is_positive_stride, scale, plus_one, low_limit, *main_limit, pre_ctrl, false);
   2.227    }
   2.228  }
   2.229  
   2.230 -
   2.231  //------------------------------is_scaled_iv---------------------------------
   2.232  // Return true if exp is a constant times an induction var
   2.233  bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, int* p_scale) {
   2.234 @@ -1854,22 +1806,14 @@
   2.235    // Must know if its a count-up or count-down loop
   2.236  
   2.237    int stride_con = cl->stride_con();
   2.238 -  Node *zero = _igvn.intcon(0);
   2.239 -  Node *one  = _igvn.intcon(1);
   2.240 +  Node* zero = _igvn.longcon(0);
   2.241 +  Node* one  = _igvn.longcon(1);
   2.242    // Use symmetrical int range [-max_jint,max_jint]
   2.243 -  Node *mini = _igvn.intcon(-max_jint);
   2.244 +  Node* mini = _igvn.longcon(-max_jint);
   2.245    set_ctrl(zero, C->root());
   2.246    set_ctrl(one,  C->root());
   2.247    set_ctrl(mini, C->root());
   2.248  
   2.249 -  // Range checks that do not dominate the loop backedge (ie.
   2.250 -  // conditionally executed) can lengthen the pre loop limit beyond
   2.251 -  // the original loop limit. To prevent this, the pre limit is
   2.252 -  // (for stride > 0) MINed with the original loop limit (MAXed
   2.253 -  // stride < 0) when some range_check (rc) is conditionally
   2.254 -  // executed.
   2.255 -  bool conditional_rc = false;
   2.256 -
   2.257    // Check loop body for tests of trip-counter plus loop-invariant vs
   2.258    // loop-invariant.
   2.259    for( uint i = 0; i < loop->_body.size(); i++ ) {
   2.260 @@ -1948,15 +1892,20 @@
   2.261        // stride_con and scale_con can be negative which will flip about the
   2.262        // sense of the test.
   2.263  
   2.264 +      // Perform the limit computations in jlong to avoid overflow
   2.265 +      jlong lscale_con = scale_con;
   2.266 +      Node* int_offset = offset;
   2.267 +      offset = new (C) ConvI2LNode(offset);
   2.268 +      register_new_node(offset, pre_ctrl);
   2.269 +      Node* int_limit = limit;
   2.270 +      limit = new (C) ConvI2LNode(limit);
   2.271 +      register_new_node(limit, pre_ctrl);
   2.272 +
   2.273        // Adjust pre and main loop limits to guard the correct iteration set
   2.274        if( cmp->Opcode() == Op_CmpU ) {// Unsigned compare is really 2 tests
   2.275          if( b_test._test == BoolTest::lt ) { // Range checks always use lt
   2.276            // The underflow and overflow limits: 0 <= scale*I+offset < limit
   2.277 -          add_constraint( stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit );
   2.278 -          if (!conditional_rc) {
   2.279 -            // (0-offset)/scale could be outside of loop iterations range.
   2.280 -            conditional_rc = !loop->dominates_backedge(iff) || RangeLimitCheck;
   2.281 -          }
   2.282 +          add_constraint(stride_con, lscale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit);
   2.283          } else {
   2.284  #ifndef PRODUCT
   2.285            if( PrintOpto )
   2.286 @@ -1970,16 +1919,16 @@
   2.287            // Fall into GE case
   2.288          case BoolTest::ge:
   2.289            // Convert (I*scale+offset) >= Limit to (I*(-scale)+(-offset)) <= -Limit
   2.290 -          scale_con = -scale_con;
   2.291 -          offset = new (C) SubINode( zero, offset );
   2.292 +          lscale_con = -lscale_con;
   2.293 +          offset = new (C) SubLNode(zero, offset);
   2.294            register_new_node( offset, pre_ctrl );
   2.295 -          limit  = new (C) SubINode( zero, limit  );
   2.296 +          limit  = new (C) SubLNode(zero, limit);
   2.297            register_new_node( limit, pre_ctrl );
   2.298            // Fall into LE case
   2.299          case BoolTest::le:
   2.300            if (b_test._test != BoolTest::gt) {
   2.301              // Convert X <= Y to X < Y+1
   2.302 -            limit = new (C) AddINode( limit, one );
   2.303 +            limit = new (C) AddLNode(limit, one);
   2.304              register_new_node( limit, pre_ctrl );
   2.305            }
   2.306            // Fall into LT case
   2.307 @@ -1987,13 +1936,7 @@
   2.308            // The underflow and overflow limits: MIN_INT <= scale*I+offset < limit
   2.309            // Note: (MIN_INT+1 == -MAX_INT) is used instead of MIN_INT here
   2.310            // to avoid problem with scale == -1: MIN_INT/(-1) == MIN_INT.
   2.311 -          add_constraint( stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit );
   2.312 -          if (!conditional_rc) {
   2.313 -            // ((MIN_INT+1)-offset)/scale could be outside of loop iterations range.
   2.314 -            // Note: negative offset is replaced with 0 but (MIN_INT+1)/scale could
   2.315 -            // still be outside of loop range.
   2.316 -            conditional_rc = !loop->dominates_backedge(iff) || RangeLimitCheck;
   2.317 -          }
   2.318 +          add_constraint(stride_con, lscale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit);
   2.319            break;
   2.320          default:
   2.321  #ifndef PRODUCT
   2.322 @@ -2029,7 +1972,8 @@
   2.323    }
   2.324  
   2.325    // Update loop limits
   2.326 -  if (conditional_rc) {
   2.327 +  if (pre_limit != orig_limit) {
   2.328 +    // Computed pre-loop limit can be outside of loop iterations range.
   2.329      pre_limit = (stride_con > 0) ? (Node*)new (C) MinINode(pre_limit, orig_limit)
   2.330                                   : (Node*)new (C) MaxINode(pre_limit, orig_limit);
   2.331      register_new_node(pre_limit, pre_ctrl);
     3.1 --- a/src/share/vm/opto/loopnode.hpp	Wed Sep 23 16:26:20 2020 +0300
     3.2 +++ b/src/share/vm/opto/loopnode.hpp	Wed May 13 15:59:17 2020 +0200
     3.3 @@ -961,9 +961,9 @@
     3.4    // always holds true.  That is, either increase the number of iterations in
     3.5    // the pre-loop or the post-loop until the condition holds true in the main
     3.6    // loop.  Scale_con, offset and limit are all loop invariant.
     3.7 -  void add_constraint( int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit );
     3.8 +  void add_constraint(jlong stride_con, jlong scale_con, Node* offset, Node* low_limit, Node* upper_limit, Node* pre_ctrl, Node** pre_limit, Node** main_limit);
     3.9    // Helper function for add_constraint().
    3.10 -  Node* adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl, bool round_up);
    3.11 +  Node* adjust_limit(bool reduce, Node* scale, Node* offset, Node* rc_limit, Node* old_limit, Node* pre_ctrl, bool round);
    3.12  
    3.13    // Partially peel loop up through last_peel node.
    3.14    bool partial_peel( IdealLoopTree *loop, Node_List &old_new );

mercurial