# HG changeset patch # User kvn # Date 1339543411 25200 # Node ID 5e990493719ed88c0384908a68f759ff64621bb0 # Parent 8b0a4867acf0f1f23ff26119e6ca91c530cd738a 7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable Summary: replace frequent C2 optimizer code patterns with new methods calls Reviewed-by: kvn, twisti Contributed-by: vladimir.x.ivanov@oracle.com diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/domgraph.cpp --- a/src/share/vm/opto/domgraph.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/domgraph.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -465,15 +465,11 @@ // Kill dead input path assert( !visited.test(whead->in(i)->_idx), "input with no loop must be dead" ); - _igvn.hash_delete(whead); - whead->del_req(i); - _igvn._worklist.push(whead); + _igvn.delete_input_of(whead, i); for (DUIterator_Fast jmax, j = whead->fast_outs(jmax); j < jmax; j++) { Node* p = whead->fast_out(j); if( p->is_Phi() ) { - _igvn.hash_delete(p); - p->del_req(i); - _igvn._worklist.push(p); + _igvn.delete_input_of(p, i); } } i--; // Rerun same iteration diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/ifnode.cpp --- a/src/share/vm/opto/ifnode.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/ifnode.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -338,8 +338,7 @@ Node *phi_f = NULL; // do not construct unless needed for (DUIterator_Last i2min, i2 = phi->last_outs(i2min); i2 >= i2min; --i2) { Node* v = phi->last_out(i2);// User of the phi - igvn->hash_delete(v); // Have to fixup other Phi users - igvn->_worklist.push(v); + igvn->rehash_node_delayed(v); // Have to fixup other Phi users uint vop = v->Opcode(); Node *proj = NULL; if( vop == Op_Phi ) { // Remote merge point @@ -552,9 +551,8 @@ if( new_cmp == cmp ) return; // Else, adjust existing check Node *new_bol = gvn->transform( new (gvn->C, 2) BoolNode( new_cmp, bol->as_Bool()->_test._test ) ); - igvn->hash_delete( iff ); + igvn->rehash_node_delayed( iff ); iff->set_req_X( 1, new_bol, igvn ); - igvn->_worklist.push( iff ); } //------------------------------up_one_dom------------------------------------- @@ -732,9 +730,7 @@ Node* adjusted = phase->transform(new (phase->C, 3) SubINode(n, phase->intcon(failtype->_lo))); Node* newcmp = phase->transform(new (phase->C, 3) CmpUNode(adjusted, phase->intcon(bound))); Node* newbool = phase->transform(new (phase->C, 2) BoolNode(newcmp, cond)); - phase->hash_delete(dom_iff); - dom_iff->set_req(1, phase->intcon(ctrl->as_Proj()->_con)); - phase->is_IterGVN()->_worklist.push(dom_iff); + phase->is_IterGVN()->replace_input_of(dom_iff, 1, phase->intcon(ctrl->as_Proj()->_con)); phase->hash_delete(this); set_req(1, newbool); return this; @@ -1042,17 +1038,15 @@ // Loop ends when projection has no more uses. for (DUIterator_Last jmin, j = ifp->last_outs(jmin); j >= jmin; --j) { Node* s = ifp->last_out(j); // Get child of IfTrue/IfFalse - igvn->hash_delete(s); // Yank from hash table before edge hacking if( !s->depends_only_on_test() ) { // Find the control input matching this def-use edge. // For Regions it may not be in slot 0. uint l; for( l = 0; s->in(l) != ifp; l++ ) { } - s->set_req(l, ctrl_target); + igvn->replace_input_of(s, l, ctrl_target); } else { // Else, for control producers, - s->set_req(0, data_target); // Move child to data-target + igvn->replace_input_of(s, 0, data_target); // Move child to data-target } - igvn->_worklist.push(s); // Revisit collapsed Phis } // End for each child of a projection igvn->remove_dead_node(ifp); diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/loopPredicate.cpp --- a/src/share/vm/opto/loopPredicate.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/loopPredicate.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -212,9 +212,8 @@ Node* use = rgn->fast_out(i); if (use->is_Phi() && use->outcnt() > 0) { assert(use->in(0) == rgn, ""); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); use->add_req(use->in(proj_index)); - _igvn._worklist.push(use); has_phi = true; } } @@ -284,9 +283,8 @@ for (DUIterator_Fast imax, i = rgn->fast_outs(imax); i < imax; i++) { Node* use = rgn->fast_out(i); if (use->is_Phi() && use->outcnt() > 0) { - hash_delete(use); + rehash_node_delayed(use); use->add_req(use->in(proj_index)); - _worklist.push(use); has_phi = true; } } diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/loopTransform.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -961,9 +961,7 @@ set_loop(zer_iff, loop->_parent); // Plug in the false-path, taken if we need to skip post-loop - _igvn.hash_delete( main_exit ); - main_exit->set_req(0, zer_iff); - _igvn._worklist.push(main_exit); + _igvn.replace_input_of(main_exit, 0, zer_iff); set_idom(main_exit, zer_iff, dd_main_exit); set_idom(main_exit->unique_out(), zer_iff, dd_main_exit); // Make the true-path, must enter the post loop @@ -1956,9 +1954,7 @@ C->set_major_progress(); Node *kill_con = _igvn.intcon( 1-flip ); set_ctrl(kill_con, C->root()); - _igvn.hash_delete(iff); - iff->set_req(1, kill_con); - _igvn._worklist.push(iff); + _igvn.replace_input_of(iff, 1, kill_con); // Find surviving projection assert(iff->is_If(), ""); ProjNode* dp = ((IfNode*)iff)->proj_out(1-flip); @@ -1966,11 +1962,9 @@ for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { Node* cd = dp->fast_out(i); // Control-dependent node if( cd->is_Load() ) { // Loads can now float around in the loop - _igvn.hash_delete(cd); // Allow the load to float around in the loop, or before it // but NOT before the pre-loop. - cd->set_req(0, ctrl); // ctrl, not NULL - _igvn._worklist.push(cd); + _igvn.replace_input_of(cd, 0, ctrl); // ctrl, not NULL --i; --imax; } @@ -2029,14 +2023,10 @@ main_bol->set_req(1,main_cmp); } // Hack the now-private loop bounds - _igvn.hash_delete(main_cmp); - main_cmp->set_req(2, main_limit); - _igvn._worklist.push(main_cmp); + _igvn.replace_input_of(main_cmp, 2, main_limit); // The OpaqueNode is unshared by design - _igvn.hash_delete(opqzm); assert( opqzm->outcnt() == 1, "cannot hack shared node" ); - opqzm->set_req(1,main_limit); - _igvn._worklist.push(opqzm); + _igvn.replace_input_of(opqzm, 1, main_limit); } //------------------------------DCE_loop_body---------------------------------- @@ -2178,9 +2168,7 @@ Node* cmp = cl->loopexit()->cmp_node(); assert(cl->limit() == cmp->in(2), "sanity"); phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist - phase->_igvn.hash_delete(cmp); - cmp->set_req(2, exact_limit); - phase->_igvn._worklist.push(cmp); // put cmp on worklist + phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist } // Note: the final value after increment should not overflow since // counted loop has limit check predicate. diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/loopUnswitch.cpp --- a/src/share/vm/opto/loopUnswitch.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/loopUnswitch.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -174,27 +174,21 @@ Node* use = worklist.pop(); Node* nuse = use->clone(); nuse->set_req(0, invar_proj); - _igvn.hash_delete(use); - use->set_req(1, nuse); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, 1, nuse); register_new_node(nuse, invar_proj); // Same for the clone Node* use_clone = old_new[use->_idx]; - _igvn.hash_delete(use_clone); - use_clone->set_req(1, nuse); - _igvn._worklist.push(use_clone); + _igvn.replace_input_of(use_clone, 1, nuse); } } // Hardwire the control paths in the loops into if(true) and if(false) - _igvn.hash_delete(unswitch_iff); + _igvn.rehash_node_delayed(unswitch_iff); short_circuit_if(unswitch_iff, proj_true); - _igvn._worklist.push(unswitch_iff); IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If(); - _igvn.hash_delete(unswitch_iff_clone); + _igvn.rehash_node_delayed(unswitch_iff_clone); short_circuit_if(unswitch_iff_clone, proj_false); - _igvn._worklist.push(unswitch_iff_clone); // Reoptimize loops loop->record_for_igvn(); @@ -224,8 +218,7 @@ LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); Node* entry = head->in(LoopNode::EntryControl); - _igvn.hash_delete(entry); - _igvn._worklist.push(entry); + _igvn.rehash_node_delayed(entry); IdealLoopTree* outer_loop = loop->_parent; Node *cont = _igvn.intcon(1); @@ -249,18 +242,14 @@ // Fast (true) control Node* iffast_pred = clone_loop_predicates(entry, iffast, !counted_loop); - _igvn.hash_delete(head); - head->set_req(LoopNode::EntryControl, iffast_pred); + _igvn.replace_input_of(head, LoopNode::EntryControl, iffast_pred); set_idom(head, iffast_pred, dom_depth(head)); - _igvn._worklist.push(head); // Slow (false) control Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); LoopNode* slow_head = old_new[head->_idx]->as_Loop(); - _igvn.hash_delete(slow_head); - slow_head->set_req(LoopNode::EntryControl, ifslow_pred); + _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow_pred); set_idom(slow_head, ifslow_pred, dom_depth(slow_head)); - _igvn._worklist.push(slow_head); recompute_dom_depth(); diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/loopnode.cpp --- a/src/share/vm/opto/loopnode.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/loopnode.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -1129,8 +1129,7 @@ // I'm mid-iteration over the Region's uses. for (DUIterator_Last imin, i = old_phi->last_outs(imin); i >= imin; ) { Node* use = old_phi->last_out(i); - igvn.hash_delete(use); - igvn._worklist.push(use); + igvn.rehash_node_delayed(use); uint uses_found = 0; for (uint j = 0; j < use->len(); j++) { if (use->in(j) == old_phi) { @@ -1186,10 +1185,8 @@ phi->init_req(LoopNode::LoopBackControl, old_phi->in(outer_idx)); phi = igvn.register_new_node_with_optimizer(phi, old_phi); // Make old Phi point to new Phi on the fall-in path - igvn.hash_delete(old_phi); - old_phi->set_req(LoopNode::EntryControl, phi); + igvn.replace_input_of(old_phi, LoopNode::EntryControl, phi); old_phi->del_req(outer_idx); - igvn._worklist.push(old_phi); } } @@ -1992,9 +1989,7 @@ // we do it here. for( uint i = 1; i < C->root()->req(); i++ ) { if( !_nodes[C->root()->in(i)->_idx] ) { // Dead path into Root? - _igvn.hash_delete(C->root()); - C->root()->del_req(i); - _igvn._worklist.push(C->root()); + _igvn.delete_input_of(C->root(), i); i--; // Rerun same iteration on compressed edges } } diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/loopopts.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -216,9 +216,7 @@ Node *con = _igvn.makecon(pop == Op_IfTrue ? TypeInt::ONE : TypeInt::ZERO); set_ctrl(con, C->root()); // Constant gets a new use // Hack the dominated test - _igvn.hash_delete(iff); - iff->set_req(1, con); - _igvn._worklist.push(iff); + _igvn.replace_input_of(iff, 1, con); // If I dont have a reachable TRUE and FALSE path following the IfNode then // I can assume this path reaches an infinite loop. In this case it's not @@ -245,10 +243,8 @@ Node* cd = dp->fast_out(i); // Control-dependent node if (cd->depends_only_on_test()) { assert(cd->in(0) == dp, ""); - _igvn.hash_delete(cd); - cd->set_req(0, prevdom); + _igvn.replace_input_of(cd, 0, prevdom); set_early_ctrl(cd); - _igvn._worklist.push(cd); IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); if (old_loop != new_loop) { if (!old_loop->_child) old_loop->_body.yank(cd); @@ -952,8 +948,7 @@ if (!n->is_Load() || late_load_ctrl != n_ctrl) { for (DUIterator_Last jmin, j = n->last_outs(jmin); j >= jmin; ) { Node *u = n->last_out(j); // Clone private computation per use - _igvn.hash_delete(u); - _igvn._worklist.push(u); + _igvn.rehash_node_delayed(u); Node *x = n->clone(); // Clone computation Node *x_ctrl = NULL; if( u->is_Phi() ) { @@ -1089,9 +1084,7 @@ for( i = 1; i < phi->req(); i++ ) { Node *b = phi->in(i); if( b->is_Phi() ) { - _igvn.hash_delete(phi); - _igvn._worklist.push(phi); - phi->set_req(i, clone_iff( b->as_Phi(), loop )); + _igvn.replace_input_of(phi, i, clone_iff( b->as_Phi(), loop )); } else { assert( b->is_Bool(), "" ); } @@ -1161,9 +1154,7 @@ for( i = 1; i < phi->req(); i++ ) { Node *b = phi->in(i); if( b->is_Phi() ) { - _igvn.hash_delete(phi); - _igvn._worklist.push(phi); - phi->set_req(i, clone_bool( b->as_Phi(), loop )); + _igvn.replace_input_of(phi, i, clone_bool( b->as_Phi(), loop )); } else { assert( b->is_Cmp() || b->is_top(), "inputs are all Cmp or TOP" ); } @@ -1347,8 +1338,7 @@ // The original user of 'use' uses 'r' instead. for (DUIterator_Last lmin, l = use->last_outs(lmin); l >= lmin;) { Node* useuse = use->last_out(l); - _igvn.hash_delete(useuse); - _igvn._worklist.push(useuse); + _igvn.rehash_node_delayed(useuse); uint uses_found = 0; if( useuse->in(0) == use ) { useuse->set_req(0, r); @@ -1435,9 +1425,7 @@ if( use->is_Phi() ) // Phi use is in prior block cfg = prev->in(idx); // NOT in block of Phi itself if (cfg->is_top()) { // Use is dead? - _igvn.hash_delete(use); - _igvn._worklist.push(use); - use->set_req(idx, C->top()); + _igvn.replace_input_of(use, idx, C->top()); continue; } @@ -1487,9 +1475,7 @@ set_ctrl(phi, prev); } // Make 'use' use the Phi instead of the old loop body exit value - _igvn.hash_delete(use); - _igvn._worklist.push(use); - use->set_req(idx, phi); + _igvn.replace_input_of(use, idx, phi); if( use->_idx >= new_counter ) { // If updating new phis // Not needed for correctness, but prevents a weak assert // in AddPNode from tripping (when we end up with different @@ -1517,9 +1503,7 @@ Node *iff = split_if_set->pop(); if( iff->in(1)->is_Phi() ) { BoolNode *b = clone_iff( iff->in(1)->as_Phi(), loop ); - _igvn.hash_delete(iff); - _igvn._worklist.push(iff); - iff->set_req(1, b); + _igvn.replace_input_of(iff, 1, b); } } } @@ -1529,9 +1513,7 @@ Node *phi = b->in(1); assert( phi->is_Phi(), "" ); CmpNode *cmp = clone_bool( (PhiNode*)phi, loop ); - _igvn.hash_delete(b); - _igvn._worklist.push(b); - b->set_req(1, cmp); + _igvn.replace_input_of(b, 1, cmp); } } if( split_cex_set ) { @@ -1686,10 +1668,8 @@ ProjNode *other_proj = iff->proj_out(!proj->is_IfTrue())->as_Proj(); int ddepth = dom_depth(proj); - _igvn.hash_delete(iff); - _igvn._worklist.push(iff); - _igvn.hash_delete(proj); - _igvn._worklist.push(proj); + _igvn.rehash_node_delayed(iff); + _igvn.rehash_node_delayed(proj); proj->set_req(0, NULL); // temporary disconnect ProjNode* proj2 = proj_clone(proj, iff); @@ -1745,10 +1725,8 @@ ProjNode *other_proj = iff->proj_out(!proj->is_IfTrue())->as_Proj(); int ddepth = dom_depth(proj); - _igvn.hash_delete(iff); - _igvn._worklist.push(iff); - _igvn.hash_delete(proj); - _igvn._worklist.push(proj); + _igvn.rehash_node_delayed(iff); + _igvn.rehash_node_delayed(proj); proj->set_req(0, NULL); // temporary disconnect ProjNode* proj2 = proj_clone(proj, iff); @@ -1970,9 +1948,7 @@ // clone "n" and insert it between the inputs of "n" and the use outside the loop Node* n_clone = n->clone(); - _igvn.hash_delete(use); - use->set_req(j, n_clone); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, j, n_clone); Node* use_c; if (!use->is_Phi()) { use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); @@ -2028,8 +2004,7 @@ #endif while( worklist.size() ) { Node *use = worklist.pop(); - _igvn.hash_delete(use); - _igvn._worklist.push(use); + _igvn.rehash_node_delayed(use); for (uint j = 1; j < use->req(); j++) { if (use->in(j) == n) { use->set_req(j, n_clone); @@ -2055,9 +2030,7 @@ _igvn.remove_dead_node(phi); phi = hit; } - _igvn.hash_delete(use); - _igvn._worklist.push(use); - use->set_req(idx, phi); + _igvn.replace_input_of(use, idx, phi); } #ifdef ASSERT @@ -2630,9 +2603,7 @@ // use is in loop if (old_new[use->_idx] != NULL) { // null for dead code Node* use_clone = old_new[use->_idx]; - _igvn.hash_delete(use); - use->set_req(j, C->top()); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, j, C->top()); insert_phi_for_loop( use_clone, j, old_new[def->_idx], def, new_head_clone ); } } else { @@ -2667,46 +2638,35 @@ if (!n->is_CFG() && n->in(0) != NULL && not_peel.test(n->_idx) && peel.test(n->in(0)->_idx)) { Node* n_clone = old_new[n->_idx]; - _igvn.hash_delete(n_clone); - n_clone->set_req(0, new_head_clone); - _igvn._worklist.push(n_clone); + _igvn.replace_input_of(n_clone, 0, new_head_clone); } } // Backedge of the surviving new_head (the clone) is original last_peel - _igvn.hash_delete(new_head_clone); - new_head_clone->set_req(LoopNode::LoopBackControl, last_peel); - _igvn._worklist.push(new_head_clone); + _igvn.replace_input_of(new_head_clone, LoopNode::LoopBackControl, last_peel); // Cut first node in original not_peel set - _igvn.hash_delete(new_head); - new_head->set_req(LoopNode::EntryControl, C->top()); - new_head->set_req(LoopNode::LoopBackControl, C->top()); - _igvn._worklist.push(new_head); + _igvn.rehash_node_delayed(new_head); // Multiple edge updates: + new_head->set_req(LoopNode::EntryControl, C->top()); // use rehash_node_delayed / set_req instead of + new_head->set_req(LoopNode::LoopBackControl, C->top()); // multiple replace_input_of calls // Copy head_clone back-branch info to original head // and remove original head's loop entry and // clone head's back-branch - _igvn.hash_delete(head); - _igvn.hash_delete(head_clone); - head->set_req(LoopNode::EntryControl, head_clone->in(LoopNode::LoopBackControl)); + _igvn.rehash_node_delayed(head); // Multiple edge updates + head->set_req(LoopNode::EntryControl, head_clone->in(LoopNode::LoopBackControl)); head->set_req(LoopNode::LoopBackControl, C->top()); - head_clone->set_req(LoopNode::LoopBackControl, C->top()); - _igvn._worklist.push(head); - _igvn._worklist.push(head_clone); + _igvn.replace_input_of(head_clone, LoopNode::LoopBackControl, C->top()); // Similarly modify the phis for (DUIterator_Fast kmax, k = head->fast_outs(kmax); k < kmax; k++) { Node* use = head->fast_out(k); if (use->is_Phi() && use->outcnt() > 0) { Node* use_clone = old_new[use->_idx]; - _igvn.hash_delete(use); - _igvn.hash_delete(use_clone); - use->set_req(LoopNode::EntryControl, use_clone->in(LoopNode::LoopBackControl)); + _igvn.rehash_node_delayed(use); // Multiple edge updates + use->set_req(LoopNode::EntryControl, use_clone->in(LoopNode::LoopBackControl)); use->set_req(LoopNode::LoopBackControl, C->top()); - use_clone->set_req(LoopNode::LoopBackControl, C->top()); - _igvn._worklist.push(use); - _igvn._worklist.push(use_clone); + _igvn.replace_input_of(use_clone, LoopNode::LoopBackControl, C->top()); } } @@ -2792,8 +2752,7 @@ set_ctrl(neg_stride, C->root()); Node *post = new (C, 3) AddINode( opaq, neg_stride); register_new_node( post, u_ctrl ); - _igvn.hash_delete(use); - _igvn._worklist.push(use); + _igvn.rehash_node_delayed(use); for (uint j = 1; j < use->req(); j++) { if (use->in(j) == phi) use->set_req(j, post); diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/macro.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -1447,9 +1447,8 @@ if (!always_slow && _memproj_fallthrough != NULL) { for (DUIterator_Fast imax, i = _memproj_fallthrough->fast_outs(imax); i < imax; i++) { Node *use = _memproj_fallthrough->fast_out(i); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); imax -= replace_input(use, _memproj_fallthrough, result_phi_rawmem); - _igvn._worklist.push(use); // back up iterator --i; } @@ -1463,9 +1462,8 @@ } for (DUIterator_Fast imax, i = _memproj_catchall->fast_outs(imax); i < imax; i++) { Node *use = _memproj_catchall->fast_out(i); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); imax -= replace_input(use, _memproj_catchall, _memproj_fallthrough); - _igvn._worklist.push(use); // back up iterator --i; } @@ -1481,9 +1479,8 @@ if (_ioproj_fallthrough != NULL) { for (DUIterator_Fast imax, i = _ioproj_fallthrough->fast_outs(imax); i < imax; i++) { Node *use = _ioproj_fallthrough->fast_out(i); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); imax -= replace_input(use, _ioproj_fallthrough, result_phi_i_o); - _igvn._worklist.push(use); // back up iterator --i; } @@ -1497,9 +1494,8 @@ } for (DUIterator_Fast imax, i = _ioproj_catchall->fast_outs(imax); i < imax; i++) { Node *use = _ioproj_catchall->fast_out(i); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); imax -= replace_input(use, _ioproj_catchall, _ioproj_fallthrough); - _igvn._worklist.push(use); // back up iterator --i; } @@ -1857,18 +1853,16 @@ if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) { // Replace Box and mark eliminated all related locks and unlocks. alock->set_non_esc_obj(); - _igvn.hash_delete(alock); + _igvn.rehash_node_delayed(alock); alock->set_box_node(newbox); - _igvn._worklist.push(alock); next_edge = false; } } if (u->is_FastLock() && u->as_FastLock()->obj_node()->eqv_uncast(obj)) { FastLockNode* flock = u->as_FastLock(); assert(flock->box_node() == oldbox, "sanity"); - _igvn.hash_delete(flock); + _igvn.rehash_node_delayed(flock); flock->set_box_node(newbox); - _igvn._worklist.push(flock); next_edge = false; } @@ -1886,9 +1880,7 @@ Node* box_node = sfn->monitor_box(jvms, idx); if (box_node == oldbox && obj_node->eqv_uncast(obj)) { int j = jvms->monitor_box_offset(idx); - _igvn.hash_delete(u); - u->set_req(j, newbox); - _igvn._worklist.push(u); + _igvn.replace_input_of(u, j, newbox); next_edge = false; } } diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/phaseX.hpp --- a/src/share/vm/opto/phaseX.hpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/phaseX.hpp Tue Jun 12 16:23:31 2012 -0700 @@ -460,6 +460,25 @@ subsume_node(old, nn); } + // Delayed node rehash: remove a node from the hash table and rehash it during + // next optimizing pass + void rehash_node_delayed(Node* n) { + hash_delete(n); + _worklist.push(n); + } + + // Replace ith edge of "n" with "in" + void replace_input_of(Node* n, int i, Node* in) { + rehash_node_delayed(n); + n->set_req(i, in); + } + + // Delete ith edge of "n" + void delete_input_of(Node* n, int i) { + rehash_node_delayed(n); + n->del_req(i); + } + bool delay_transform() const { return _delay_transform; } void set_delay_transform(bool delay) { diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/split_if.cpp --- a/src/share/vm/opto/split_if.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/split_if.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -137,9 +137,7 @@ Node *iff_ctrl = iff->is_If() ? iff->in(0) : get_ctrl(iff); Node *x = bol->clone(); register_new_node(x, iff_ctrl); - _igvn.hash_delete(iff); - iff->set_req(1, x); - _igvn._worklist.push(iff); + _igvn.replace_input_of(iff, 1, x); } _igvn.remove_dead_node( bol ); --i; @@ -151,9 +149,7 @@ assert( bol->in(1) == n, "" ); Node *x = n->clone(); register_new_node(x, get_ctrl(bol)); - _igvn.hash_delete(bol); - bol->set_req(1, x); - _igvn._worklist.push(bol); + _igvn.replace_input_of(bol, 1, x); } _igvn.remove_dead_node( n ); @@ -387,9 +383,7 @@ if( use->in(i) == def ) break; assert( i < use->req(), "def should be among use's inputs" ); - _igvn.hash_delete(use); - use->set_req(i, new_def); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, i, new_def); } //------------------------------do_split_if------------------------------------ diff -r 8b0a4867acf0 -r 5e990493719e src/share/vm/opto/superword.cpp --- a/src/share/vm/opto/superword.cpp Tue Jun 12 14:31:44 2012 -0700 +++ b/src/share/vm/opto/superword.cpp Tue Jun 12 16:23:31 2012 -0700 @@ -944,7 +944,7 @@ void SuperWord::remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, Node *uip, Unique_Node_List &sched_before) { Node* my_mem = current->in(MemNode::Memory); - _igvn.hash_delete(current); + _igvn.rehash_node_delayed(current); _igvn.hash_delete(my_mem); //remove current_store from its current position in the memmory graph @@ -952,7 +952,7 @@ Node* use = current->out(i); if (use->is_Mem()) { assert(use->in(MemNode::Memory) == current, "must be"); - _igvn.hash_delete(use); + _igvn.rehash_node_delayed(use); if (use == prev) { // connect prev to my_mem use->set_req(MemNode::Memory, my_mem); } else if (sched_before.member(use)) { @@ -962,7 +962,6 @@ _igvn.hash_delete(lip); use->set_req(MemNode::Memory, lip); } - _igvn._worklist.push(use); --i; //deleted this edge; rescan position } } @@ -976,25 +975,20 @@ Node* use = insert_pt->out(i); if (use->is_Mem()) { assert(use->in(MemNode::Memory) == insert_pt, "must be"); - _igvn.hash_delete(use); - use->set_req(MemNode::Memory, current); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, MemNode::Memory, current); --i; //deleted this edge; rescan position } else if (!sched_up && use->is_Phi() && use->bottom_type() == Type::MEMORY) { uint pos; //lip (lower insert point) must be the last one in the memory slice - _igvn.hash_delete(use); for (pos=1; pos < use->req(); pos++) { if (use->in(pos) == insert_pt) break; } - use->set_req(pos, current); - _igvn._worklist.push(use); + _igvn.replace_input_of(use, pos, current); --i; } } //connect current to insert_pt current->set_req(MemNode::Memory, insert_pt); - _igvn._worklist.push(current); } //------------------------------co_locate_pack---------------------------------- @@ -1077,15 +1071,13 @@ Node* use = current->out(i); if (use->is_Mem() && use != previous) { assert(use->in(MemNode::Memory) == current, "must be"); - _igvn.hash_delete(use); if (schedule_before_pack.member(use)) { _igvn.hash_delete(upper_insert_pt); - use->set_req(MemNode::Memory, upper_insert_pt); + _igvn.replace_input_of(use, MemNode::Memory, upper_insert_pt); } else { _igvn.hash_delete(lower_insert_pt); - use->set_req(MemNode::Memory, lower_insert_pt); + _igvn.replace_input_of(use, MemNode::Memory, lower_insert_pt); } - _igvn._worklist.push(use); --i; // deleted this edge; rescan position } } @@ -1122,9 +1114,7 @@ // Give each load the same memory state for (uint i = 0; i < pk->size(); i++) { LoadNode* ld = pk->at(i)->as_Load(); - _igvn.hash_delete(ld); - ld->set_req(MemNode::Memory, mem_input); - _igvn._worklist.push(ld); + _igvn.replace_input_of(ld, MemNode::Memory, mem_input); } } } @@ -1282,16 +1272,14 @@ // Insert extract operation _igvn.hash_delete(def); - _igvn.hash_delete(use); int def_pos = alignment(def) / data_size(def); const Type* def_t = velt_type(def); Node* ex = ExtractNode::make(_phase->C, def, def_pos, def_t); _phase->_igvn.register_new_node_with_optimizer(ex); _phase->set_ctrl(ex, _phase->get_ctrl(def)); - use->set_req(idx, ex); + _igvn.replace_input_of(use, idx, ex); _igvn._worklist.push(def); - _igvn._worklist.push(use); bb_insert_after(ex, bb_idx(def)); set_velt_type(ex, def_t);