src/share/vm/opto/phaseX.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File JDK-8034216 Cdiff src/share/vm/opto/phaseX.cpp

src/share/vm/opto/phaseX.cpp

Print this page

        

*** 832,841 **** --- 832,842 ---- } #ifndef PRODUCT void PhaseIterGVN::verify_step(Node* n) { + if (VerifyIterativeGVN) { _verify_window[_verify_counter % _verify_window_size] = n; ++_verify_counter; ResourceMark rm; ResourceArea *area = Thread::current()->resource_area(); VectorSet old_space(area), new_space(area);
*** 853,862 **** --- 854,864 ---- --i; continue; } // Typical fanout is 1-2, so this call visits about 6 nodes. Node::verify_recur(n, verify_depth, old_space, new_space); } + } } #endif //------------------------------init_worklist----------------------------------
*** 869,939 **** Node *m = n->in(i); if( m ) init_worklist(m); } } - //------------------------------optimize--------------------------------------- - void PhaseIterGVN::optimize() { - debug_only(uint num_processed = 0;); - #ifndef PRODUCT - { - _verify_counter = 0; - _verify_full_passes = 0; - for ( int i = 0; i < _verify_window_size; i++ ) { - _verify_window[i] = NULL; - } - } - #endif - - #ifdef ASSERT - Node* prev = NULL; - uint rep_cnt = 0; - #endif - uint loop_count = 0; - - // Pull from worklist; transform node; - // If node has changed: update edge info and put uses on worklist. - while( _worklist.size() ) { - if (C->check_node_count(NodeLimitFudgeFactor * 2, - "out of nodes optimizing method")) { - return; - } - Node *n = _worklist.pop(); - if (++loop_count >= K * C->live_nodes()) { - debug_only(n->dump(4);) - assert(false, "infinite loop in PhaseIterGVN::optimize"); - C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); - return; - } - #ifdef ASSERT - if (n == prev) { - if (++rep_cnt > 3) { - n->dump(4); - assert(false, "loop in Ideal transformation"); - } - } else { - rep_cnt = 0; - } - prev = n; - #endif - if (TraceIterativeGVN && Verbose) { - tty->print(" Pop "); - NOT_PRODUCT( n->dump(); ) - debug_only(if( (num_processed++ % 100) == 0 ) _worklist.print_set();) - } - - if (n->outcnt() != 0) { - - #ifndef PRODUCT - uint wlsize = _worklist.size(); - const Type* oldtype = type_or_null(n); - #endif //PRODUCT - - Node *nn = transform_old(n); - #ifndef PRODUCT if (TraceIterativeGVN) { const Type* newtype = type_or_null(n); if (nn != n) { // print old node tty->print("< "); if (oldtype != newtype && oldtype != NULL) { --- 871,884 ---- Node *m = n->in(i); if( m ) init_worklist(m); } } #ifndef PRODUCT + void PhaseIterGVN::trace_PhaseIterGVN(Node* n, Node* nn, const Type* oldtype) { if (TraceIterativeGVN) { + uint wlsize = _worklist.size(); const Type* newtype = type_or_null(n); if (nn != n) { // print old node tty->print("< "); if (oldtype != newtype && oldtype != NULL) {
*** 967,986 **** tty->print(" %d", pushed->_idx); } tty->print_cr(" }"); } } ! if( VerifyIterativeGVN && nn != n ) { ! verify_step((Node*) NULL); // ignore n, it might be subsumed ! } ! #endif ! } else if (!n->is_top()) { ! remove_dead_node(n); ! } } ! #ifndef PRODUCT C->verify_graph_edges(); if( VerifyOpto && allow_progress() ) { // Must turn off allow_progress to enable assert and break recursion C->root()->verify(); { // Check if any progress was missed using IterGVN --- 912,932 ---- tty->print(" %d", pushed->_idx); } tty->print_cr(" }"); } } ! } ! ! void PhaseIterGVN::init_verifyPhaseIterGVN() { ! _verify_counter = 0; ! _verify_full_passes = 0; ! for ( int i = 0; i < _verify_window_size; i++ ) { ! _verify_window[i] = NULL; } + } ! void PhaseIterGVN::verify_PhaseIterGVN() { C->verify_graph_edges(); if( VerifyOpto && allow_progress() ) { // Must turn off allow_progress to enable assert and break recursion C->root()->verify(); { // Check if any progress was missed using IterGVN
*** 996,1014 **** igvn2.set_allow_progress(false); igvn2.optimize(); igvn2.set_allow_progress(true); } } ! if ( VerifyIterativeGVN && PrintOpto ) { ! if ( _verify_counter == _verify_full_passes ) tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes", _verify_full_passes); ! else tty->print_cr("VerifyIterativeGVN: %d transforms, %d full verify passes", _verify_counter, _verify_full_passes); } #endif } //------------------register_new_node_with_optimizer--------------------------- // Register a new node with the optimizer. Update the types array, the def-use --- 942,1012 ---- igvn2.set_allow_progress(false); igvn2.optimize(); igvn2.set_allow_progress(true); } } ! if (VerifyIterativeGVN && PrintOpto) { ! if ( _verify_counter == _verify_full_passes ) { tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes", _verify_full_passes); ! } else { tty->print_cr("VerifyIterativeGVN: %d transforms, %d full verify passes", _verify_counter, _verify_full_passes); } + } + } + #endif /* PRODUCT */ + + + void PhaseIterGVN::optimize() { + DEBUG_ONLY(uint num_processed = 0;) + NOT_PRODUCT(init_verifyPhaseIterGVN();) + + uint loop_count = 0; + + // Pull from worklist; transform node; + // If node has changed: update edge info and put uses on worklist. + while(_worklist.size()) { + if (C->check_node_count(NodeLimitFudgeFactor * 2, "Out of nodes")) { + return; + } + Node* n = _worklist.pop(); + if (++loop_count >= K * C->live_nodes()) { + #ifdef ASSERT + n->dump(4); + _worklist.dump(); + assert(false, "infinite loop in PhaseIterGVN::optimize"); #endif + C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize"); + return; + } + #ifdef ASSERT + if (TraceIterativeGVN && Verbose) { + tty->print(" Pop "); + n->dump(); + if( (num_processed++ % 100) == 0 ) { + _worklist.print_set(); + } + } + #endif + if (n->outcnt() != 0) { + NOT_PRODUCT(const Type* oldtype = type_or_null(n)); + + Node* nn = transform_old(n); + #ifndef PRODUCT + trace_PhaseIterGVN(n, nn, oldtype); + if (nn != n) { + // ignore n, it might be subsumed + verify_step((Node*) NULL); + } + #endif + } else if (!n->is_top()) { + remove_dead_node(n); + } + } + + NOT_PRODUCT(verify_PhaseIterGVN();) } //------------------register_new_node_with_optimizer--------------------------- // Register a new node with the optimizer. Update the types array, the def-use
*** 1036,1156 **** } return transform_old(n); } ! //------------------------------transform_old---------------------------------- ! Node *PhaseIterGVN::transform_old( Node *n ) { ! #ifndef PRODUCT ! debug_only(uint loop_count = 0;); ! set_transforms(); ! #endif // Remove 'n' from hash table in case it gets modified _table.hash_delete(n); ! if( VerifyIterativeGVN ) { ! assert( !_table.find_index(n->_idx), "found duplicate entry in table"); } // Apply the Ideal call in a loop until it no longer applies ! Node *k = n; DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) ! Node *i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT - if( VerifyIterativeGVN ) verify_step(k); ! if( i && VerifyOpto ) { ! if( !allow_progress() ) { ! if (i->is_Add() && i->outcnt() == 1) { // Switched input to left side because this is the only use ! } else if( i->is_If() && (i->in(0) == NULL) ) { // This IF is dead because it is dominated by an equivalent IF When // dominating if changed, info is not propagated sparsely to 'this' // Propagating this info further will spuriously identify other // progress. return i; } else set_progress(); ! } else set_progress(); } #endif ! while( i ) { #ifndef PRODUCT ! debug_only( if( loop_count >= K ) i->dump(4); ) assert(loop_count < K, "infinite loop in PhaseIterGVN::transform"); ! debug_only( loop_count++; ) #endif assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes"); // Made a change; put users of original Node on worklist ! add_users_to_worklist( k ); // Replacing root of transform tree? ! if( k != i ) { // Make users of old Node now use new. ! subsume_node( k, i ); k = i; } DEBUG_ONLY(dead_loop_check(k);) // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) i = k->Ideal(this, /*can_reshape=*/true); ! assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT - if( VerifyIterativeGVN ) verify_step(k); ! if( i && VerifyOpto ) set_progress(); #endif } // If brand new node, make space in type array. ensure_type_or_null(k); // See what kind of values 'k' takes on at runtime ! const Type *t = k->Value(this); assert(t != NULL, "value sanity"); // Since I just called 'Value' to compute the set of run-time values // for this Node, and 'Value' is non-local (and therefore expensive) I'll // cache Value. Later requests for the local phase->type of this Node can // use the cached Value instead of suffering with 'bottom_type'. ! if (t != type_or_null(k)) { ! NOT_PRODUCT( set_progress(); ) ! NOT_PRODUCT( inc_new_values();) set_type(k, t); // If k is a TypeNode, capture any more-precise type permanently into Node k->raise_bottom_type(t); // Move users of node to worklist ! add_users_to_worklist( k ); } - // If 'k' computes a constant, replace it with a constant ! if( t->singleton() && !k->is_Con() ) { ! NOT_PRODUCT( set_progress(); ) ! Node *con = makecon(t); // Make a constant ! add_users_to_worklist( k ); ! subsume_node( k, con ); // Everybody using k now uses con return con; } // Now check for Identities i = k->Identity(this); // Look for a nearby replacement ! if( i != k ) { // Found? Return replacement! ! NOT_PRODUCT( set_progress(); ) ! add_users_to_worklist( k ); ! subsume_node( k, i ); // Everybody using k now uses i return i; } // Global Value Numbering i = hash_find_insert(k); // Check for pre-existing node ! if( i && (i != k) ) { // Return the pre-existing node if it isn't dead ! NOT_PRODUCT( set_progress(); ) ! add_users_to_worklist( k ); ! subsume_node( k, i ); // Everybody using k now uses i return i; } // Return Idealized original return k; --- 1034,1157 ---- } return transform_old(n); } ! Node *PhaseIterGVN::transform_old(Node* n) { ! DEBUG_ONLY(uint loop_count = 0;); ! NOT_PRODUCT(set_transforms()); ! // Remove 'n' from hash table in case it gets modified _table.hash_delete(n); ! if (VerifyIterativeGVN) { ! assert(!_table.find_index(n->_idx), "found duplicate entry in table"); } // Apply the Ideal call in a loop until it no longer applies ! Node* k = n; DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) ! Node* i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT verify_step(k); ! if (i && VerifyOpto ) { ! if (!allow_progress()) { ! if (i->is_Add() && (i->outcnt() == 1)) { // Switched input to left side because this is the only use ! } else if (i->is_If() && (i->in(0) == NULL)) { // This IF is dead because it is dominated by an equivalent IF When // dominating if changed, info is not propagated sparsely to 'this' // Propagating this info further will spuriously identify other // progress. return i; } else set_progress(); ! } else { set_progress(); } + } #endif ! while (i != NULL) { #ifndef PRODUCT ! DEBUG_ONLY(if (loop_count >= K) i->dump(4);) assert(loop_count < K, "infinite loop in PhaseIterGVN::transform"); ! DEBUG_ONLY(loop_count++;) #endif assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes"); // Made a change; put users of original Node on worklist ! add_users_to_worklist(k); // Replacing root of transform tree? ! if (k != i) { // Make users of old Node now use new. ! subsume_node(k, i); k = i; } DEBUG_ONLY(dead_loop_check(k);) // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) i = k->Ideal(this, /*can_reshape=*/true); ! assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); #ifndef PRODUCT verify_step(k); ! if (i && VerifyOpto) { ! set_progress(); ! } #endif } // If brand new node, make space in type array. ensure_type_or_null(k); // See what kind of values 'k' takes on at runtime ! const Type* t = k->Value(this); assert(t != NULL, "value sanity"); // Since I just called 'Value' to compute the set of run-time values // for this Node, and 'Value' is non-local (and therefore expensive) I'll // cache Value. Later requests for the local phase->type of this Node can // use the cached Value instead of suffering with 'bottom_type'. ! if (type_or_null(k) != t) { ! #ifndef PRODUCT ! // Do not count initial visit to node as a transformation ! if (type_or_null(k) == NULL) { ! inc_new_values(); ! set_progress(); ! } ! #endif set_type(k, t); // If k is a TypeNode, capture any more-precise type permanently into Node k->raise_bottom_type(t); // Move users of node to worklist ! add_users_to_worklist(k); } // If 'k' computes a constant, replace it with a constant ! if (t->singleton() && !k->is_Con()) { ! NOT_PRODUCT(set_progress();) ! Node* con = makecon(t); // Make a constant ! add_users_to_worklist(k); ! subsume_node(k, con); // Everybody using k now uses con return con; } // Now check for Identities i = k->Identity(this); // Look for a nearby replacement ! if (i != k) { // Found? Return replacement! ! NOT_PRODUCT(set_progress();) ! add_users_to_worklist(k); ! subsume_node(k, i); // Everybody using k now uses i return i; } // Global Value Numbering i = hash_find_insert(k); // Check for pre-existing node ! if (i && (i != k)) { // Return the pre-existing node if it isn't dead ! NOT_PRODUCT(set_progress();) ! add_users_to_worklist(k); ! subsume_node(k, i); // Everybody using k now uses i return i; } // Return Idealized original return k;
src/share/vm/opto/phaseX.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File