Mercurial > hg > truffle
annotate src/share/vm/opto/ifnode.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | 08eb13460b3a |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1153
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1153
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1153
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "opto/addnode.hpp" | |
28 #include "opto/cfgnode.hpp" | |
29 #include "opto/connode.hpp" | |
30 #include "opto/phaseX.hpp" | |
31 #include "opto/runtime.hpp" | |
32 #include "opto/subnode.hpp" | |
33 | |
0 | 34 // Portions of code courtesy of Clifford Click |
35 | |
36 // Optimization - Graph Style | |
37 | |
38 | |
39 extern int explicit_null_checks_elided; | |
40 | |
41 //============================================================================= | |
42 //------------------------------Value------------------------------------------ | |
43 // Return a tuple for whichever arm of the IF is reachable | |
44 const Type *IfNode::Value( PhaseTransform *phase ) const { | |
45 if( !in(0) ) return Type::TOP; | |
46 if( phase->type(in(0)) == Type::TOP ) | |
47 return Type::TOP; | |
48 const Type *t = phase->type(in(1)); | |
49 if( t == Type::TOP ) // data is undefined | |
50 return TypeTuple::IFNEITHER; // unreachable altogether | |
51 if( t == TypeInt::ZERO ) // zero, or false | |
52 return TypeTuple::IFFALSE; // only false branch is reachable | |
53 if( t == TypeInt::ONE ) // 1, or true | |
54 return TypeTuple::IFTRUE; // only true branch is reachable | |
55 assert( t == TypeInt::BOOL, "expected boolean type" ); | |
56 | |
57 return TypeTuple::IFBOTH; // No progress | |
58 } | |
59 | |
60 const RegMask &IfNode::out_RegMask() const { | |
61 return RegMask::Empty; | |
62 } | |
63 | |
64 //------------------------------split_if--------------------------------------- | |
65 // Look for places where we merge constants, then test on the merged value. | |
66 // If the IF test will be constant folded on the path with the constant, we | |
67 // win by splitting the IF to before the merge point. | |
68 static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { | |
69 // I could be a lot more general here, but I'm trying to squeeze this | |
70 // in before the Christmas '98 break so I'm gonna be kinda restrictive | |
71 // on the patterns I accept. CNC | |
72 | |
73 // Look for a compare of a constant and a merged value | |
74 Node *i1 = iff->in(1); | |
75 if( !i1->is_Bool() ) return NULL; | |
76 BoolNode *b = i1->as_Bool(); | |
77 Node *cmp = b->in(1); | |
78 if( !cmp->is_Cmp() ) return NULL; | |
79 i1 = cmp->in(1); | |
80 if( i1 == NULL || !i1->is_Phi() ) return NULL; | |
81 PhiNode *phi = i1->as_Phi(); | |
82 if( phi->is_copy() ) return NULL; | |
83 Node *con2 = cmp->in(2); | |
84 if( !con2->is_Con() ) return NULL; | |
85 // See that the merge point contains some constants | |
86 Node *con1=NULL; | |
87 uint i4; | |
88 for( i4 = 1; i4 < phi->req(); i4++ ) { | |
89 con1 = phi->in(i4); | |
605 | 90 if( !con1 ) return NULL; // Do not optimize partially collapsed merges |
0 | 91 if( con1->is_Con() ) break; // Found a constant |
92 // Also allow null-vs-not-null checks | |
93 const TypePtr *tp = igvn->type(con1)->isa_ptr(); | |
94 if( tp && tp->_ptr == TypePtr::NotNull ) | |
95 break; | |
96 } | |
97 if( i4 >= phi->req() ) return NULL; // Found no constants | |
98 | |
99 igvn->C->set_has_split_ifs(true); // Has chance for split-if | |
100 | |
101 // Make sure that the compare can be constant folded away | |
102 Node *cmp2 = cmp->clone(); | |
103 cmp2->set_req(1,con1); | |
104 cmp2->set_req(2,con2); | |
105 const Type *t = cmp2->Value(igvn); | |
106 // This compare is dead, so whack it! | |
107 igvn->remove_dead_node(cmp2); | |
108 if( !t->singleton() ) return NULL; | |
109 | |
110 // No intervening control, like a simple Call | |
111 Node *r = iff->in(0); | |
112 if( !r->is_Region() ) return NULL; | |
113 if( phi->region() != r ) return NULL; | |
114 // No other users of the cmp/bool | |
115 if (b->outcnt() != 1 || cmp->outcnt() != 1) { | |
116 //tty->print_cr("many users of cmp/bool"); | |
117 return NULL; | |
118 } | |
119 | |
120 // Make sure we can determine where all the uses of merged values go | |
121 for (DUIterator_Fast jmax, j = r->fast_outs(jmax); j < jmax; j++) { | |
122 Node* u = r->fast_out(j); | |
123 if( u == r ) continue; | |
124 if( u == iff ) continue; | |
125 if( u->outcnt() == 0 ) continue; // use is dead & ignorable | |
126 if( !u->is_Phi() ) { | |
127 /* | |
128 if( u->is_Start() ) { | |
129 tty->print_cr("Region has inlined start use"); | |
130 } else { | |
131 tty->print_cr("Region has odd use"); | |
132 u->dump(2); | |
133 }*/ | |
134 return NULL; | |
135 } | |
136 if( u != phi ) { | |
137 // CNC - do not allow any other merged value | |
138 //tty->print_cr("Merging another value"); | |
139 //u->dump(2); | |
140 return NULL; | |
141 } | |
142 // Make sure we can account for all Phi uses | |
143 for (DUIterator_Fast kmax, k = u->fast_outs(kmax); k < kmax; k++) { | |
144 Node* v = u->fast_out(k); // User of the phi | |
145 // CNC - Allow only really simple patterns. | |
146 // In particular I disallow AddP of the Phi, a fairly common pattern | |
147 if( v == cmp ) continue; // The compare is OK | |
148 if( (v->is_ConstraintCast()) && | |
149 v->in(0)->in(0) == iff ) | |
150 continue; // CastPP/II of the IfNode is OK | |
151 // Disabled following code because I cannot tell if exactly one | |
152 // path dominates without a real dominator check. CNC 9/9/1999 | |
153 //uint vop = v->Opcode(); | |
154 //if( vop == Op_Phi ) { // Phi from another merge point might be OK | |
155 // Node *r = v->in(0); // Get controlling point | |
156 // if( !r ) return NULL; // Degraded to a copy | |
157 // // Find exactly one path in (either True or False doms, but not IFF) | |
158 // int cnt = 0; | |
159 // for( uint i = 1; i < r->req(); i++ ) | |
160 // if( r->in(i) && r->in(i)->in(0) == iff ) | |
161 // cnt++; | |
162 // if( cnt == 1 ) continue; // Exactly one of True or False guards Phi | |
163 //} | |
164 if( !v->is_Call() ) { | |
165 /* | |
166 if( v->Opcode() == Op_AddP ) { | |
167 tty->print_cr("Phi has AddP use"); | |
168 } else if( v->Opcode() == Op_CastPP ) { | |
169 tty->print_cr("Phi has CastPP use"); | |
170 } else if( v->Opcode() == Op_CastII ) { | |
171 tty->print_cr("Phi has CastII use"); | |
172 } else { | |
173 tty->print_cr("Phi has use I cant be bothered with"); | |
174 } | |
175 */ | |
176 } | |
177 return NULL; | |
178 | |
179 /* CNC - Cut out all the fancy acceptance tests | |
180 // Can we clone this use when doing the transformation? | |
181 // If all uses are from Phis at this merge or constants, then YES. | |
182 if( !v->in(0) && v != cmp ) { | |
183 tty->print_cr("Phi has free-floating use"); | |
184 v->dump(2); | |
185 return NULL; | |
186 } | |
187 for( uint l = 1; l < v->req(); l++ ) { | |
188 if( (!v->in(l)->is_Phi() || v->in(l)->in(0) != r) && | |
189 !v->in(l)->is_Con() ) { | |
190 tty->print_cr("Phi has use"); | |
191 v->dump(2); | |
192 return NULL; | |
193 } // End of if Phi-use input is neither Phi nor Constant | |
194 } // End of for all inputs to Phi-use | |
195 */ | |
196 } // End of for all uses of Phi | |
197 } // End of for all uses of Region | |
198 | |
199 // Only do this if the IF node is in a sane state | |
200 if (iff->outcnt() != 2) | |
201 return NULL; | |
202 | |
203 // Got a hit! Do the Mondo Hack! | |
204 // | |
205 //ABC a1c def ghi B 1 e h A C a c d f g i | |
206 // R - Phi - Phi - Phi Rc - Phi - Phi - Phi Rx - Phi - Phi - Phi | |
207 // cmp - 2 cmp - 2 cmp - 2 | |
208 // bool bool_c bool_x | |
209 // if if_c if_x | |
210 // T F T F T F | |
211 // ..s.. ..t .. ..s.. ..t.. ..s.. ..t.. | |
212 // | |
605 | 213 // Split the paths coming into the merge point into 2 separate groups of |
0 | 214 // merges. On the left will be all the paths feeding constants into the |
215 // Cmp's Phi. On the right will be the remaining paths. The Cmp's Phi | |
216 // will fold up into a constant; this will let the Cmp fold up as well as | |
217 // all the control flow. Below the original IF we have 2 control | |
218 // dependent regions, 's' and 't'. Now we will merge the two paths | |
219 // just prior to 's' and 't' from the two IFs. At least 1 path (and quite | |
220 // likely 2 or more) will promptly constant fold away. | |
221 PhaseGVN *phase = igvn; | |
222 | |
223 // Make a region merging constants and a region merging the rest | |
224 uint req_c = 0; | |
225 for (uint ii = 1; ii < r->req(); ii++) { | |
226 if( phi->in(ii) == con1 ) { | |
227 req_c++; | |
228 } | |
229 } | |
230 Node *region_c = new (igvn->C, req_c + 1) RegionNode(req_c + 1); | |
231 Node *phi_c = con1; | |
232 uint len = r->req(); | |
233 Node *region_x = new (igvn->C, len - req_c + 1) RegionNode(len - req_c + 1); | |
234 Node *phi_x = PhiNode::make_blank(region_x, phi); | |
235 for (uint i = 1, i_c = 1, i_x = 1; i < len; i++) { | |
236 if( phi->in(i) == con1 ) { | |
237 region_c->init_req( i_c++, r ->in(i) ); | |
238 } else { | |
239 region_x->init_req( i_x, r ->in(i) ); | |
240 phi_x ->init_req( i_x++, phi->in(i) ); | |
241 } | |
242 } | |
243 | |
244 // Register the new RegionNodes but do not transform them. Cannot | |
605 | 245 // transform until the entire Region/Phi conglomerate has been hacked |
0 | 246 // as a single huge transform. |
247 igvn->register_new_node_with_optimizer( region_c ); | |
248 igvn->register_new_node_with_optimizer( region_x ); | |
249 // Prevent the untimely death of phi_x. Currently he has no uses. He is | |
250 // about to get one. If this only use goes away, then phi_x will look dead. | |
251 // However, he will be picking up some more uses down below. | |
252 Node *hook = new (igvn->C, 4) Node(4); | |
253 hook->init_req(0, phi_x); | |
254 hook->init_req(1, phi_c); | |
1013
ce590301ae2a
6889300: assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes")
kvn
parents:
851
diff
changeset
|
255 phi_x = phase->transform( phi_x ); |
0 | 256 |
257 // Make the compare | |
258 Node *cmp_c = phase->makecon(t); | |
259 Node *cmp_x = cmp->clone(); | |
260 cmp_x->set_req(1,phi_x); | |
261 cmp_x->set_req(2,con2); | |
262 cmp_x = phase->transform(cmp_x); | |
263 // Make the bool | |
264 Node *b_c = phase->transform(new (igvn->C, 2) BoolNode(cmp_c,b->_test._test)); | |
265 Node *b_x = phase->transform(new (igvn->C, 2) BoolNode(cmp_x,b->_test._test)); | |
266 // Make the IfNode | |
267 IfNode *iff_c = new (igvn->C, 2) IfNode(region_c,b_c,iff->_prob,iff->_fcnt); | |
268 igvn->set_type_bottom(iff_c); | |
269 igvn->_worklist.push(iff_c); | |
270 hook->init_req(2, iff_c); | |
271 | |
272 IfNode *iff_x = new (igvn->C, 2) IfNode(region_x,b_x,iff->_prob, iff->_fcnt); | |
273 igvn->set_type_bottom(iff_x); | |
274 igvn->_worklist.push(iff_x); | |
275 hook->init_req(3, iff_x); | |
276 | |
277 // Make the true/false arms | |
278 Node *iff_c_t = phase->transform(new (igvn->C, 1) IfTrueNode (iff_c)); | |
279 Node *iff_c_f = phase->transform(new (igvn->C, 1) IfFalseNode(iff_c)); | |
280 Node *iff_x_t = phase->transform(new (igvn->C, 1) IfTrueNode (iff_x)); | |
281 Node *iff_x_f = phase->transform(new (igvn->C, 1) IfFalseNode(iff_x)); | |
282 | |
283 // Merge the TRUE paths | |
284 Node *region_s = new (igvn->C, 3) RegionNode(3); | |
285 igvn->_worklist.push(region_s); | |
286 region_s->init_req(1, iff_c_t); | |
287 region_s->init_req(2, iff_x_t); | |
288 igvn->register_new_node_with_optimizer( region_s ); | |
289 | |
290 // Merge the FALSE paths | |
291 Node *region_f = new (igvn->C, 3) RegionNode(3); | |
292 igvn->_worklist.push(region_f); | |
293 region_f->init_req(1, iff_c_f); | |
294 region_f->init_req(2, iff_x_f); | |
295 igvn->register_new_node_with_optimizer( region_f ); | |
296 | |
297 igvn->hash_delete(cmp);// Remove soon-to-be-dead node from hash table. | |
298 cmp->set_req(1,NULL); // Whack the inputs to cmp because it will be dead | |
299 cmp->set_req(2,NULL); | |
300 // Check for all uses of the Phi and give them a new home. | |
301 // The 'cmp' got cloned, but CastPP/IIs need to be moved. | |
302 Node *phi_s = NULL; // do not construct unless needed | |
303 Node *phi_f = NULL; // do not construct unless needed | |
304 for (DUIterator_Last i2min, i2 = phi->last_outs(i2min); i2 >= i2min; --i2) { | |
305 Node* v = phi->last_out(i2);// User of the phi | |
306 igvn->hash_delete(v); // Have to fixup other Phi users | |
307 igvn->_worklist.push(v); | |
308 uint vop = v->Opcode(); | |
309 Node *proj = NULL; | |
310 if( vop == Op_Phi ) { // Remote merge point | |
311 Node *r = v->in(0); | |
312 for (uint i3 = 1; i3 < r->req(); i3++) | |
313 if (r->in(i3) && r->in(i3)->in(0) == iff) { | |
314 proj = r->in(i3); | |
315 break; | |
316 } | |
317 } else if( v->is_ConstraintCast() ) { | |
318 proj = v->in(0); // Controlling projection | |
319 } else { | |
320 assert( 0, "do not know how to handle this guy" ); | |
321 } | |
322 | |
323 Node *proj_path_data, *proj_path_ctrl; | |
324 if( proj->Opcode() == Op_IfTrue ) { | |
325 if( phi_s == NULL ) { | |
326 // Only construct phi_s if needed, otherwise provides | |
327 // interfering use. | |
328 phi_s = PhiNode::make_blank(region_s,phi); | |
329 phi_s->init_req( 1, phi_c ); | |
330 phi_s->init_req( 2, phi_x ); | |
1013
ce590301ae2a
6889300: assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes")
kvn
parents:
851
diff
changeset
|
331 hook->add_req(phi_s); |
0 | 332 phi_s = phase->transform(phi_s); |
333 } | |
334 proj_path_data = phi_s; | |
335 proj_path_ctrl = region_s; | |
336 } else { | |
337 if( phi_f == NULL ) { | |
338 // Only construct phi_f if needed, otherwise provides | |
339 // interfering use. | |
340 phi_f = PhiNode::make_blank(region_f,phi); | |
341 phi_f->init_req( 1, phi_c ); | |
342 phi_f->init_req( 2, phi_x ); | |
1013
ce590301ae2a
6889300: assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes")
kvn
parents:
851
diff
changeset
|
343 hook->add_req(phi_f); |
0 | 344 phi_f = phase->transform(phi_f); |
345 } | |
346 proj_path_data = phi_f; | |
347 proj_path_ctrl = region_f; | |
348 } | |
349 | |
350 // Fixup 'v' for for the split | |
351 if( vop == Op_Phi ) { // Remote merge point | |
352 uint i; | |
353 for( i = 1; i < v->req(); i++ ) | |
354 if( v->in(i) == phi ) | |
355 break; | |
356 v->set_req(i, proj_path_data ); | |
357 } else if( v->is_ConstraintCast() ) { | |
358 v->set_req(0, proj_path_ctrl ); | |
359 v->set_req(1, proj_path_data ); | |
360 } else | |
361 ShouldNotReachHere(); | |
362 } | |
363 | |
364 // Now replace the original iff's True/False with region_s/region_t. | |
365 // This makes the original iff go dead. | |
366 for (DUIterator_Last i3min, i3 = iff->last_outs(i3min); i3 >= i3min; --i3) { | |
367 Node* p = iff->last_out(i3); | |
368 assert( p->Opcode() == Op_IfTrue || p->Opcode() == Op_IfFalse, "" ); | |
369 Node *u = (p->Opcode() == Op_IfTrue) ? region_s : region_f; | |
370 // Replace p with u | |
371 igvn->add_users_to_worklist(p); | |
372 for (DUIterator_Last lmin, l = p->last_outs(lmin); l >= lmin;) { | |
373 Node* x = p->last_out(l); | |
374 igvn->hash_delete(x); | |
375 uint uses_found = 0; | |
376 for( uint j = 0; j < x->req(); j++ ) { | |
377 if( x->in(j) == p ) { | |
378 x->set_req(j, u); | |
379 uses_found++; | |
380 } | |
381 } | |
382 l -= uses_found; // we deleted 1 or more copies of this edge | |
383 } | |
384 igvn->remove_dead_node(p); | |
385 } | |
386 | |
387 // Force the original merge dead | |
388 igvn->hash_delete(r); | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
389 // First, remove region's dead users. |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
390 for (DUIterator_Last lmin, l = r->last_outs(lmin); l >= lmin;) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
391 Node* u = r->last_out(l); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
392 if( u == r ) { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
393 r->set_req(0, NULL); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
394 } else { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
395 assert(u->outcnt() == 0, "only dead users"); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
396 igvn->remove_dead_node(u); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
397 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
398 l -= 1; |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
399 } |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
605
diff
changeset
|
400 igvn->remove_dead_node(r); |
0 | 401 |
402 // Now remove the bogus extra edges used to keep things alive | |
403 igvn->remove_dead_node( hook ); | |
404 | |
405 // Must return either the original node (now dead) or a new node | |
406 // (Do not return a top here, since that would break the uniqueness of top.) | |
407 return new (igvn->C, 1) ConINode(TypeInt::ZERO); | |
408 } | |
409 | |
410 //------------------------------is_range_check--------------------------------- | |
411 // Return 0 if not a range check. Return 1 if a range check and set index and | |
412 // offset. Return 2 if we had to negate the test. Index is NULL if the check | |
413 // is versus a constant. | |
414 int IfNode::is_range_check(Node* &range, Node* &index, jint &offset) { | |
415 Node* b = in(1); | |
416 if (b == NULL || !b->is_Bool()) return 0; | |
417 BoolNode* bn = b->as_Bool(); | |
418 Node* cmp = bn->in(1); | |
419 if (cmp == NULL) return 0; | |
420 if (cmp->Opcode() != Op_CmpU) return 0; | |
421 | |
422 Node* l = cmp->in(1); | |
423 Node* r = cmp->in(2); | |
424 int flip_test = 1; | |
425 if (bn->_test._test == BoolTest::le) { | |
426 l = cmp->in(2); | |
427 r = cmp->in(1); | |
428 flip_test = 2; | |
429 } else if (bn->_test._test != BoolTest::lt) { | |
430 return 0; | |
431 } | |
432 if (l->is_top()) return 0; // Top input means dead test | |
433 if (r->Opcode() != Op_LoadRange) return 0; | |
434 | |
435 // We have recognized one of these forms: | |
436 // Flip 1: If (Bool[<] CmpU(l, LoadRange)) ... | |
437 // Flip 2: If (Bool[<=] CmpU(LoadRange, l)) ... | |
438 | |
439 // Make sure it's a real range check by requiring an uncommon trap | |
440 // along the OOB path. Otherwise, it's possible that the user wrote | |
441 // something which optimized to look like a range check but behaves | |
442 // in some other way. | |
443 Node* iftrap = proj_out(flip_test == 2 ? true : false); | |
444 bool found_trap = false; | |
445 if (iftrap != NULL) { | |
446 Node* u = iftrap->unique_ctrl_out(); | |
447 if (u != NULL) { | |
448 // It could be a merge point (Region) for uncommon trap. | |
449 if (u->is_Region()) { | |
450 Node* c = u->unique_ctrl_out(); | |
451 if (c != NULL) { | |
452 iftrap = u; | |
453 u = c; | |
454 } | |
455 } | |
456 if (u->in(0) == iftrap && u->is_CallStaticJava()) { | |
457 int req = u->as_CallStaticJava()->uncommon_trap_request(); | |
458 if (Deoptimization::trap_request_reason(req) == | |
459 Deoptimization::Reason_range_check) { | |
460 found_trap = true; | |
461 } | |
462 } | |
463 } | |
464 } | |
465 if (!found_trap) return 0; // sorry, no cigar | |
466 | |
467 // Look for index+offset form | |
468 Node* ind = l; | |
469 jint off = 0; | |
470 if (l->is_top()) { | |
471 return 0; | |
472 } else if (l->is_Add()) { | |
473 if ((off = l->in(1)->find_int_con(0)) != 0) { | |
474 ind = l->in(2); | |
475 } else if ((off = l->in(2)->find_int_con(0)) != 0) { | |
476 ind = l->in(1); | |
477 } | |
478 } else if ((off = l->find_int_con(-1)) >= 0) { | |
479 // constant offset with no variable index | |
480 ind = NULL; | |
481 } else { | |
482 // variable index with no constant offset (or dead negative index) | |
483 off = 0; | |
484 } | |
485 | |
486 // Return all the values: | |
487 index = ind; | |
488 offset = off; | |
489 range = r; | |
490 return flip_test; | |
491 } | |
492 | |
493 //------------------------------adjust_check----------------------------------- | |
494 // Adjust (widen) a prior range check | |
495 static void adjust_check(Node* proj, Node* range, Node* index, | |
496 int flip, jint off_lo, PhaseIterGVN* igvn) { | |
497 PhaseGVN *gvn = igvn; | |
498 // Break apart the old check | |
499 Node *iff = proj->in(0); | |
500 Node *bol = iff->in(1); | |
501 if( bol->is_top() ) return; // In case a partially dead range check appears | |
502 // bail (or bomb[ASSERT/DEBUG]) if NOT projection-->IfNode-->BoolNode | |
503 DEBUG_ONLY( if( !bol->is_Bool() ) { proj->dump(3); fatal("Expect projection-->IfNode-->BoolNode"); } ) | |
504 if( !bol->is_Bool() ) return; | |
505 | |
506 Node *cmp = bol->in(1); | |
507 // Compute a new check | |
508 Node *new_add = gvn->intcon(off_lo); | |
509 if( index ) { | |
510 new_add = off_lo ? gvn->transform(new (gvn->C, 3) AddINode( index, new_add )) : index; | |
511 } | |
512 Node *new_cmp = (flip == 1) | |
513 ? new (gvn->C, 3) CmpUNode( new_add, range ) | |
514 : new (gvn->C, 3) CmpUNode( range, new_add ); | |
515 new_cmp = gvn->transform(new_cmp); | |
516 // See if no need to adjust the existing check | |
517 if( new_cmp == cmp ) return; | |
518 // Else, adjust existing check | |
519 Node *new_bol = gvn->transform( new (gvn->C, 2) BoolNode( new_cmp, bol->as_Bool()->_test._test ) ); | |
520 igvn->hash_delete( iff ); | |
521 iff->set_req_X( 1, new_bol, igvn ); | |
522 } | |
523 | |
524 //------------------------------up_one_dom------------------------------------- | |
525 // Walk up the dominator tree one step. Return NULL at root or true | |
526 // complex merges. Skips through small diamonds. | |
527 Node* IfNode::up_one_dom(Node *curr, bool linear_only) { | |
528 Node *dom = curr->in(0); | |
529 if( !dom ) // Found a Region degraded to a copy? | |
530 return curr->nonnull_req(); // Skip thru it | |
531 | |
532 if( curr != dom ) // Normal walk up one step? | |
533 return dom; | |
534 | |
535 // Use linear_only if we are still parsing, since we cannot | |
536 // trust the regions to be fully filled in. | |
537 if (linear_only) | |
538 return NULL; | |
539 | |
1153
bea7a22a6f79
6915110: IfNode::up_one_dom moves beyond RootNode bug in src/share/vm/opto/ifnode.cpp
kvn
parents:
1017
diff
changeset
|
540 if( dom->is_Root() ) |
bea7a22a6f79
6915110: IfNode::up_one_dom moves beyond RootNode bug in src/share/vm/opto/ifnode.cpp
kvn
parents:
1017
diff
changeset
|
541 return NULL; |
bea7a22a6f79
6915110: IfNode::up_one_dom moves beyond RootNode bug in src/share/vm/opto/ifnode.cpp
kvn
parents:
1017
diff
changeset
|
542 |
0 | 543 // Else hit a Region. Check for a loop header |
544 if( dom->is_Loop() ) | |
545 return dom->in(1); // Skip up thru loops | |
546 | |
547 // Check for small diamonds | |
548 Node *din1, *din2, *din3, *din4; | |
549 if( dom->req() == 3 && // 2-path merge point | |
550 (din1 = dom ->in(1)) && // Left path exists | |
551 (din2 = dom ->in(2)) && // Right path exists | |
552 (din3 = din1->in(0)) && // Left path up one | |
553 (din4 = din2->in(0)) ) { // Right path up one | |
554 if( din3->is_Call() && // Handle a slow-path call on either arm | |
555 (din3 = din3->in(0)) ) | |
556 din3 = din3->in(0); | |
557 if( din4->is_Call() && // Handle a slow-path call on either arm | |
558 (din4 = din4->in(0)) ) | |
559 din4 = din4->in(0); | |
560 if( din3 == din4 && din3->is_If() ) | |
561 return din3; // Skip around diamonds | |
562 } | |
563 | |
564 // Give up the search at true merges | |
565 return NULL; // Dead loop? Or hit root? | |
566 } | |
567 | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
568 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
569 //------------------------------filtered_int_type-------------------------------- |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
570 // Return a possibly more restrictive type for val based on condition control flow for an if |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
571 const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
572 assert(if_proj && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
573 (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection"); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
574 if (if_proj->in(0) && if_proj->in(0)->is_If()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
575 IfNode* iff = if_proj->in(0)->as_If(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
576 if (iff->in(1) && iff->in(1)->is_Bool()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
577 BoolNode* bol = iff->in(1)->as_Bool(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
578 if (bol->in(1) && bol->in(1)->is_Cmp()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
579 const CmpNode* cmp = bol->in(1)->as_Cmp(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
580 if (cmp->in(1) == val) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
581 const TypeInt* cmp2_t = gvn->type(cmp->in(2))->isa_int(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
582 if (cmp2_t != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
583 jint lo = cmp2_t->_lo; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
584 jint hi = cmp2_t->_hi; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
585 BoolTest::mask msk = if_proj->Opcode() == Op_IfTrue ? bol->_test._test : bol->_test.negate(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
586 switch (msk) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
587 case BoolTest::ne: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
588 // Can't refine type |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
589 return NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
590 case BoolTest::eq: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
591 return cmp2_t; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
592 case BoolTest::lt: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
593 lo = TypeInt::INT->_lo; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
594 if (hi - 1 < hi) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
595 hi = hi - 1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
596 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
597 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
598 case BoolTest::le: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
599 lo = TypeInt::INT->_lo; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
600 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
601 case BoolTest::gt: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
602 if (lo + 1 > lo) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
603 lo = lo + 1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
604 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
605 hi = TypeInt::INT->_hi; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
606 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
607 case BoolTest::ge: |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
608 // lo unchanged |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
609 hi = TypeInt::INT->_hi; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
610 break; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
611 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
612 const TypeInt* rtn_t = TypeInt::make(lo, hi, cmp2_t->_widen); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
613 return rtn_t; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
614 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
615 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
616 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
617 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
618 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
619 return NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
620 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
621 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
622 //------------------------------fold_compares---------------------------- |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
623 // See if a pair of CmpIs can be converted into a CmpU. In some cases |
605 | 624 // the direction of this if is determined by the preceding if so it |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
625 // can be eliminate entirely. Given an if testing (CmpI n c) check |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
626 // for an immediately control dependent if that is testing (CmpI n c2) |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
627 // and has one projection leading to this if and the other projection |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
628 // leading to a region that merges one of this ifs control |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
629 // projections. |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
630 // |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
631 // If |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
632 // / | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
633 // / | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
634 // / | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
635 // If | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
636 // /\ | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
637 // / \ | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
638 // / \ | |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
639 // / Region |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
640 // |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
641 Node* IfNode::fold_compares(PhaseGVN* phase) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
642 if (!EliminateAutoBox || Opcode() != Op_If) return NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
643 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
644 Node* this_cmp = in(1)->in(1); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
645 if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
646 this_cmp->in(2)->is_Con() && this_cmp->in(2) != phase->C->top()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
647 Node* ctrl = in(0); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
648 BoolNode* this_bool = in(1)->as_Bool(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
649 Node* n = this_cmp->in(1); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
650 int hi = this_cmp->in(2)->get_int(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
651 if (ctrl != NULL && ctrl->is_Proj() && ctrl->outcnt() == 1 && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
652 ctrl->in(0)->is_If() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
653 ctrl->in(0)->outcnt() == 2 && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
654 ctrl->in(0)->in(1)->is_Bool() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
655 ctrl->in(0)->in(1)->in(1)->Opcode() == Op_CmpI && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
656 ctrl->in(0)->in(1)->in(1)->in(2)->is_Con() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
657 ctrl->in(0)->in(1)->in(1)->in(1) == n) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
658 IfNode* dom_iff = ctrl->in(0)->as_If(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
659 Node* otherproj = dom_iff->proj_out(!ctrl->as_Proj()->_con); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
660 if (otherproj->outcnt() == 1 && otherproj->unique_out()->is_Region() && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
661 this_bool->_test._test != BoolTest::ne && this_bool->_test._test != BoolTest::eq) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
662 // Identify which proj goes to the region and which continues on |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
663 RegionNode* region = otherproj->unique_out()->as_Region(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
664 Node* success = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
665 Node* fail = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
666 for (int i = 0; i < 2; i++) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
667 Node* proj = proj_out(i); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
668 if (success == NULL && proj->outcnt() == 1 && proj->unique_out() == region) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
669 success = proj; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
670 } else if (fail == NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
671 fail = proj; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
672 } else { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
673 success = fail = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
674 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
675 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
676 if (success != NULL && fail != NULL && !region->has_phi()) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
677 int lo = dom_iff->in(1)->in(1)->in(2)->get_int(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
678 BoolNode* dom_bool = dom_iff->in(1)->as_Bool(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
679 Node* dom_cmp = dom_bool->in(1); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
680 const TypeInt* failtype = filtered_int_type(phase, n, ctrl); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
681 if (failtype != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
682 const TypeInt* type2 = filtered_int_type(phase, n, fail); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
683 if (type2 != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
684 failtype = failtype->join(type2)->is_int(); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
685 } else { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
686 failtype = NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
687 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
688 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
689 |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
690 if (failtype != NULL && |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
691 dom_bool->_test._test != BoolTest::ne && dom_bool->_test._test != BoolTest::eq) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
692 int bound = failtype->_hi - failtype->_lo + 1; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
693 if (failtype->_hi != max_jint && failtype->_lo != min_jint && bound > 1) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
694 // Merge the two compares into a single unsigned compare by building (CmpU (n - lo) hi) |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
695 BoolTest::mask cond = fail->as_Proj()->_con ? BoolTest::lt : BoolTest::ge; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
696 Node* adjusted = phase->transform(new (phase->C, 3) SubINode(n, phase->intcon(failtype->_lo))); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
697 Node* newcmp = phase->transform(new (phase->C, 3) CmpUNode(adjusted, phase->intcon(bound))); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
698 Node* newbool = phase->transform(new (phase->C, 2) BoolNode(newcmp, cond)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
699 phase->hash_delete(dom_iff); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
700 dom_iff->set_req(1, phase->intcon(ctrl->as_Proj()->_con)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
701 phase->is_IterGVN()->_worklist.push(dom_iff); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
702 phase->hash_delete(this); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
703 set_req(1, newbool); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
704 return this; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
705 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
706 if (failtype->_lo > failtype->_hi) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
707 // previous if determines the result of this if so |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
708 // replace Bool with constant |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
709 phase->hash_delete(this); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
710 set_req(1, phase->intcon(success->as_Proj()->_con)); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
711 return this; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
712 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
713 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
714 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
715 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
716 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
717 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
718 return NULL; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
719 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
720 |
0 | 721 //------------------------------remove_useless_bool---------------------------- |
722 // Check for people making a useless boolean: things like | |
723 // if( (x < y ? true : false) ) { ... } | |
724 // Replace with if( x < y ) { ... } | |
725 static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) { | |
726 Node *i1 = iff->in(1); | |
727 if( !i1->is_Bool() ) return NULL; | |
728 BoolNode *bol = i1->as_Bool(); | |
729 | |
730 Node *cmp = bol->in(1); | |
731 if( cmp->Opcode() != Op_CmpI ) return NULL; | |
732 | |
733 // Must be comparing against a bool | |
734 const Type *cmp2_t = phase->type( cmp->in(2) ); | |
735 if( cmp2_t != TypeInt::ZERO && | |
736 cmp2_t != TypeInt::ONE ) | |
737 return NULL; | |
738 | |
739 // Find a prior merge point merging the boolean | |
740 i1 = cmp->in(1); | |
741 if( !i1->is_Phi() ) return NULL; | |
742 PhiNode *phi = i1->as_Phi(); | |
743 if( phase->type( phi ) != TypeInt::BOOL ) | |
744 return NULL; | |
745 | |
746 // Check for diamond pattern | |
747 int true_path = phi->is_diamond_phi(); | |
748 if( true_path == 0 ) return NULL; | |
749 | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
750 // Make sure that iff and the control of the phi are different. This |
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
751 // should really only happen for dead control flow since it requires |
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
752 // an illegal cycle. |
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
753 if (phi->in(0)->in(1)->in(0) == iff) return NULL; |
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
754 |
0 | 755 // phi->region->if_proj->ifnode->bool->cmp |
756 BoolNode *bol2 = phi->in(0)->in(1)->in(0)->in(1)->as_Bool(); | |
757 | |
758 // Now get the 'sense' of the test correct so we can plug in | |
759 // either iff2->in(1) or its complement. | |
760 int flip = 0; | |
761 if( bol->_test._test == BoolTest::ne ) flip = 1-flip; | |
762 else if( bol->_test._test != BoolTest::eq ) return NULL; | |
763 if( cmp2_t == TypeInt::ZERO ) flip = 1-flip; | |
764 | |
765 const Type *phi1_t = phase->type( phi->in(1) ); | |
766 const Type *phi2_t = phase->type( phi->in(2) ); | |
767 // Check for Phi(0,1) and flip | |
768 if( phi1_t == TypeInt::ZERO ) { | |
769 if( phi2_t != TypeInt::ONE ) return NULL; | |
770 flip = 1-flip; | |
771 } else { | |
772 // Check for Phi(1,0) | |
773 if( phi1_t != TypeInt::ONE ) return NULL; | |
774 if( phi2_t != TypeInt::ZERO ) return NULL; | |
775 } | |
776 if( true_path == 2 ) { | |
777 flip = 1-flip; | |
778 } | |
779 | |
780 Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2); | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
17
diff
changeset
|
781 assert(new_bol != iff->in(1), "must make progress"); |
0 | 782 iff->set_req(1, new_bol); |
783 // Intervening diamond probably goes dead | |
784 phase->C->set_major_progress(); | |
785 return iff; | |
786 } | |
787 | |
788 static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff); | |
789 | |
790 //------------------------------Ideal------------------------------------------ | |
791 // Return a node which is more "ideal" than the current node. Strip out | |
792 // control copies | |
793 Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) { | |
794 if (remove_dead_region(phase, can_reshape)) return this; | |
795 // No Def-Use info? | |
796 if (!can_reshape) return NULL; | |
797 PhaseIterGVN *igvn = phase->is_IterGVN(); | |
798 | |
799 // Don't bother trying to transform a dead if | |
800 if (in(0)->is_top()) return NULL; | |
801 // Don't bother trying to transform an if with a dead test | |
802 if (in(1)->is_top()) return NULL; | |
803 // Another variation of a dead test | |
804 if (in(1)->is_Con()) return NULL; | |
805 // Another variation of a dead if | |
806 if (outcnt() < 2) return NULL; | |
807 | |
808 // Canonicalize the test. | |
809 Node* idt_if = idealize_test(phase, this); | |
810 if (idt_if != NULL) return idt_if; | |
811 | |
812 // Try to split the IF | |
813 Node *s = split_if(this, igvn); | |
814 if (s != NULL) return s; | |
815 | |
816 // Check for people making a useless boolean: things like | |
817 // if( (x < y ? true : false) ) { ... } | |
818 // Replace with if( x < y ) { ... } | |
819 Node *bol2 = remove_useless_bool(this, phase); | |
820 if( bol2 ) return bol2; | |
821 | |
822 // Setup to scan up the CFG looking for a dominating test | |
823 Node *dom = in(0); | |
824 Node *prev_dom = this; | |
825 | |
826 // Check for range-check vs other kinds of tests | |
827 Node *index1, *range1; | |
828 jint offset1; | |
829 int flip1 = is_range_check(range1, index1, offset1); | |
830 if( flip1 ) { | |
831 Node *first_prev_dom = NULL; | |
832 | |
833 // Try to remove extra range checks. All 'up_one_dom' gives up at merges | |
834 // so all checks we inspect post-dominate the top-most check we find. | |
835 // If we are going to fail the current check and we reach the top check | |
605 | 836 // then we are guaranteed to fail, so just start interpreting there. |
0 | 837 // We 'expand' the top 2 range checks to include all post-dominating |
838 // checks. | |
839 | |
840 // The top 2 range checks seen | |
841 Node *prev_chk1 = NULL; | |
842 Node *prev_chk2 = NULL; | |
843 // Low and high offsets seen so far | |
844 jint off_lo = offset1; | |
845 jint off_hi = offset1; | |
846 | |
847 // Scan for the top 2 checks and collect range of offsets | |
848 for( int dist = 0; dist < 999; dist++ ) { // Range-Check scan limit | |
849 if( dom->Opcode() == Op_If && // Not same opcode? | |
850 prev_dom->in(0) == dom ) { // One path of test does dominate? | |
851 if( dom == this ) return NULL; // dead loop | |
852 // See if this is a range check | |
853 Node *index2, *range2; | |
854 jint offset2; | |
855 int flip2 = dom->as_If()->is_range_check(range2, index2, offset2); | |
856 // See if this is a _matching_ range check, checking against | |
857 // the same array bounds. | |
858 if( flip2 == flip1 && range2 == range1 && index2 == index1 && | |
859 dom->outcnt() == 2 ) { | |
860 // Gather expanded bounds | |
861 off_lo = MIN2(off_lo,offset2); | |
862 off_hi = MAX2(off_hi,offset2); | |
863 // Record top 2 range checks | |
864 prev_chk2 = prev_chk1; | |
865 prev_chk1 = prev_dom; | |
866 // If we match the test exactly, then the top test covers | |
867 // both our lower and upper bounds. | |
868 if( dom->in(1) == in(1) ) | |
869 prev_chk2 = prev_chk1; | |
870 } | |
871 } | |
872 prev_dom = dom; | |
873 dom = up_one_dom( dom ); | |
874 if( !dom ) break; | |
875 } | |
876 | |
877 | |
878 // Attempt to widen the dominating range check to cover some later | |
879 // ones. Since range checks "fail" by uncommon-trapping to the | |
880 // interpreter, widening a check can make us speculative enter the | |
881 // interpreter. If we see range-check deopt's, do not widen! | |
882 if (!phase->C->allow_range_check_smearing()) return NULL; | |
883 | |
884 // Constant indices only need to check the upper bound. | |
885 // Non-constance indices must check both low and high. | |
886 if( index1 ) { | |
887 // Didn't find 2 prior covering checks, so cannot remove anything. | |
888 if( !prev_chk2 ) return NULL; | |
889 // 'Widen' the offsets of the 1st and 2nd covering check | |
890 adjust_check( prev_chk1, range1, index1, flip1, off_lo, igvn ); | |
891 // Do not call adjust_check twice on the same projection | |
892 // as the first call may have transformed the BoolNode to a ConI | |
893 if( prev_chk1 != prev_chk2 ) { | |
894 adjust_check( prev_chk2, range1, index1, flip1, off_hi, igvn ); | |
895 } | |
896 // Test is now covered by prior checks, dominate it out | |
897 prev_dom = prev_chk2; | |
898 } else { | |
899 // Didn't find prior covering check, so cannot remove anything. | |
900 if( !prev_chk1 ) return NULL; | |
901 // 'Widen' the offset of the 1st and only covering check | |
902 adjust_check( prev_chk1, range1, index1, flip1, off_hi, igvn ); | |
903 // Test is now covered by prior checks, dominate it out | |
904 prev_dom = prev_chk1; | |
905 } | |
906 | |
907 | |
908 } else { // Scan for an equivalent test | |
909 | |
910 Node *cmp; | |
911 int dist = 0; // Cutoff limit for search | |
912 int op = Opcode(); | |
913 if( op == Op_If && | |
914 (cmp=in(1)->in(1))->Opcode() == Op_CmpP ) { | |
915 if( cmp->in(2) != NULL && // make sure cmp is not already dead | |
916 cmp->in(2)->bottom_type() == TypePtr::NULL_PTR ) { | |
917 dist = 64; // Limit for null-pointer scans | |
918 } else { | |
919 dist = 4; // Do not bother for random pointer tests | |
920 } | |
921 } else { | |
922 dist = 4; // Limit for random junky scans | |
923 } | |
924 | |
925 // Normal equivalent-test check. | |
926 if( !dom ) return NULL; // Dead loop? | |
927 | |
17
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
928 Node* result = fold_compares(phase); |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
929 if (result != NULL) { |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
930 return result; |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
931 } |
ff5961f4c095
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
never
parents:
0
diff
changeset
|
932 |
0 | 933 // Search up the dominator tree for an If with an identical test |
934 while( dom->Opcode() != op || // Not same opcode? | |
935 dom->in(1) != in(1) || // Not same input 1? | |
936 (req() == 3 && dom->in(2) != in(2)) || // Not same input 2? | |
937 prev_dom->in(0) != dom ) { // One path of test does not dominate? | |
938 if( dist < 0 ) return NULL; | |
939 | |
940 dist--; | |
941 prev_dom = dom; | |
942 dom = up_one_dom( dom ); | |
943 if( !dom ) return NULL; | |
944 } | |
945 | |
946 // Check that we did not follow a loop back to ourselves | |
947 if( this == dom ) | |
948 return NULL; | |
949 | |
950 if( dist > 2 ) // Add to count of NULL checks elided | |
951 explicit_null_checks_elided++; | |
952 | |
953 } // End of Else scan for an equivalent test | |
954 | |
955 // Hit! Remove this IF | |
956 #ifndef PRODUCT | |
957 if( TraceIterativeGVN ) { | |
958 tty->print(" Removing IfNode: "); this->dump(); | |
959 } | |
960 if( VerifyOpto && !phase->allow_progress() ) { | |
961 // Found an equivalent dominating test, | |
962 // we can not guarantee reaching a fix-point for these during iterativeGVN | |
963 // since intervening nodes may not change. | |
964 return NULL; | |
965 } | |
966 #endif | |
967 | |
968 // Replace dominated IfNode | |
969 dominated_by( prev_dom, igvn ); | |
970 | |
971 // Must return either the original node (now dead) or a new node | |
972 // (Do not return a top here, since that would break the uniqueness of top.) | |
973 return new (phase->C, 1) ConINode(TypeInt::ZERO); | |
974 } | |
975 | |
976 //------------------------------dominated_by----------------------------------- | |
977 void IfNode::dominated_by( Node *prev_dom, PhaseIterGVN *igvn ) { | |
978 igvn->hash_delete(this); // Remove self to prevent spurious V-N | |
979 Node *idom = in(0); | |
980 // Need opcode to decide which way 'this' test goes | |
981 int prev_op = prev_dom->Opcode(); | |
982 Node *top = igvn->C->top(); // Shortcut to top | |
983 | |
984 // Now walk the current IfNode's projections. | |
985 // Loop ends when 'this' has no more uses. | |
986 for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) { | |
987 Node *ifp = last_out(i); // Get IfTrue/IfFalse | |
988 igvn->add_users_to_worklist(ifp); | |
989 // Check which projection it is and set target. | |
990 // Data-target is either the dominating projection of the same type | |
991 // or TOP if the dominating projection is of opposite type. | |
992 // Data-target will be used as the new control edge for the non-CFG | |
993 // nodes like Casts and Loads. | |
994 Node *data_target = (ifp->Opcode() == prev_op ) ? prev_dom : top; | |
995 // Control-target is just the If's immediate dominator or TOP. | |
996 Node *ctrl_target = (ifp->Opcode() == prev_op ) ? idom : top; | |
997 | |
998 // For each child of an IfTrue/IfFalse projection, reroute. | |
999 // Loop ends when projection has no more uses. | |
1000 for (DUIterator_Last jmin, j = ifp->last_outs(jmin); j >= jmin; --j) { | |
1001 Node* s = ifp->last_out(j); // Get child of IfTrue/IfFalse | |
1002 igvn->hash_delete(s); // Yank from hash table before edge hacking | |
1003 if( !s->depends_only_on_test() ) { | |
1004 // Find the control input matching this def-use edge. | |
1005 // For Regions it may not be in slot 0. | |
1006 uint l; | |
1007 for( l = 0; s->in(l) != ifp; l++ ) { } | |
1008 s->set_req(l, ctrl_target); | |
1009 } else { // Else, for control producers, | |
1010 s->set_req(0, data_target); // Move child to data-target | |
1011 } | |
1012 igvn->_worklist.push(s); // Revisit collapsed Phis | |
1013 } // End for each child of a projection | |
1014 | |
1015 igvn->remove_dead_node(ifp); | |
1016 } // End for each IfTrue/IfFalse child of If | |
1017 | |
1018 // Kill the IfNode | |
1019 igvn->remove_dead_node(this); | |
1020 } | |
1021 | |
1022 //------------------------------Identity--------------------------------------- | |
1023 // If the test is constant & we match, then we are the input Control | |
1024 Node *IfTrueNode::Identity( PhaseTransform *phase ) { | |
1025 // Can only optimize if cannot go the other way | |
1026 const TypeTuple *t = phase->type(in(0))->is_tuple(); | |
1027 return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFTRUE ) | |
1028 ? in(0)->in(0) // IfNode control | |
1029 : this; // no progress | |
1030 } | |
1031 | |
1032 //------------------------------dump_spec-------------------------------------- | |
1033 #ifndef PRODUCT | |
1034 void IfNode::dump_spec(outputStream *st) const { | |
1035 st->print("P=%f, C=%f",_prob,_fcnt); | |
1036 } | |
1037 #endif | |
1038 | |
1039 //------------------------------idealize_test---------------------------------- | |
1040 // Try to canonicalize tests better. Peek at the Cmp/Bool/If sequence and | |
1041 // come up with a canonical sequence. Bools getting 'eq', 'gt' and 'ge' forms | |
1042 // converted to 'ne', 'le' and 'lt' forms. IfTrue/IfFalse get swapped as | |
1043 // needed. | |
1044 static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff) { | |
1045 assert(iff->in(0) != NULL, "If must be live"); | |
1046 | |
1047 if (iff->outcnt() != 2) return NULL; // Malformed projections. | |
1048 Node* old_if_f = iff->proj_out(false); | |
1049 Node* old_if_t = iff->proj_out(true); | |
1050 | |
1051 // CountedLoopEnds want the back-control test to be TRUE, irregardless of | |
1052 // whether they are testing a 'gt' or 'lt' condition. The 'gt' condition | |
1053 // happens in count-down loops | |
1054 if (iff->is_CountedLoopEnd()) return NULL; | |
1055 if (!iff->in(1)->is_Bool()) return NULL; // Happens for partially optimized IF tests | |
1056 BoolNode *b = iff->in(1)->as_Bool(); | |
1057 BoolTest bt = b->_test; | |
1058 // Test already in good order? | |
1059 if( bt.is_canonical() ) | |
1060 return NULL; | |
1061 | |
1062 // Flip test to be canonical. Requires flipping the IfFalse/IfTrue and | |
1063 // cloning the IfNode. | |
1064 Node* new_b = phase->transform( new (phase->C, 2) BoolNode(b->in(1), bt.negate()) ); | |
1065 if( !new_b->is_Bool() ) return NULL; | |
1066 b = new_b->as_Bool(); | |
1067 | |
1068 PhaseIterGVN *igvn = phase->is_IterGVN(); | |
1069 assert( igvn, "Test is not canonical in parser?" ); | |
1070 | |
1071 // The IF node never really changes, but it needs to be cloned | |
1072 iff = new (phase->C, 2) IfNode( iff->in(0), b, 1.0-iff->_prob, iff->_fcnt); | |
1073 | |
1074 Node *prior = igvn->hash_find_insert(iff); | |
1075 if( prior ) { | |
1076 igvn->remove_dead_node(iff); | |
1077 iff = (IfNode*)prior; | |
1078 } else { | |
1079 // Cannot call transform on it just yet | |
1080 igvn->set_type_bottom(iff); | |
1081 } | |
1082 igvn->_worklist.push(iff); | |
1083 | |
1084 // Now handle projections. Cloning not required. | |
1085 Node* new_if_f = (Node*)(new (phase->C, 1) IfFalseNode( iff )); | |
1086 Node* new_if_t = (Node*)(new (phase->C, 1) IfTrueNode ( iff )); | |
1087 | |
1088 igvn->register_new_node_with_optimizer(new_if_f); | |
1089 igvn->register_new_node_with_optimizer(new_if_t); | |
1090 // Flip test, so flip trailing control | |
1621
6027dddc26c6
6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents:
1552
diff
changeset
|
1091 igvn->replace_node(old_if_f, new_if_t); |
6027dddc26c6
6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents:
1552
diff
changeset
|
1092 igvn->replace_node(old_if_t, new_if_f); |
0 | 1093 |
1094 // Progress | |
1095 return iff; | |
1096 } | |
1097 | |
1098 //------------------------------Identity--------------------------------------- | |
1099 // If the test is constant & we match, then we are the input Control | |
1100 Node *IfFalseNode::Identity( PhaseTransform *phase ) { | |
1101 // Can only optimize if cannot go the other way | |
1102 const TypeTuple *t = phase->type(in(0))->is_tuple(); | |
1103 return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFFALSE ) | |
1104 ? in(0)->in(0) // IfNode control | |
1105 : this; // no progress | |
1106 } |