--- old/src/share/vm/opto/phaseX.cpp 2014-04-04 17:01:52.949825030 +0200 +++ new/src/share/vm/opto/phaseX.cpp 2014-04-04 17:01:52.729825034 +0200 @@ -834,26 +834,28 @@ #ifndef PRODUCT void PhaseIterGVN::verify_step(Node* n) { - _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); - if (C->unique() < 1000 || - 0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) { - ++_verify_full_passes; - Node::verify_recur(C->root(), -1, old_space, new_space); - } - const int verify_depth = 4; - for ( int i = 0; i < _verify_window_size; i++ ) { - Node* n = _verify_window[i]; - if ( n == NULL ) continue; - if( n->in(0) == NodeSentinel ) { // xform_idom - _verify_window[i] = n->in(1); - --i; continue; + 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); + if (C->unique() < 1000 || + 0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) { + ++_verify_full_passes; + Node::verify_recur(C->root(), -1, old_space, new_space); + } + const int verify_depth = 4; + for ( int i = 0; i < _verify_window_size; i++ ) { + Node* n = _verify_window[i]; + if ( n == NULL ) continue; + if( n->in(0) == NodeSentinel ) { // xform_idom + _verify_window[i] = n->in(1); + --i; continue; + } + // Typical fanout is 1-2, so this call visits about 6 nodes. + Node::verify_recur(n, verify_depth, old_space, new_space); } - // Typical fanout is 1-2, so this call visits about 6 nodes. - Node::verify_recur(n, verify_depth, old_space, new_space); } } #endif @@ -871,114 +873,58 @@ } } -//------------------------------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"); +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) { + oldtype->dump(); } - } 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();) + do { tty->print("\t"); } while (tty->position() < 16); + tty->print("<"); + n->dump(); } - - 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) { - oldtype->dump(); - } - do { tty->print("\t"); } while (tty->position() < 16); - tty->print("<"); - n->dump(); - } - if (oldtype != newtype || nn != n) { - // print new node and/or new type - if (oldtype == NULL) { - tty->print("* "); - } else if (nn != n) { - tty->print("> "); - } else { - tty->print("= "); - } - if (newtype == NULL) { - tty->print("null"); - } else { - newtype->dump(); - } - do { tty->print("\t"); } while (tty->position() < 16); - nn->dump(); - } - if (Verbose && wlsize < _worklist.size()) { - tty->print(" Push {"); - while (wlsize != _worklist.size()) { - Node* pushed = _worklist.at(wlsize++); - tty->print(" %d", pushed->_idx); - } - tty->print_cr(" }"); - } + if (oldtype != newtype || nn != n) { + // print new node and/or new type + if (oldtype == NULL) { + tty->print("* "); + } else if (nn != n) { + tty->print("> "); + } else { + tty->print("= "); } - if( VerifyIterativeGVN && nn != n ) { - verify_step((Node*) NULL); // ignore n, it might be subsumed + if (newtype == NULL) { + tty->print("null"); + } else { + newtype->dump(); } -#endif - } else if (!n->is_top()) { - remove_dead_node(n); + do { tty->print("\t"); } while (tty->position() < 16); + nn->dump(); } + if (Verbose && wlsize < _worklist.size()) { + tty->print(" Push {"); + while (wlsize != _worklist.size()) { + Node* pushed = _worklist.at(wlsize++); + 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; } +} -#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 @@ -998,15 +944,67 @@ igvn2.set_allow_progress(true); } } - if ( VerifyIterativeGVN && PrintOpto ) { - if ( _verify_counter == _verify_full_passes ) + if (VerifyIterativeGVN && PrintOpto) { + 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();) } @@ -1038,32 +1036,29 @@ 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) { + 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) ) { + } 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 @@ -1071,35 +1066,37 @@ return i; } else set_progress(); - } else + } 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 ); + 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 ); + 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"); + 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(); + verify_step(k); + if (i && VerifyOpto) { + set_progress(); + } #endif } @@ -1107,48 +1104,52 @@ 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 ); + 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 + 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) ) { + 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 + NOT_PRODUCT(set_progress();) + add_users_to_worklist(k); + subsume_node(k, i); // Everybody using k now uses i return i; }