@@ -1179,6 +1179,14 @@ static bool can_overflow(const TypeInt* t, jint c) {
11791179 (c > 0 && (java_add (t_hi, c) < t_hi)));
11801180}
11811181
1182+ // Check if addition of a long with type 't' and a constant 'c' can overflow.
1183+ static bool can_overflow (const TypeLong* t, jlong c) {
1184+ jlong t_lo = t->_lo ;
1185+ jlong t_hi = t->_hi ;
1186+ return ((c < 0 && (java_add (t_lo, c) > t_lo)) ||
1187+ (c > 0 && (java_add (t_hi, c) < t_hi)));
1188+ }
1189+
11821190// Let <x, x_off> = x_operands and <y, y_off> = y_operands.
11831191// If x == y and neither add(x, x_off) nor add(y, y_off) overflow, return
11841192// add(x, op(x_off, y_off)). Otherwise, return nullptr.
@@ -1363,6 +1371,31 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const {
13631371//
13641372// Note: we assume that SubL was already replaced by an AddL, and that the stride
13651373// has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride).
1374+ //
1375+ // Proof MaxL collapsed version equivalent to original (MinL version similar):
1376+ // is_sub_con ensures that con1, con2 ∈ [min_int, 0[
1377+ //
1378+ // Original:
1379+ // - AddL2 underflow => x + con2 ∈ ]max_long - min_int, max_long], ALWAYS BAILOUT as x + con1 + con2 surely fails can_overflow (*)
1380+ // - AddL2 no underflow => x + con2 ∈ [min_long, max_long]
1381+ // - MaxL2 clamp => min_int
1382+ // - AddL1 underflow: NOT POSSIBLE: cannot underflow since min_int + con1 ∈ [2 * min_int, min_int] always > min_long
1383+ // - AddL1 no underflow => min_int + con1 ∈ [2 * min_int, min_int]
1384+ // - MaxL1 clamp => min_int (RESULT 1)
1385+ // - MaxL1 no clamp: NOT POSSIBLE: min_int + con1 ∈ [2 * min_int, min_int] always <= min_int, so clamp always taken
1386+ // - MaxL2 no clamp => x + con2 ∈ [min_int, max_long]
1387+ // - AddL1 underflow: NOT POSSIBLE: cannot underflow since x + con2 + con1 ∈ [2 * min_int, max_long] always > min_long
1388+ // - AddL1 no underflow => x + con2 + con1 ∈ [2 * min_int, max_long]
1389+ // - MaxL1 clamp => min_int (RESULT 2)
1390+ // - MaxL1 no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3)
1391+ //
1392+ // Collapsed:
1393+ // - AddL2 (cannot underflow) => con2 + con1 ∈ [2 * min_int, 0]
1394+ // - AddL1 underflow: NOT POSSIBLE: would have bailed out at can_overflow (*)
1395+ // - AddL1 no underflow => x + con2 + con1 ∈ [min_long, max_long]
1396+ // - MaxL clamp => min_int (RESULT 1 and RESULT 2)
1397+ // - MaxL no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3)
1398+ //
13661399static Node* fold_subI_no_underflow_pattern (Node* n, PhaseGVN* phase) {
13671400 assert (n->Opcode () == Op_MaxL || n->Opcode () == Op_MinL, " sanity" );
13681401 // Check that the two clamps have the correct values.
@@ -1392,6 +1425,10 @@ static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
13921425 Node* x = add2->in (1 );
13931426 Node* con2 = add2->in (2 );
13941427 if (is_sub_con (con2)) {
1428+ // Collapsed graph not equivalent if potential over/underflow -> bailing out (*)
1429+ if (can_overflow (phase->type (x)->is_long (), con1->get_long () + con2->get_long ())) {
1430+ return nullptr ;
1431+ }
13951432 Node* new_con = phase->transform (new AddLNode (con1, con2));
13961433 Node* new_sub = phase->transform (new AddLNode (x, new_con));
13971434 n->set_req_X (1 , new_sub, phase);
0 commit comments