|
1 | 1 | /*
|
2 |
| - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
@@ -941,6 +941,14 @@ static bool can_overflow(const TypeInt* t, jint c) {
|
941 | 941 | (c > 0 && (java_add(t_hi, c) < t_hi)));
|
942 | 942 | }
|
943 | 943 |
|
| 944 | +// Check if addition of a long with type 't' and a constant 'c' can overflow. |
| 945 | +static bool can_overflow(const TypeLong* t, jlong c) { |
| 946 | + jlong t_lo = t->_lo; |
| 947 | + jlong t_hi = t->_hi; |
| 948 | + return ((c < 0 && (java_add(t_lo, c) > t_lo)) || |
| 949 | + (c > 0 && (java_add(t_hi, c) < t_hi))); |
| 950 | +} |
| 951 | + |
944 | 952 | //=============================================================================
|
945 | 953 | //------------------------------Idealize---------------------------------------
|
946 | 954 | // MINs show up in range-check loop limit calculations. Look for
|
@@ -1062,6 +1070,31 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const {
|
1062 | 1070 | //
|
1063 | 1071 | // Note: we assume that SubL was already replaced by an AddL, and that the stride
|
1064 | 1072 | // has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride).
|
| 1073 | +// |
| 1074 | +// Proof MaxL collapsed version equivalent to original (MinL version similar): |
| 1075 | +// is_sub_con ensures that con1, con2 ∈ [min_int, 0[ |
| 1076 | +// |
| 1077 | +// Original: |
| 1078 | +// - AddL2 underflow => x + con2 ∈ ]max_long - min_int, max_long], ALWAYS BAILOUT as x + con1 + con2 surely fails can_overflow (*) |
| 1079 | +// - AddL2 no underflow => x + con2 ∈ [min_long, max_long] |
| 1080 | +// - MaxL2 clamp => min_int |
| 1081 | +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since min_int + con1 ∈ [2 * min_int, min_int] always > min_long |
| 1082 | +// - AddL1 no underflow => min_int + con1 ∈ [2 * min_int, min_int] |
| 1083 | +// - MaxL1 clamp => min_int (RESULT 1) |
| 1084 | +// - MaxL1 no clamp: NOT POSSIBLE: min_int + con1 ∈ [2 * min_int, min_int] always <= min_int, so clamp always taken |
| 1085 | +// - MaxL2 no clamp => x + con2 ∈ [min_int, max_long] |
| 1086 | +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since x + con2 + con1 ∈ [2 * min_int, max_long] always > min_long |
| 1087 | +// - AddL1 no underflow => x + con2 + con1 ∈ [2 * min_int, max_long] |
| 1088 | +// - MaxL1 clamp => min_int (RESULT 2) |
| 1089 | +// - MaxL1 no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) |
| 1090 | +// |
| 1091 | +// Collapsed: |
| 1092 | +// - AddL2 (cannot underflow) => con2 + con1 ∈ [2 * min_int, 0] |
| 1093 | +// - AddL1 underflow: NOT POSSIBLE: would have bailed out at can_overflow (*) |
| 1094 | +// - AddL1 no underflow => x + con2 + con1 ∈ [min_long, max_long] |
| 1095 | +// - MaxL clamp => min_int (RESULT 1 and RESULT 2) |
| 1096 | +// - MaxL no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) |
| 1097 | +// |
1065 | 1098 | static bool is_clamp(PhaseGVN* phase, Node* n, Node* c) {
|
1066 | 1099 | // Check that the two clamps have the correct values.
|
1067 | 1100 | jlong clamp = (n->Opcode() == Op_MaxL) ? min_jint : max_jint;
|
@@ -1093,6 +1126,10 @@ Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
|
1093 | 1126 | Node* x = add2->in(1);
|
1094 | 1127 | Node* con2 = add2->in(2);
|
1095 | 1128 | if (is_sub_con(phase, n, con2)) {
|
| 1129 | + // Collapsed graph not equivalent if potential over/underflow -> bailing out (*) |
| 1130 | + if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) { |
| 1131 | + return NULL; |
| 1132 | + } |
1096 | 1133 | Node* new_con = phase->transform(new AddLNode(con1, con2));
|
1097 | 1134 | Node* new_sub = phase->transform(new AddLNode(x, new_con));
|
1098 | 1135 | n->set_req_X(1, new_sub, phase);
|
|
0 commit comments