|
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 |
@@ -1052,6 +1060,31 @@ Node *MinINode::Ideal(PhaseGVN *phase, bool can_reshape) { |
1052 | 1060 | // |
1053 | 1061 | // Note: we assume that SubL was already replaced by an AddL, and that the stride |
1054 | 1062 | // has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride). |
| 1063 | +// |
| 1064 | +// Proof MaxL collapsed version equivalent to original (MinL version similar): |
| 1065 | +// is_sub_con ensures that con1, con2 ∈ [min_int, 0[ |
| 1066 | +// |
| 1067 | +// Original: |
| 1068 | +// - AddL2 underflow => x + con2 ∈ ]max_long - min_int, max_long], ALWAYS BAILOUT as x + con1 + con2 surely fails can_overflow (*) |
| 1069 | +// - AddL2 no underflow => x + con2 ∈ [min_long, max_long] |
| 1070 | +// - MaxL2 clamp => min_int |
| 1071 | +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since min_int + con1 ∈ [2 * min_int, min_int] always > min_long |
| 1072 | +// - AddL1 no underflow => min_int + con1 ∈ [2 * min_int, min_int] |
| 1073 | +// - MaxL1 clamp => min_int (RESULT 1) |
| 1074 | +// - MaxL1 no clamp: NOT POSSIBLE: min_int + con1 ∈ [2 * min_int, min_int] always <= min_int, so clamp always taken |
| 1075 | +// - MaxL2 no clamp => x + con2 ∈ [min_int, max_long] |
| 1076 | +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since x + con2 + con1 ∈ [2 * min_int, max_long] always > min_long |
| 1077 | +// - AddL1 no underflow => x + con2 + con1 ∈ [2 * min_int, max_long] |
| 1078 | +// - MaxL1 clamp => min_int (RESULT 2) |
| 1079 | +// - MaxL1 no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) |
| 1080 | +// |
| 1081 | +// Collapsed: |
| 1082 | +// - AddL2 (cannot underflow) => con2 + con1 ∈ [2 * min_int, 0] |
| 1083 | +// - AddL1 underflow: NOT POSSIBLE: would have bailed out at can_overflow (*) |
| 1084 | +// - AddL1 no underflow => x + con2 + con1 ∈ [min_long, max_long] |
| 1085 | +// - MaxL clamp => min_int (RESULT 1 and RESULT 2) |
| 1086 | +// - MaxL no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) |
| 1087 | +// |
1055 | 1088 | static bool is_clamp(PhaseGVN* phase, Node* n, Node* c) { |
1056 | 1089 | // Check that the two clamps have the correct values. |
1057 | 1090 | jlong clamp = (n->Opcode() == Op_MaxL) ? min_jint : max_jint; |
@@ -1083,6 +1116,10 @@ Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) { |
1083 | 1116 | Node* x = add2->in(1); |
1084 | 1117 | Node* con2 = add2->in(2); |
1085 | 1118 | if (is_sub_con(phase, n, con2)) { |
| 1119 | + // Collapsed graph not equivalent if potential over/underflow -> bailing out (*) |
| 1120 | + if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) { |
| 1121 | + return NULL; |
| 1122 | + } |
1086 | 1123 | Node* new_con = phase->transform(new (phase->C) AddLNode(con1, con2)); |
1087 | 1124 | Node* new_sub = phase->transform(new (phase->C) AddLNode(x, new_con)); |
1088 | 1125 | n->set_req_X(1, new_sub, phase); |
|
0 commit comments