Tue, 24 Jul 2012 13:16:26 -0400
Merge
1.1 --- a/src/share/vm/opto/phaseX.cpp Mon Jul 23 13:04:59 2012 -0700 1.2 +++ b/src/share/vm/opto/phaseX.cpp Tue Jul 24 13:16:26 2012 -0400 1.3 @@ -757,6 +757,7 @@ 1.4 //------------------------------PhaseIterGVN----------------------------------- 1.5 // Initialize hash table to fresh and clean for +VerifyOpto 1.6 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ), 1.7 + _stack(C->unique() >> 1), 1.8 _delay_transform(false) { 1.9 } 1.10 1.11 @@ -764,6 +765,7 @@ 1.12 // Initialize with previous PhaseIterGVN info; used by PhaseCCP 1.13 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), 1.14 _worklist( igvn->_worklist ), 1.15 + _stack( igvn->_stack ), 1.16 _delay_transform(igvn->_delay_transform) 1.17 { 1.18 } 1.19 @@ -772,6 +774,7 @@ 1.20 // Initialize with previous PhaseGVN info from Parser 1.21 PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), 1.22 _worklist(*C->for_igvn()), 1.23 + _stack(C->unique() >> 1), 1.24 _delay_transform(false) 1.25 { 1.26 uint max; 1.27 @@ -1138,51 +1141,77 @@ 1.28 // Kill a globally dead Node. All uses are also globally dead and are 1.29 // aggressively trimmed. 1.30 void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { 1.31 - assert(dead != C->root(), "killing root, eh?"); 1.32 - if (dead->is_top()) return; 1.33 - NOT_PRODUCT( set_progress(); ) 1.34 - // Remove from iterative worklist 1.35 - _worklist.remove(dead); 1.36 - if (!dead->is_Con()) { // Don't kill cons but uses 1.37 - // Remove from hash table 1.38 - _table.hash_delete( dead ); 1.39 - // Smash all inputs to 'dead', isolating him completely 1.40 - for( uint i = 0; i < dead->req(); i++ ) { 1.41 - Node *in = dead->in(i); 1.42 - if( in ) { // Points to something? 1.43 - dead->set_req(i,NULL); // Kill the edge 1.44 - if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? 1.45 - remove_dead_node(in); // Recursively remove 1.46 - } else if (in->outcnt() == 1 && 1.47 - in->has_special_unique_user()) { 1.48 - _worklist.push(in->unique_out()); 1.49 - } else if (in->outcnt() <= 2 && dead->is_Phi()) { 1.50 - if( in->Opcode() == Op_Region ) 1.51 - _worklist.push(in); 1.52 - else if( in->is_Store() ) { 1.53 - DUIterator_Fast imax, i = in->fast_outs(imax); 1.54 - _worklist.push(in->fast_out(i)); 1.55 - i++; 1.56 - if(in->outcnt() == 2) { 1.57 - _worklist.push(in->fast_out(i)); 1.58 - i++; 1.59 + enum DeleteProgress { 1.60 + PROCESS_INPUTS, 1.61 + PROCESS_OUTPUTS 1.62 + }; 1.63 + assert(_stack.is_empty(), "not empty"); 1.64 + _stack.push(dead, PROCESS_INPUTS); 1.65 + 1.66 + while (_stack.is_nonempty()) { 1.67 + dead = _stack.node(); 1.68 + uint progress_state = _stack.index(); 1.69 + assert(dead != C->root(), "killing root, eh?"); 1.70 + assert(!dead->is_top(), "add check for top when pushing"); 1.71 + NOT_PRODUCT( set_progress(); ) 1.72 + if (progress_state == PROCESS_INPUTS) { 1.73 + // After following inputs, continue to outputs 1.74 + _stack.set_index(PROCESS_OUTPUTS); 1.75 + // Remove from iterative worklist 1.76 + _worklist.remove(dead); 1.77 + if (!dead->is_Con()) { // Don't kill cons but uses 1.78 + bool recurse = false; 1.79 + // Remove from hash table 1.80 + _table.hash_delete( dead ); 1.81 + // Smash all inputs to 'dead', isolating him completely 1.82 + for( uint i = 0; i < dead->req(); i++ ) { 1.83 + Node *in = dead->in(i); 1.84 + if( in ) { // Points to something? 1.85 + dead->set_req(i,NULL); // Kill the edge 1.86 + if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? 1.87 + _stack.push(in, PROCESS_INPUTS); // Recursively remove 1.88 + recurse = true; 1.89 + } else if (in->outcnt() == 1 && 1.90 + in->has_special_unique_user()) { 1.91 + _worklist.push(in->unique_out()); 1.92 + } else if (in->outcnt() <= 2 && dead->is_Phi()) { 1.93 + if( in->Opcode() == Op_Region ) 1.94 + _worklist.push(in); 1.95 + else if( in->is_Store() ) { 1.96 + DUIterator_Fast imax, i = in->fast_outs(imax); 1.97 + _worklist.push(in->fast_out(i)); 1.98 + i++; 1.99 + if(in->outcnt() == 2) { 1.100 + _worklist.push(in->fast_out(i)); 1.101 + i++; 1.102 + } 1.103 + assert(!(i < imax), "sanity"); 1.104 + } 1.105 } 1.106 - assert(!(i < imax), "sanity"); 1.107 } 1.108 } 1.109 + 1.110 + if (dead->is_macro()) { 1.111 + C->remove_macro_node(dead); 1.112 + } 1.113 + 1.114 + if (recurse) { 1.115 + continue; 1.116 + } 1.117 } 1.118 } 1.119 1.120 - if (dead->is_macro()) { 1.121 - C->remove_macro_node(dead); 1.122 + // Aggressively kill globally dead uses 1.123 + // (Rather than pushing all the outs at once, we push one at a time, 1.124 + // plus the parent to resume later, because of the indefinite number 1.125 + // of edge deletions per loop trip.) 1.126 + if (dead->outcnt() > 0) { 1.127 + // Recursively remove 1.128 + _stack.push(dead->raw_out(0), PROCESS_INPUTS); 1.129 + } else { 1.130 + _stack.pop(); 1.131 } 1.132 } 1.133 - // Aggressively kill globally dead uses 1.134 - // (Cannot use DUIterator_Last because of the indefinite number 1.135 - // of edge deletions per loop trip.) 1.136 - while (dead->outcnt() > 0) { 1.137 - remove_globally_dead_node(dead->raw_out(0)); 1.138 - } 1.139 } 1.140 1.141 //------------------------------subsume_node-----------------------------------
2.1 --- a/src/share/vm/opto/phaseX.hpp Mon Jul 23 13:04:59 2012 -0700 2.2 +++ b/src/share/vm/opto/phaseX.hpp Tue Jul 24 13:16:26 2012 -0400 2.3 @@ -403,6 +403,8 @@ 2.4 // Subsume users of node 'old' into node 'nn' 2.5 void subsume_node( Node *old, Node *nn ); 2.6 2.7 + Node_Stack _stack; // Stack used to avoid recursion 2.8 + 2.9 protected: 2.10 2.11 // Idealize new Node 'n' with respect to its inputs and its value 2.12 @@ -438,8 +440,8 @@ 2.13 // It is significant only for debugging and profiling. 2.14 Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL); 2.15 2.16 - // Kill a globally dead Node. It is allowed to have uses which are 2.17 - // assumed dead and left 'in limbo'. 2.18 + // Kill a globally dead Node. All uses are also globally dead and are 2.19 + // aggressively trimmed. 2.20 void remove_globally_dead_node( Node *dead ); 2.21 2.22 // Kill all inputs to a dead node, recursively making more dead nodes.