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 
34 template <typename OverflowOp>
35 class AddHelper {
36 public:
37   typedef typename OverflowOp::TypeClass TypeClass;
38   typedef typename TypeClass::NativeType NativeType;
39 
will_overflow(NativeType value1,NativeType value2)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 
can_overflow(const Type * type1,const Type * type2)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 
57 template <typename OverflowOp>
58 class SubHelper {
59 public:
60   typedef typename OverflowOp::TypeClass TypeClass;
61   typedef typename TypeClass::NativeType NativeType;
62 
will_overflow(NativeType value1,NativeType value2)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 
can_overflow(const Type * type1,const Type * type2)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 
81 template <typename OverflowOp>
82 class MulHelper {
83 public:
84   typedef typename OverflowOp::TypeClass TypeClass;
85 
can_overflow(const Type * type1,const Type * type2)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 
will_overflow(jint v1,jint v2) const96 bool OverflowAddINode::will_overflow(jint v1, jint v2) const {
97   return AddHelper<OverflowAddINode>::will_overflow(v1, v2);
98 }
99 
will_overflow(jint v1,jint v2) const100 bool OverflowSubINode::will_overflow(jint v1, jint v2) const {
101   return SubHelper<OverflowSubINode>::will_overflow(v1, v2);
102 }
103 
will_overflow(jint v1,jint v2) const104 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 }
111 
will_overflow(jlong v1,jlong v2) const112 bool OverflowAddLNode::will_overflow(jlong v1, jlong v2) const {
113   return AddHelper<OverflowAddLNode>::will_overflow(v1, v2);
114 }
115 
will_overflow(jlong v1,jlong v2) const116 bool OverflowSubLNode::will_overflow(jlong v1, jlong v2) const {
117   return SubHelper<OverflowSubLNode>::will_overflow(v1, v2);
118 }
119 
is_overflow(jlong val1,jlong val2)120 bool 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 
can_overflow(const Type * t1,const Type * t2) const149 bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const {
150   return AddHelper<OverflowAddINode>::can_overflow(t1, t2);
151 }
152 
can_overflow(const Type * t1,const Type * t2) const153 bool 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 
can_overflow(const Type * t1,const Type * t2) const160 bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const {
161   return MulHelper<OverflowMulINode>::can_overflow(t1, t2);
162 }
163 
can_overflow(const Type * t1,const Type * t2) const164 bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const {
165   return AddHelper<OverflowAddLNode>::can_overflow(t1, t2);
166 }
167 
can_overflow(const Type * t1,const Type * t2) const168 bool 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 
can_overflow(const Type * t1,const Type * t2) const175 bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const {
176   return MulHelper<OverflowMulLNode>::can_overflow(t1, t2);
177 }
178 
sub(const Type * t1,const Type * t2) const179 const 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 
184 template <typename OverflowOp>
185 struct IdealHelper {
186   typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong
187   typedef typename TypeClass::NativeType NativeType;
188 
IdealIdealHelper189   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 
ValueIdealHelper212   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 
Ideal(PhaseGVN * phase,bool can_reshape)252 Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) {
253   return IdealHelper<OverflowINode>::Ideal(this, phase, can_reshape);
254 }
255 
Ideal(PhaseGVN * phase,bool can_reshape)256 Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
257   return IdealHelper<OverflowLNode>::Ideal(this, phase, can_reshape);
258 }
259 
Value(PhaseGVN * phase) const260 const Type* OverflowINode::Value(PhaseGVN* phase) const {
261   return IdealHelper<OverflowINode>::Value(this, phase);
262 }
263 
Value(PhaseGVN * phase) const264 const Type* OverflowLNode::Value(PhaseGVN* phase) const {
265   return IdealHelper<OverflowLNode>::Value(this, phase);
266 }
267 
268