@@ -3590,20 +3590,39 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) {
35903590 _igvn.register_new_node_with_optimizer (N);
35913591 _phase->set_ctrl (N, pre_ctrl);
35923592
3593+ // The computation of the new pre-loop limit could overflow or underflow the int range. This is problematic in
3594+ // combination with Range Check Elimination (RCE), which determines a "safe" range where a RangeCheck will always
3595+ // succeed. RCE adjusts the pre-loop limit such that we only enter the main-loop once we have reached the "safe"
3596+ // range, and adjusts the main-loop limit so that we exit the main-loop before we leave the "safe" range. After RCE,
3597+ // the range of the main-loop can only be safely narrowed, and should never be widened. Hence, the pre-loop limit
3598+ // can only be increased (for stride > 0), but an add overflow might decrease it, or decreased (for stride < 0), but
3599+ // a sub underflow might increase it. To prevent that, we perform the Sub / Add and Max / Min with long operations.
3600+ lim0 = new ConvI2LNode (lim0);
3601+ N = new ConvI2LNode (N);
3602+ orig_limit = new ConvI2LNode (orig_limit);
3603+ _igvn.register_new_node_with_optimizer (lim0);
3604+ _igvn.register_new_node_with_optimizer (N);
3605+ _igvn.register_new_node_with_optimizer (orig_limit);
3606+
35933607 // substitute back into (1), so that new limit
35943608 // lim = lim0 + N
35953609 Node* lim;
35963610 if (stride < 0 ) {
3597- lim = new SubINode (lim0, N);
3611+ lim = new SubLNode (lim0, N);
35983612 } else {
3599- lim = new AddINode (lim0, N);
3613+ lim = new AddLNode (lim0, N);
36003614 }
36013615 _igvn.register_new_node_with_optimizer (lim);
36023616 _phase->set_ctrl (lim, pre_ctrl);
36033617 Node* constrained =
3604- (stride > 0 ) ? (Node*) new MinINode ( lim, orig_limit)
3605- : (Node*) new MaxINode ( lim, orig_limit);
3618+ (stride > 0 ) ? (Node*) new MinLNode (_phase-> C , lim, orig_limit)
3619+ : (Node*) new MaxLNode (_phase-> C , lim, orig_limit);
36063620 _igvn.register_new_node_with_optimizer (constrained);
3621+
3622+ // We know that the result is in the int range, there is never truncation
3623+ constrained = new ConvL2INode (constrained);
3624+ _igvn.register_new_node_with_optimizer (constrained);
3625+
36073626 _phase->set_ctrl (constrained, pre_ctrl);
36083627 _igvn.replace_input_of (pre_opaq, 1 , constrained);
36093628}
0 commit comments