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