1/*
2 * Copyright (c) 2013, 2018, 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::is_overflow(jlong val1, jlong val2) {
121 // x * { 0, 1 } will never overflow. Even for x = min_jlong
122 if (val1 == 0 || val2 == 0 || val1 == 1 || val2 == 1) {
123 return false;
124 }
125
126 // x * min_jlong for x not in { 0, 1 } overflows
127 // even -1 as -1 * min_jlong is an overflow
128 if (val1 == min_jlong || val2 == min_jlong) {
129 return true;
130 }
131
132 // if (x * y) / y == x there is no overflow
133 //
134 // the multiplication here is done as unsigned to avoid undefined behaviour which
135 // can be used by the compiler to assume that the check further down (result / val2 != val1)
136 // is always false and breaks the overflow check
137 julong v1 = (julong) val1;
138 julong v2 = (julong) val2;
139 julong tmp = v1 * v2;
140 jlong result = (jlong) tmp;
141
142 if (result / val2 != val1) {
143 return true;
144 }
145
146 return false;
147}
148
149bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const {
150 return AddHelper<OverflowAddINode>::can_overflow(t1, t2);
151}
152
153bool OverflowSubINode::can_overflow(const Type* t1, const Type* t2) const {
154 if (in(1) == in(2)) {
155 return false;
156 }
157 return SubHelper<OverflowSubINode>::can_overflow(t1, t2);
158}
159
160bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const {
161 return MulHelper<OverflowMulINode>::can_overflow(t1, t2);
162}
163
164bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const {
165 return AddHelper<OverflowAddLNode>::can_overflow(t1, t2);
166}
167
168bool OverflowSubLNode::can_overflow(const Type* t1, const Type* t2) const {
169 if (in(1) == in(2)) {
170 return false;
171 }
172 return SubHelper<OverflowSubLNode>::can_overflow(t1, t2);
173}
174
175bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const {
176 return MulHelper<OverflowMulLNode>::can_overflow(t1, t2);
177}
178
179const Type* OverflowNode::sub(const Type* t1, const Type* t2) const {
180 fatal("sub() should not be called for '%s'", NodeClassNames[this->Opcode()]);
181 return TypeInt::CC;
182}
183
184template <typename OverflowOp>
185struct IdealHelper {
186 typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong
187 typedef typename TypeClass::NativeType NativeType;
188
189 static Node* Ideal(const OverflowOp* node, PhaseGVN* phase, bool can_reshape) {
190 Node* arg1 = node->in(1);
191 Node* arg2 = node->in(2);
192 const Type* type1 = phase->type(arg1);
193 const Type* type2 = phase->type(arg2);
194
195 if (type1 == NULL || type2 == NULL) {
196 return NULL;
197 }
198
199 if (type1 != Type::TOP && type1->singleton() &&
200 type2 != Type::TOP && type2->singleton()) {
201 NativeType val1 = TypeClass::as_self(type1)->get_con();
202 NativeType val2 = TypeClass::as_self(type2)->get_con();
203 if (node->will_overflow(val1, val2) == false) {
204 Node* con_result = ConINode::make(0);
205 return con_result;
206 }
207 return NULL;
208 }
209 return NULL;
210 }
211
212 static const Type* Value(const OverflowOp* node, PhaseTransform* phase) {
213 const Type *t1 = phase->type( node->in(1) );
214 const Type *t2 = phase->type( node->in(2) );
215 if( t1 == Type::TOP ) return Type::TOP;
216 if( t2 == Type::TOP ) return Type::TOP;
217
218 const TypeClass* i1 = TypeClass::as_self(t1);
219 const TypeClass* i2 = TypeClass::as_self(t2);
220
221 if (i1 == NULL || i2 == NULL) {
222 return TypeInt::CC;
223 }
224
225 if (t1->singleton() && t2->singleton()) {
226 NativeType val1 = i1->get_con();
227 NativeType val2 = i2->get_con();
228 if (node->will_overflow(val1, val2)) {
229 return TypeInt::CC;
230 }
231 return TypeInt::ZERO;
232 } else if (i1 != TypeClass::TYPE_DOMAIN && i2 != TypeClass::TYPE_DOMAIN) {
233 if (node->will_overflow(i1->_lo, i2->_lo)) {
234 return TypeInt::CC;
235 } else if (node->will_overflow(i1->_lo, i2->_hi)) {
236 return TypeInt::CC;
237 } else if (node->will_overflow(i1->_hi, i2->_lo)) {
238 return TypeInt::CC;
239 } else if (node->will_overflow(i1->_hi, i2->_hi)) {
240 return TypeInt::CC;
241 }
242 return TypeInt::ZERO;
243 }
244
245 if (!node->can_overflow(t1, t2)) {
246 return TypeInt::ZERO;
247 }
248 return TypeInt::CC;
249 }
250};
251
252Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) {
253 return IdealHelper<OverflowINode>::Ideal(this, phase, can_reshape);
254}
255
256Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
257 return IdealHelper<OverflowLNode>::Ideal(this, phase, can_reshape);
258}
259
260const Type* OverflowINode::Value(PhaseGVN* phase) const {
261 return IdealHelper<OverflowINode>::Value(this, phase);
262}
263
264const Type* OverflowLNode::Value(PhaseGVN* phase) const {
265 return IdealHelper<OverflowLNode>::Value(this, phase);
266}
267
268