Mercurial > hg > truffle
annotate src/share/vm/opto/mathexactnode.cpp @ 15152:5f75a06505a6
Fix formatting
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Tue, 15 Apr 2014 13:40:43 +0200 |
parents | 4ca6dc0799b6 |
children | 52b4284cb496 |
rev | line source |
---|---|
12323 | 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 */ | |
24 | |
25 #include "precompiled.hpp" | |
26 #include "memory/allocation.inline.hpp" | |
27 #include "opto/addnode.hpp" | |
12888
4a2acfb16e97
8025657: compiler/intrinsics/mathexact/ConstantTest.java fails on assert in lcm.cpp on solaris x64
rbackman
parents:
12323
diff
changeset
|
28 #include "opto/cfgnode.hpp" |
12323 | 29 #include "opto/machnode.hpp" |
12888
4a2acfb16e97
8025657: compiler/intrinsics/mathexact/ConstantTest.java fails on assert in lcm.cpp on solaris x64
rbackman
parents:
12323
diff
changeset
|
30 #include "opto/matcher.hpp" |
12323 | 31 #include "opto/mathexactnode.hpp" |
32 #include "opto/subnode.hpp" | |
33 | |
14909 | 34 MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) { |
35 init_class_id(Class_MathExact); | |
36 init_req(0, ctrl); | |
37 init_req(1, in1); | |
38 } | |
39 | |
40 MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) { | |
41 init_class_id(Class_MathExact); | |
42 init_req(0, ctrl); | |
43 init_req(1, in1); | |
44 init_req(2, in2); | |
45 } | |
46 | |
47 BoolNode* MathExactNode::bool_node() const { | |
48 Node* flags = flags_node(); | |
49 BoolNode* boolnode = flags->unique_out()->as_Bool(); | |
50 assert(boolnode != NULL, "must have BoolNode"); | |
51 return boolnode; | |
52 } | |
53 | |
54 IfNode* MathExactNode::if_node() const { | |
55 BoolNode* boolnode = bool_node(); | |
56 IfNode* ifnode = boolnode->unique_out()->as_If(); | |
57 assert(ifnode != NULL, "must have IfNode"); | |
58 return ifnode; | |
59 } | |
60 | |
61 Node* MathExactNode::control_node() const { | |
62 IfNode* ifnode = if_node(); | |
63 return ifnode->in(0); | |
64 } | |
65 | |
66 Node* MathExactNode::non_throwing_branch() const { | |
67 IfNode* ifnode = if_node(); | |
68 if (bool_node()->_test._test == BoolTest::overflow) { | |
69 return ifnode->proj_out(0); | |
70 } | |
71 return ifnode->proj_out(1); | |
72 } | |
73 | |
74 // If the MathExactNode won't overflow we have to replace the | |
75 // FlagsProjNode and ProjNode that is generated by the MathExactNode | |
76 Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) { | |
77 PhaseIterGVN* igvn = phase->is_IterGVN(); | |
78 if (igvn) { | |
79 ProjNode* result = result_node(); | |
80 ProjNode* flags = flags_node(); | |
81 | |
82 if (result != NULL) { | |
83 igvn->replace_node(result, new_result); | |
84 } | |
12323 | 85 |
14909 | 86 if (flags != NULL) { |
87 BoolNode* boolnode = bool_node(); | |
88 switch (boolnode->_test._test) { | |
89 case BoolTest::overflow: | |
90 // if the check is for overflow - never taken | |
91 igvn->replace_node(boolnode, phase->intcon(0)); | |
92 break; | |
93 case BoolTest::no_overflow: | |
94 // if the check is for no overflow - always taken | |
95 igvn->replace_node(boolnode, phase->intcon(1)); | |
96 break; | |
97 default: | |
98 fatal("Unexpected value of BoolTest"); | |
99 break; | |
100 } | |
101 flags->del_req(0); | |
102 } | |
103 } | |
104 return new_result; | |
105 } | |
106 | |
107 Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) { | |
108 uint ideal_reg = proj->ideal_reg(); | |
109 RegMask rm; | |
110 if (proj->_con == result_proj_node) { | |
111 rm = m->mathExactI_result_proj_mask(); | |
112 } else { | |
113 assert(proj->_con == flags_proj_node, "must be result or flags"); | |
114 assert(ideal_reg == Op_RegFlags, "sanity"); | |
115 rm = m->mathExactI_flags_proj_mask(); | |
116 } | |
117 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); | |
118 } | |
119 | |
120 Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) { | |
121 uint ideal_reg = proj->ideal_reg(); | |
122 RegMask rm; | |
123 if (proj->_con == result_proj_node) { | |
124 rm = m->mathExactL_result_proj_mask(); | |
125 } else { | |
126 assert(proj->_con == flags_proj_node, "must be result or flags"); | |
127 assert(ideal_reg == Op_RegFlags, "sanity"); | |
128 rm = m->mathExactI_flags_proj_mask(); | |
129 } | |
130 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); | |
131 } | |
132 | |
133 Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
134 Node* arg1 = in(1); | |
135 Node* arg2 = in(2); | |
136 | |
137 const Type* type1 = phase->type(arg1); | |
138 const Type* type2 = phase->type(arg2); | |
139 | |
140 if (type1 != Type::TOP && type1->singleton() && | |
141 type2 != Type::TOP && type2->singleton()) { | |
142 jint val1 = arg1->get_int(); | |
143 jint val2 = arg2->get_int(); | |
144 jint result = val1 + val2; | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
145 // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result |
14909 | 146 if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { |
147 Node* con_result = ConINode::make(phase->C, result); | |
148 return no_overflow(phase, con_result); | |
12323 | 149 } |
14909 | 150 return NULL; |
12323 | 151 } |
152 | |
14909 | 153 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x |
154 Node* add_result = new (phase->C) AddINode(arg1, arg2); | |
155 return no_overflow(phase, add_result); | |
156 } | |
157 | |
158 if (type2->singleton()) { | |
159 return NULL; // no change - keep constant on the right | |
12323 | 160 } |
14909 | 161 |
162 if (type1->singleton()) { | |
163 // Make it x + Constant - move constant to the right | |
164 swap_edges(1, 2); | |
165 return this; | |
166 } | |
167 | |
168 if (arg2->is_Load()) { | |
169 return NULL; // no change - keep load on the right | |
170 } | |
171 | |
172 if (arg1->is_Load()) { | |
173 // Make it x + Load - move load to the right | |
174 swap_edges(1, 2); | |
175 return this; | |
176 } | |
12323 | 177 |
14909 | 178 if (arg1->_idx > arg2->_idx) { |
179 // Sort the edges | |
180 swap_edges(1, 2); | |
181 return this; | |
182 } | |
183 | |
184 return NULL; | |
185 } | |
186 | |
187 Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
188 Node* arg1 = in(1); | |
189 Node* arg2 = in(2); | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
190 |
14909 | 191 const Type* type1 = phase->type(arg1); |
192 const Type* type2 = phase->type(arg2); | |
193 | |
194 if (type1 != Type::TOP && type1->singleton() && | |
195 type2 != Type::TOP && type2->singleton()) { | |
196 jlong val1 = arg1->get_long(); | |
197 jlong val2 = arg2->get_long(); | |
198 jlong result = val1 + val2; | |
199 // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result | |
200 if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { | |
201 Node* con_result = ConLNode::make(phase->C, result); | |
202 return no_overflow(phase, con_result); | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
203 } |
14909 | 204 return NULL; |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
205 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
206 |
14909 | 207 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x |
208 Node* add_result = new (phase->C) AddLNode(arg1, arg2); | |
209 return no_overflow(phase, add_result); | |
210 } | |
211 | |
212 if (type2->singleton()) { | |
213 return NULL; // no change - keep constant on the right | |
214 } | |
215 | |
216 if (type1->singleton()) { | |
217 // Make it x + Constant - move constant to the right | |
218 swap_edges(1, 2); | |
219 return this; | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
220 } |
14909 | 221 |
222 if (arg2->is_Load()) { | |
223 return NULL; // no change - keep load on the right | |
224 } | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
225 |
14909 | 226 if (arg1->is_Load()) { |
227 // Make it x + Load - move load to the right | |
228 swap_edges(1, 2); | |
229 return this; | |
230 } | |
231 | |
232 if (arg1->_idx > arg2->_idx) { | |
233 // Sort the edges | |
234 swap_edges(1, 2); | |
235 return this; | |
236 } | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
237 |
14909 | 238 return NULL; |
239 } | |
240 | |
241 Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
242 Node* arg1 = in(1); | |
243 Node* arg2 = in(2); | |
244 | |
245 const Type* type1 = phase->type(arg1); | |
246 const Type* type2 = phase->type(arg2); | |
247 | |
248 if (type1 != Type::TOP && type1->singleton() && | |
249 type2 != Type::TOP && type2->singleton()) { | |
250 jint val1 = arg1->get_int(); | |
251 jint val2 = arg2->get_int(); | |
252 jint result = val1 - val2; | |
253 | |
254 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and | |
255 // the sign of the result is different than the sign of arg1 | |
256 if (((val1 ^ val2) & (val1 ^ result)) >= 0) { | |
257 Node* con_result = ConINode::make(phase->C, result); | |
258 return no_overflow(phase, con_result); | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
259 } |
14909 | 260 return NULL; |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
261 } |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
262 |
14909 | 263 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { |
264 // Sub with zero is the same as add with zero | |
265 Node* add_result = new (phase->C) AddINode(arg1, arg2); | |
266 return no_overflow(phase, add_result); | |
267 } | |
268 | |
269 return NULL; | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
270 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
271 |
14909 | 272 Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
273 Node* arg1 = in(1); | |
274 Node* arg2 = in(2); | |
275 | |
276 const Type* type1 = phase->type(arg1); | |
277 const Type* type2 = phase->type(arg2); | |
278 | |
279 if (type1 != Type::TOP && type1->singleton() && | |
280 type2 != Type::TOP && type2->singleton()) { | |
281 jlong val1 = arg1->get_long(); | |
282 jlong val2 = arg2->get_long(); | |
283 jlong result = val1 - val2; | |
284 | |
285 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and | |
286 // the sign of the result is different than the sign of arg1 | |
287 if (((val1 ^ val2) & (val1 ^ result)) >= 0) { | |
288 Node* con_result = ConLNode::make(phase->C, result); | |
289 return no_overflow(phase, con_result); | |
290 } | |
291 return NULL; | |
292 } | |
293 | |
294 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { | |
295 // Sub with zero is the same as add with zero | |
296 Node* add_result = new (phase->C) AddLNode(arg1, arg2); | |
297 return no_overflow(phase, add_result); | |
298 } | |
299 | |
300 return NULL; | |
301 } | |
302 | |
303 Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
304 Node *arg = in(1); | |
305 | |
306 const Type* type = phase->type(arg); | |
307 if (type != Type::TOP && type->singleton()) { | |
308 jint value = arg->get_int(); | |
309 if (value != min_jint) { | |
310 Node* neg_result = ConINode::make(phase->C, -value); | |
311 return no_overflow(phase, neg_result); | |
312 } | |
313 } | |
314 return NULL; | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
315 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
316 |
14909 | 317 Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
318 Node *arg = in(1); | |
319 | |
320 const Type* type = phase->type(arg); | |
321 if (type != Type::TOP && type->singleton()) { | |
322 jlong value = arg->get_long(); | |
323 if (value != min_jlong) { | |
324 Node* neg_result = ConLNode::make(phase->C, -value); | |
325 return no_overflow(phase, neg_result); | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
326 } |
14909 | 327 } |
328 return NULL; | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
329 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
330 |
14909 | 331 Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { |
332 Node* arg1 = in(1); | |
333 Node* arg2 = in(2); | |
334 | |
335 const Type* type1 = phase->type(arg1); | |
336 const Type* type2 = phase->type(arg2); | |
337 | |
338 if (type1 != Type::TOP && type1->singleton() && | |
339 type2 != Type::TOP && type2->singleton()) { | |
340 jint val1 = arg1->get_int(); | |
341 jint val2 = arg2->get_int(); | |
342 jlong result = (jlong) val1 * (jlong) val2; | |
343 if ((jint) result == result) { | |
344 // no overflow | |
345 Node* mul_result = ConINode::make(phase->C, result); | |
346 return no_overflow(phase, mul_result); | |
347 } | |
348 } | |
349 | |
350 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { | |
351 return no_overflow(phase, ConINode::make(phase->C, 0)); | |
352 } | |
353 | |
354 if (type1 == TypeInt::ONE) { | |
355 Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0)); | |
356 return no_overflow(phase, mul_result); | |
357 } | |
358 if (type2 == TypeInt::ONE) { | |
359 Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0)); | |
360 return no_overflow(phase, mul_result); | |
361 } | |
362 | |
363 if (type1 == TypeInt::MINUS_1) { | |
364 return new (phase->C) NegExactINode(NULL, arg2); | |
365 } | |
366 | |
367 if (type2 == TypeInt::MINUS_1) { | |
368 return new (phase->C) NegExactINode(NULL, arg1); | |
369 } | |
370 | |
371 return NULL; | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
372 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
373 |
14909 | 374 Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
375 Node* arg1 = in(1); | |
376 Node* arg2 = in(2); | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
377 |
14909 | 378 const Type* type1 = phase->type(arg1); |
379 const Type* type2 = phase->type(arg2); | |
380 | |
381 if (type1 != Type::TOP && type1->singleton() && | |
382 type2 != Type::TOP && type2->singleton()) { | |
383 jlong val1 = arg1->get_long(); | |
384 jlong val2 = arg2->get_long(); | |
385 | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
386 jlong result = val1 * val2; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
387 jlong ax = (val1 < 0 ? -val1 : val1); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
388 jlong ay = (val2 < 0 ? -val2 : val2); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
389 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
390 bool overflow = false; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
391 if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
392 // potential overflow if any bit in upper 32 bits are set |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
393 if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
394 // -1 * Long.MIN_VALUE will overflow |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
395 overflow = true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
396 } else if (val2 != 0 && (result / val2 != val1)) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
397 overflow = true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
398 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
399 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12888
diff
changeset
|
400 |
14909 | 401 if (!overflow) { |
402 Node* mul_result = ConLNode::make(phase->C, result); | |
403 return no_overflow(phase, mul_result); | |
404 } | |
405 } | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
406 |
14909 | 407 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { |
408 return no_overflow(phase, ConLNode::make(phase->C, 0)); | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
409 } |
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
410 |
14909 | 411 if (type1 == TypeLong::ONE) { |
412 Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0)); | |
413 return no_overflow(phase, mul_result); | |
414 } | |
415 if (type2 == TypeLong::ONE) { | |
416 Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0)); | |
417 return no_overflow(phase, mul_result); | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
418 } |
14909 | 419 |
420 if (type1 == TypeLong::MINUS_1) { | |
421 return new (phase->C) NegExactLNode(NULL, arg2); | |
422 } | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
423 |
14909 | 424 if (type2 == TypeLong::MINUS_1) { |
425 return new (phase->C) NegExactLNode(NULL, arg1); | |
426 } | |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
427 |
14909 | 428 return NULL; |
14495
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
429 } |
cd5d10655495
8027754: Enable loop optimizations for loops with MathExact inside
rbackman
parents:
12972
diff
changeset
|
430 |