src/share/vm/opto/mathexactnode.cpp

Fri, 11 Jul 2014 19:51:36 -0400

author
drchase
date
Fri, 11 Jul 2014 19:51:36 -0400
changeset 7161
fc2c88ea11a9
parent 6375
085b304a1cc5
child 6876
710a3c8b516e
permissions
-rw-r--r--

8036588: VerifyFieldClosure fails instanceKlass:3133
Summary: Changed deopt live-pointer test to use returns-object instead of live-and-returns-object
Reviewed-by: iveresov, kvn, jrose

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

mercurial