src/share/vm/opto/phaseX.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/phaseX.cpp	Fri Apr  4 17:01:52 2014
--- new/src/share/vm/opto/phaseX.cpp	Fri Apr  4 17:01:52 2014

*** 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 **** --- 871,884 ---- 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 + 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 **** --- 912,932 ---- 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); } + } + + void PhaseIterGVN::init_verifyPhaseIterGVN() { + _verify_counter = 0; + _verify_full_passes = 0; + for ( int i = 0; i < _verify_window_size; i++ ) { + _verify_window[i] = NULL; } + } #ifndef PRODUCT + 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 **** --- 942,1012 ---- igvn2.set_allow_progress(false); igvn2.optimize(); igvn2.set_allow_progress(true); } } ! if ( VerifyIterativeGVN && PrintOpto ) { ! if ( _verify_counter == _verify_full_passes ) ! if ( _verify_counter == _verify_full_passes ) { tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes", _verify_full_passes); else + } 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 **** --- 1034,1157 ---- } return transform_old(n); } //------------------------------transform_old---------------------------------- Node *PhaseIterGVN::transform_old( Node *n ) { #ifndef PRODUCT debug_only(uint loop_count = 0;); set_transforms(); #endif + 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"); ! 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; ! 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); ! 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) { ! 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) ) { ! } 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 ) { ! while (i != NULL) { #ifndef PRODUCT ! debug_only( if( loop_count >= K ) i->dump(4); ) ! DEBUG_ONLY(if (loop_count >= K) i->dump(4);) assert(loop_count < K, "infinite loop in PhaseIterGVN::transform"); ! debug_only( loop_count++; ) ! 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 ) { ! 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(); ! 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); ! 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();) ! 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 ! 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 ! 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) ) { ! 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 ! 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