Mon, 25 May 2020 14:24:27 +0800
8244407: JVM crashes after transformation in C2 IdealLoopTree::split_fall_in
Reviewed-by: thartmann, kvn, andrew
Contributed-by: zhouyong44@huawei.com
rbackman@5791 | 1 | /* |
rbackman@5791 | 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
rbackman@5791 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
rbackman@5791 | 4 | * |
rbackman@5791 | 5 | * This code is free software; you can redistribute it and/or modify it |
rbackman@5791 | 6 | * under the terms of the GNU General Public License version 2 only, as |
rbackman@5791 | 7 | * published by the Free Software Foundation. |
rbackman@5791 | 8 | * |
rbackman@5791 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
rbackman@5791 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
rbackman@5791 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
rbackman@5791 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
rbackman@5791 | 13 | * accompanied this code). |
rbackman@5791 | 14 | * |
rbackman@5791 | 15 | * You should have received a copy of the GNU General Public License version |
rbackman@5791 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
rbackman@5791 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
rbackman@5791 | 18 | * |
rbackman@5791 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
rbackman@5791 | 20 | * or visit www.oracle.com if you need additional information or have any |
rbackman@5791 | 21 | * questions. |
rbackman@5791 | 22 | * |
rbackman@5791 | 23 | */ |
rbackman@5791 | 24 | |
rbackman@5791 | 25 | #include "precompiled.hpp" |
rbackman@5791 | 26 | #include "memory/allocation.inline.hpp" |
rbackman@5791 | 27 | #include "opto/addnode.hpp" |
rbackman@5927 | 28 | #include "opto/cfgnode.hpp" |
rbackman@5791 | 29 | #include "opto/machnode.hpp" |
rbackman@5927 | 30 | #include "opto/matcher.hpp" |
rbackman@5791 | 31 | #include "opto/mathexactnode.hpp" |
rbackman@5791 | 32 | #include "opto/subnode.hpp" |
rbackman@5791 | 33 | |
rbackman@6375 | 34 | template <typename OverflowOp> |
rbackman@6375 | 35 | class AddHelper { |
rbackman@6375 | 36 | public: |
rbackman@6375 | 37 | typedef typename OverflowOp::TypeClass TypeClass; |
rbackman@6375 | 38 | typedef typename TypeClass::NativeType NativeType; |
rbackman@6375 | 39 | |
rbackman@6375 | 40 | static bool will_overflow(NativeType value1, NativeType value2) { |
rbackman@6375 | 41 | NativeType result = value1 + value2; |
rbackman@6375 | 42 | // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result |
rbackman@6375 | 43 | if (((value1 ^ result) & (value2 ^ result)) >= 0) { |
rbackman@6375 | 44 | return false; |
rbackman@6375 | 45 | } |
rbackman@6375 | 46 | return true; |
rbackman@6375 | 47 | } |
rbackman@6375 | 48 | |
rbackman@6375 | 49 | static bool can_overflow(const Type* type1, const Type* type2) { |
rbackman@6375 | 50 | if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { |
rbackman@6375 | 51 | return false; |
rbackman@6375 | 52 | } |
rbackman@6375 | 53 | return true; |
rbackman@6375 | 54 | } |
rbackman@6375 | 55 | }; |
rbackman@6375 | 56 | |
rbackman@6375 | 57 | template <typename OverflowOp> |
rbackman@6375 | 58 | class SubHelper { |
rbackman@6375 | 59 | public: |
rbackman@6375 | 60 | typedef typename OverflowOp::TypeClass TypeClass; |
rbackman@6375 | 61 | typedef typename TypeClass::NativeType NativeType; |
rbackman@6375 | 62 | |
rbackman@6375 | 63 | static bool will_overflow(NativeType value1, NativeType value2) { |
rbackman@6375 | 64 | NativeType result = value1 - value2; |
rbackman@6375 | 65 | // hacker's delight 2-12 overflow iff the arguments have different signs and |
rbackman@6375 | 66 | // the sign of the result is different than the sign of arg1 |
rbackman@6375 | 67 | if (((value1 ^ value2) & (value1 ^ result)) >= 0) { |
rbackman@6375 | 68 | return false; |
rbackman@6375 | 69 | } |
rbackman@6375 | 70 | return true; |
rbackman@6375 | 71 | } |
rbackman@6375 | 72 | |
rbackman@6375 | 73 | static bool can_overflow(const Type* type1, const Type* type2) { |
rbackman@6375 | 74 | if (type2 == TypeClass::ZERO) { |
rbackman@6375 | 75 | return false; |
rbackman@6375 | 76 | } |
rbackman@6375 | 77 | return true; |
rbackman@6375 | 78 | } |
rbackman@6375 | 79 | }; |
rbackman@6375 | 80 | |
rbackman@6375 | 81 | template <typename OverflowOp> |
rbackman@6375 | 82 | class MulHelper { |
rbackman@6375 | 83 | public: |
rbackman@6375 | 84 | typedef typename OverflowOp::TypeClass TypeClass; |
rbackman@6375 | 85 | |
rbackman@6375 | 86 | static bool can_overflow(const Type* type1, const Type* type2) { |
rbackman@6375 | 87 | if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { |
rbackman@6375 | 88 | return false; |
rbackman@6375 | 89 | } else if (type1 == TypeClass::ONE || type2 == TypeClass::ONE) { |
rbackman@6375 | 90 | return false; |
rbackman@6375 | 91 | } |
rbackman@6375 | 92 | return true; |
rbackman@6375 | 93 | } |
rbackman@6375 | 94 | }; |
rbackman@6375 | 95 | |
rbackman@6375 | 96 | bool OverflowAddINode::will_overflow(jint v1, jint v2) const { |
rbackman@6375 | 97 | return AddHelper<OverflowAddINode>::will_overflow(v1, v2); |
rbackman@5997 | 98 | } |
rbackman@5997 | 99 | |
rbackman@6375 | 100 | bool OverflowSubINode::will_overflow(jint v1, jint v2) const { |
rbackman@6375 | 101 | return SubHelper<OverflowSubINode>::will_overflow(v1, v2); |
rbackman@5791 | 102 | } |
rbackman@5791 | 103 | |
rbackman@6375 | 104 | bool OverflowMulINode::will_overflow(jint v1, jint v2) const { |
rbackman@6375 | 105 | jlong result = (jlong) v1 * (jlong) v2; |
rbackman@6375 | 106 | if ((jint) result == result) { |
rbackman@6375 | 107 | return false; |
rbackman@6375 | 108 | } |
rbackman@6375 | 109 | return true; |
rbackman@5927 | 110 | } |
rbackman@5927 | 111 | |
rbackman@6375 | 112 | bool OverflowAddLNode::will_overflow(jlong v1, jlong v2) const { |
rbackman@6375 | 113 | return AddHelper<OverflowAddLNode>::will_overflow(v1, v2); |
rbackman@5927 | 114 | } |
rbackman@5927 | 115 | |
rbackman@6375 | 116 | bool OverflowSubLNode::will_overflow(jlong v1, jlong v2) const { |
rbackman@6375 | 117 | return SubHelper<OverflowSubLNode>::will_overflow(v1, v2); |
rbackman@5927 | 118 | } |
rbackman@5927 | 119 | |
rbackman@6375 | 120 | bool OverflowMulLNode::will_overflow(jlong val1, jlong val2) const { |
rbackman@5997 | 121 | jlong result = val1 * val2; |
rbackman@5997 | 122 | jlong ax = (val1 < 0 ? -val1 : val1); |
rbackman@5997 | 123 | jlong ay = (val2 < 0 ? -val2 : val2); |
rbackman@5997 | 124 | |
rbackman@5997 | 125 | bool overflow = false; |
rbackman@5997 | 126 | if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) { |
rbackman@5997 | 127 | // potential overflow if any bit in upper 32 bits are set |
rbackman@5997 | 128 | if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) { |
rbackman@5997 | 129 | // -1 * Long.MIN_VALUE will overflow |
rbackman@5997 | 130 | overflow = true; |
rbackman@5997 | 131 | } else if (val2 != 0 && (result / val2 != val1)) { |
rbackman@5997 | 132 | overflow = true; |
rbackman@5997 | 133 | } |
rbackman@5997 | 134 | } |
rbackman@5997 | 135 | |
rbackman@6375 | 136 | return overflow; |
rbackman@6375 | 137 | } |
rbackman@6375 | 138 | |
rbackman@6375 | 139 | bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 140 | return AddHelper<OverflowAddINode>::can_overflow(t1, t2); |
rbackman@6375 | 141 | } |
rbackman@6375 | 142 | |
rbackman@6375 | 143 | bool OverflowSubINode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 144 | if (in(1) == in(2)) { |
rbackman@6375 | 145 | return false; |
rbackman@6375 | 146 | } |
rbackman@6375 | 147 | return SubHelper<OverflowSubINode>::can_overflow(t1, t2); |
rbackman@6375 | 148 | } |
rbackman@6375 | 149 | |
rbackman@6375 | 150 | bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 151 | return MulHelper<OverflowMulINode>::can_overflow(t1, t2); |
rbackman@6375 | 152 | } |
rbackman@6375 | 153 | |
rbackman@6375 | 154 | bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 155 | return AddHelper<OverflowAddLNode>::can_overflow(t1, t2); |
rbackman@6375 | 156 | } |
rbackman@6375 | 157 | |
rbackman@6375 | 158 | bool OverflowSubLNode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 159 | if (in(1) == in(2)) { |
rbackman@6375 | 160 | return false; |
rbackman@6375 | 161 | } |
rbackman@6375 | 162 | return SubHelper<OverflowSubLNode>::can_overflow(t1, t2); |
rbackman@6375 | 163 | } |
rbackman@6375 | 164 | |
rbackman@6375 | 165 | bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const { |
rbackman@6375 | 166 | return MulHelper<OverflowMulLNode>::can_overflow(t1, t2); |
rbackman@6375 | 167 | } |
rbackman@6375 | 168 | |
rbackman@6375 | 169 | const Type* OverflowNode::sub(const Type* t1, const Type* t2) const { |
rbackman@6375 | 170 | fatal(err_msg_res("sub() should not be called for '%s'", NodeClassNames[this->Opcode()])); |
rbackman@6375 | 171 | return TypeInt::CC; |
rbackman@6375 | 172 | } |
rbackman@6375 | 173 | |
rbackman@6375 | 174 | template <typename OverflowOp> |
rbackman@6375 | 175 | struct IdealHelper { |
rbackman@6375 | 176 | typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong |
rbackman@6375 | 177 | typedef typename TypeClass::NativeType NativeType; |
rbackman@6375 | 178 | |
rbackman@6375 | 179 | static Node* Ideal(const OverflowOp* node, PhaseGVN* phase, bool can_reshape) { |
rbackman@6375 | 180 | Node* arg1 = node->in(1); |
rbackman@6375 | 181 | Node* arg2 = node->in(2); |
rbackman@6375 | 182 | const Type* type1 = phase->type(arg1); |
rbackman@6375 | 183 | const Type* type2 = phase->type(arg2); |
rbackman@6375 | 184 | |
rbackman@6375 | 185 | if (type1 == NULL || type2 == NULL) { |
rbackman@6375 | 186 | return NULL; |
rbackman@5997 | 187 | } |
rbackman@6375 | 188 | |
rbackman@6375 | 189 | if (type1 != Type::TOP && type1->singleton() && |
rbackman@6375 | 190 | type2 != Type::TOP && type2->singleton()) { |
rbackman@6375 | 191 | NativeType val1 = TypeClass::as_self(type1)->get_con(); |
rbackman@6375 | 192 | NativeType val2 = TypeClass::as_self(type2)->get_con(); |
rbackman@6375 | 193 | if (node->will_overflow(val1, val2) == false) { |
rbackman@6375 | 194 | Node* con_result = ConINode::make(phase->C, 0); |
rbackman@6375 | 195 | return con_result; |
rbackman@6375 | 196 | } |
rbackman@6375 | 197 | return NULL; |
rbackman@6375 | 198 | } |
rbackman@6375 | 199 | return NULL; |
rbackman@5997 | 200 | } |
rbackman@5997 | 201 | |
rbackman@6375 | 202 | static const Type* Value(const OverflowOp* node, PhaseTransform* phase) { |
rbackman@6375 | 203 | const Type *t1 = phase->type( node->in(1) ); |
rbackman@6375 | 204 | const Type *t2 = phase->type( node->in(2) ); |
rbackman@6375 | 205 | if( t1 == Type::TOP ) return Type::TOP; |
rbackman@6375 | 206 | if( t2 == Type::TOP ) return Type::TOP; |
rbackman@6375 | 207 | |
rbackman@6375 | 208 | const TypeClass* i1 = TypeClass::as_self(t1); |
rbackman@6375 | 209 | const TypeClass* i2 = TypeClass::as_self(t2); |
rbackman@6375 | 210 | |
rbackman@6375 | 211 | if (i1 == NULL || i2 == NULL) { |
rbackman@6375 | 212 | return TypeInt::CC; |
rbackman@6375 | 213 | } |
rbackman@6375 | 214 | |
rbackman@6375 | 215 | if (t1->singleton() && t2->singleton()) { |
rbackman@6375 | 216 | NativeType val1 = i1->get_con(); |
rbackman@6375 | 217 | NativeType val2 = i2->get_con(); |
rbackman@6375 | 218 | if (node->will_overflow(val1, val2)) { |
rbackman@6375 | 219 | return TypeInt::CC; |
rbackman@6375 | 220 | } |
rbackman@6375 | 221 | return TypeInt::ZERO; |
rbackman@6375 | 222 | } else if (i1 != TypeClass::TYPE_DOMAIN && i2 != TypeClass::TYPE_DOMAIN) { |
rbackman@6375 | 223 | if (node->will_overflow(i1->_lo, i2->_lo)) { |
rbackman@6375 | 224 | return TypeInt::CC; |
rbackman@6375 | 225 | } else if (node->will_overflow(i1->_lo, i2->_hi)) { |
rbackman@6375 | 226 | return TypeInt::CC; |
rbackman@6375 | 227 | } else if (node->will_overflow(i1->_hi, i2->_lo)) { |
rbackman@6375 | 228 | return TypeInt::CC; |
rbackman@6375 | 229 | } else if (node->will_overflow(i1->_hi, i2->_hi)) { |
rbackman@6375 | 230 | return TypeInt::CC; |
rbackman@6375 | 231 | } |
rbackman@6375 | 232 | return TypeInt::ZERO; |
rbackman@6375 | 233 | } |
rbackman@6375 | 234 | |
rbackman@6375 | 235 | if (!node->can_overflow(t1, t2)) { |
rbackman@6375 | 236 | return TypeInt::ZERO; |
rbackman@6375 | 237 | } |
rbackman@6375 | 238 | return TypeInt::CC; |
rbackman@5997 | 239 | } |
rbackman@6375 | 240 | }; |
rbackman@5997 | 241 | |
rbackman@6375 | 242 | Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) { |
rbackman@6375 | 243 | return IdealHelper<OverflowINode>::Ideal(this, phase, can_reshape); |
rbackman@5997 | 244 | } |
rbackman@5997 | 245 | |
rbackman@6375 | 246 | Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
rbackman@6375 | 247 | return IdealHelper<OverflowLNode>::Ideal(this, phase, can_reshape); |
rbackman@6375 | 248 | } |
rbackman@6375 | 249 | |
rbackman@6375 | 250 | const Type* OverflowINode::Value(PhaseTransform* phase) const { |
rbackman@6375 | 251 | return IdealHelper<OverflowINode>::Value(this, phase); |
rbackman@6375 | 252 | } |
rbackman@6375 | 253 | |
rbackman@6375 | 254 | const Type* OverflowLNode::Value(PhaseTransform* phase) const { |
rbackman@6375 | 255 | return IdealHelper<OverflowLNode>::Value(this, phase); |
rbackman@6375 | 256 | } |
rbackman@6375 | 257 |