--- a/hotspot/src/share/vm/opto/phaseX.cpp Thu Apr 03 12:37:53 2014 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Mon Apr 14 10:57:07 2014 +0200
@@ -831,154 +831,111 @@
}
}
+/**
+ * Initialize worklist for each node.
+ */
+void PhaseIterGVN::init_worklist(Node* first) {
+ Unique_Node_List to_process;
+ to_process.push(first);
+
+ while (to_process.size() > 0) {
+ Node* n = to_process.pop();
+ if (!_worklist.member(n)) {
+ _worklist.push(n);
+
+ uint cnt = n->req();
+ for(uint i = 0; i < cnt; i++) {
+ Node* m = n->in(i);
+ if (m != NULL) {
+ to_process.push(m);
+ }
+ }
+ }
+ }
+}
#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);
}
- // 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----------------------------------
-// Initialize worklist for each node.
-void PhaseIterGVN::init_worklist( Node *n ) {
- if( _worklist.member(n) ) return;
- _worklist.push(n);
- uint cnt = n->req();
- for( uint i =0 ; i < cnt; i++ ) {
- Node *m = n->in(i);
- if( m ) init_worklist(m);
+ 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);
+ }
}
}
-//------------------------------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;
+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();
+ }
+ 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 (nn != n) {
+ // ignore n, it might be subsumed
+ verify_step((Node*) 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) {
- 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( 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
@@ -998,21 +955,78 @@
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
+}
+#endif /* PRODUCT */
+
+#ifdef ASSERT
+/**
+ * Dumps information that can help to debug the problem. A debug
+ * build fails with an assert.
+ */
+void PhaseIterGVN::dump_infinite_loop_info(Node* n) {
+ n->dump(4);
+ _worklist.dump();
+ assert(false, "infinite loop in PhaseIterGVN::optimize");
+}
+
+/**
+ * Prints out information about IGVN if the 'verbose' option is used.
+ */
+void PhaseIterGVN::trace_PhaseIterGVN_verbose(Node* n, int num_processed) {
+ if (TraceIterativeGVN && Verbose) {
+ tty->print(" Pop ");
+ n->dump();
+ if ((num_processed % 100) == 0) {
+ _worklist.print_set();
+ }
+ }
+}
+#endif /* ASSERT */
+
+void PhaseIterGVN::optimize() {
+ DEBUG_ONLY(uint num_processed = 0;)
+ NOT_PRODUCT(init_verifyPhaseIterGVN();)
+
+ uint loop_count = 0;
+ // Pull from worklist and transform the node. If the 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()) {
+ DEBUG_ONLY(dump_infinite_loop_info(n);)
+ C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize");
+ return;
+ }
+ DEBUG_ONLY(trace_PhaseIterGVN_verbose(n, num_processed++);)
+ if (n->outcnt() != 0) {
+ NOT_PRODUCT(const Type* oldtype = type_or_null(n));
+ // Do the transformation
+ Node* nn = transform_old(n);
+ NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);)
+ } 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
-// info. Put on worklist.
+/**
+ * Register a new node with the optimizer. Update the types array, the def-use
+ * info. Put on worklist.
+ */
Node* PhaseIterGVN::register_new_node_with_optimizer(Node* n, Node* orig) {
set_type_bottom(n);
_worklist.push(n);
@@ -1038,32 +1052,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 +1082,38 @@
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); )
- assert(loop_count < K, "infinite loop in PhaseIterGVN::transform");
- debug_only( loop_count++; )
+ if (loop_count >= K) {
+ dump_infinite_loop_info(i);
+ }
+ 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 +1121,49 @@
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
+ 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;
}