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