Skip to content

Commit 38afa4d

Browse files
dafedafeeme64
authored andcommitted
8338430: Improve compiler transformations
Co-authored-by: Emanuel Peter <[email protected]> Reviewed-by: ahgross, rhalade, thartmann, epeter
1 parent e91b3f0 commit 38afa4d

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/hotspot/share/opto/addnode.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
//
13661399
static 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

Comments
 (0)