mathexactnode.cpp revision 9056:dc9930a04ab0
1/*
2 * Copyright (c) 2013, 2014, 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 */
24
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"
33
34template <typename OverflowOp>
35class AddHelper {
36public:
37  typedef typename OverflowOp::TypeClass TypeClass;
38  typedef typename TypeClass::NativeType NativeType;
39
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  }
48
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};
56
57template <typename OverflowOp>
58class SubHelper {
59public:
60  typedef typename OverflowOp::TypeClass TypeClass;
61  typedef typename TypeClass::NativeType NativeType;
62
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  }
72
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};
80
81template <typename OverflowOp>
82class MulHelper {
83public:
84  typedef typename OverflowOp::TypeClass TypeClass;
85
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};
95
96bool OverflowAddINode::will_overflow(jint v1, jint v2) const {
97  return AddHelper<OverflowAddINode>::will_overflow(v1, v2);
98}
99
100bool OverflowSubINode::will_overflow(jint v1, jint v2) const {
101  return SubHelper<OverflowSubINode>::will_overflow(v1, v2);
102}
103
104bool 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}
111
112bool OverflowAddLNode::will_overflow(jlong v1, jlong v2) const {
113  return AddHelper<OverflowAddLNode>::will_overflow(v1, v2);
114}
115
116bool OverflowSubLNode::will_overflow(jlong v1, jlong v2) const {
117  return SubHelper<OverflowSubLNode>::will_overflow(v1, v2);
118}
119
120bool 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);
124
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    }
135
136    return overflow;
137}
138
139bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const {
140  return AddHelper<OverflowAddINode>::can_overflow(t1, t2);
141}
142
143bool 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}
149
150bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const {
151  return MulHelper<OverflowMulINode>::can_overflow(t1, t2);
152}
153
154bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const {
155  return AddHelper<OverflowAddLNode>::can_overflow(t1, t2);
156}
157
158bool 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}
164
165bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const {
166  return MulHelper<OverflowMulLNode>::can_overflow(t1, t2);
167}
168
169const Type* OverflowNode::sub(const Type* t1, const Type* t2) const {
170  fatal("sub() should not be called for '%s'", NodeClassNames[this->Opcode()]);
171  return TypeInt::CC;
172}
173
174template <typename OverflowOp>
175struct IdealHelper {
176  typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong
177  typedef typename TypeClass::NativeType NativeType;
178
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);
184
185    if (type1 == NULL || type2 == NULL) {
186      return NULL;
187    }
188
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(0);
195        return con_result;
196      }
197      return NULL;
198    }
199    return NULL;
200  }
201
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;
207
208    const TypeClass* i1 = TypeClass::as_self(t1);
209    const TypeClass* i2 = TypeClass::as_self(t2);
210
211    if (i1 == NULL || i2 == NULL) {
212      return TypeInt::CC;
213    }
214
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    }
234
235    if (!node->can_overflow(t1, t2)) {
236      return TypeInt::ZERO;
237    }
238    return TypeInt::CC;
239  }
240};
241
242Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) {
243  return IdealHelper<OverflowINode>::Ideal(this, phase, can_reshape);
244}
245
246Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
247  return IdealHelper<OverflowLNode>::Ideal(this, phase, can_reshape);
248}
249
250const Type* OverflowINode::Value(PhaseTransform* phase) const {
251  return IdealHelper<OverflowINode>::Value(this, phase);
252}
253
254const Type* OverflowLNode::Value(PhaseTransform* phase) const {
255  return IdealHelper<OverflowLNode>::Value(this, phase);
256}
257
258