提交 654e029b 编写于 作者: N never

6862956: PhaseIdealLoop should have a CFG verification mode

Reviewed-by: kvn, twisti
上级 f0c9f327
...@@ -1545,7 +1545,7 @@ void Compile::Optimize() { ...@@ -1545,7 +1545,7 @@ void Compile::Optimize() {
if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) {
{ {
TracePhase t2("idealLoop", &_t_idealLoop, true); TracePhase t2("idealLoop", &_t_idealLoop, true);
PhaseIdealLoop ideal_loop( igvn, NULL, true ); PhaseIdealLoop ideal_loop( igvn, true );
loop_opts_cnt--; loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 1", 2); if (major_progress()) print_method("PhaseIdealLoop 1", 2);
if (failing()) return; if (failing()) return;
...@@ -1553,7 +1553,7 @@ void Compile::Optimize() { ...@@ -1553,7 +1553,7 @@ void Compile::Optimize() {
// Loop opts pass if partial peeling occurred in previous pass // Loop opts pass if partial peeling occurred in previous pass
if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) { if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) {
TracePhase t3("idealLoop", &_t_idealLoop, true); TracePhase t3("idealLoop", &_t_idealLoop, true);
PhaseIdealLoop ideal_loop( igvn, NULL, false ); PhaseIdealLoop ideal_loop( igvn, false );
loop_opts_cnt--; loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 2", 2); if (major_progress()) print_method("PhaseIdealLoop 2", 2);
if (failing()) return; if (failing()) return;
...@@ -1561,10 +1561,15 @@ void Compile::Optimize() { ...@@ -1561,10 +1561,15 @@ void Compile::Optimize() {
// Loop opts pass for loop-unrolling before CCP // Loop opts pass for loop-unrolling before CCP
if(major_progress() && (loop_opts_cnt > 0)) { if(major_progress() && (loop_opts_cnt > 0)) {
TracePhase t4("idealLoop", &_t_idealLoop, true); TracePhase t4("idealLoop", &_t_idealLoop, true);
PhaseIdealLoop ideal_loop( igvn, NULL, false ); PhaseIdealLoop ideal_loop( igvn, false );
loop_opts_cnt--; loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 3", 2); if (major_progress()) print_method("PhaseIdealLoop 3", 2);
} }
if (!failing()) {
// Verify that last round of loop opts produced a valid graph
NOT_PRODUCT( TracePhase t2("idealLoopVerify", &_t_idealLoopVerify, TimeCompiler); )
PhaseIdealLoop::verify(igvn);
}
} }
if (failing()) return; if (failing()) return;
...@@ -1597,12 +1602,20 @@ void Compile::Optimize() { ...@@ -1597,12 +1602,20 @@ void Compile::Optimize() {
while(major_progress() && (loop_opts_cnt > 0)) { while(major_progress() && (loop_opts_cnt > 0)) {
TracePhase t2("idealLoop", &_t_idealLoop, true); TracePhase t2("idealLoop", &_t_idealLoop, true);
assert( cnt++ < 40, "infinite cycle in loop optimization" ); assert( cnt++ < 40, "infinite cycle in loop optimization" );
PhaseIdealLoop ideal_loop( igvn, NULL, true ); PhaseIdealLoop ideal_loop( igvn, true );
loop_opts_cnt--; loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop iterations", 2); if (major_progress()) print_method("PhaseIdealLoop iterations", 2);
if (failing()) return; if (failing()) return;
} }
} }
{
// Verify that all previous optimizations produced a valid graph
// at least to this point, even if no loop optimizations were done.
NOT_PRODUCT( TracePhase t2("idealLoopVerify", &_t_idealLoopVerify, TimeCompiler); )
PhaseIdealLoop::verify(igvn);
}
{ {
NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); ) NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); )
PhaseMacroExpand mex(igvn); PhaseMacroExpand mex(igvn);
......
/* /*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -396,7 +396,7 @@ struct NTarjan { ...@@ -396,7 +396,7 @@ struct NTarjan {
// nodes (using the is_CFG() call) and places them in a dominator tree. Thus, // nodes (using the is_CFG() call) and places them in a dominator tree. Thus,
// it needs a count of the CFG nodes for the mapping table. This is the // it needs a count of the CFG nodes for the mapping table. This is the
// Lengauer & Tarjan O(E-alpha(E,V)) algorithm. // Lengauer & Tarjan O(E-alpha(E,V)) algorithm.
void PhaseIdealLoop::Dominators( ) { void PhaseIdealLoop::Dominators() {
ResourceMark rm; ResourceMark rm;
// Setup mappings from my Graph to Tarjan's stuff and back // Setup mappings from my Graph to Tarjan's stuff and back
// Note: Tarjan uses 1-based arrays // Note: Tarjan uses 1-based arrays
...@@ -454,7 +454,7 @@ void PhaseIdealLoop::Dominators( ) { ...@@ -454,7 +454,7 @@ void PhaseIdealLoop::Dominators( ) {
// flow into the main graph (and hence into ROOT) but are not reachable // flow into the main graph (and hence into ROOT) but are not reachable
// from above. Such code is dead, but requires a global pass to detect // from above. Such code is dead, but requires a global pass to detect
// it; this global pass was the 'build_loop_tree' pass run just prior. // it; this global pass was the 'build_loop_tree' pass run just prior.
if( whead->is_Region() ) { if( !_verify_only && whead->is_Region() ) {
for( uint i = 1; i < whead->req(); i++ ) { for( uint i = 1; i < whead->req(); i++ ) {
if (!has_node(whead->in(i))) { if (!has_node(whead->in(i))) {
// Kill dead input path // Kill dead input path
......
...@@ -1420,13 +1420,12 @@ static void log_loop_tree(IdealLoopTree* root, IdealLoopTree* loop, CompileLog* ...@@ -1420,13 +1420,12 @@ static void log_loop_tree(IdealLoopTree* root, IdealLoopTree* loop, CompileLog*
} }
//============================================================================= //=============================================================================
//------------------------------PhaseIdealLoop--------------------------------- //----------------------------build_and_optimize-------------------------------
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
// its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups.
PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me, bool do_split_ifs ) void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) {
: PhaseTransform(Ideal_Loop), int old_progress = C->major_progress();
_igvn(igvn),
_dom_lca_tags(C->comp_arena()) {
// Reset major-progress flag for the driver's heuristics // Reset major-progress flag for the driver's heuristics
C->clear_major_progress(); C->clear_major_progress();
...@@ -1465,18 +1464,20 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1465,18 +1464,20 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
} }
// No loops after all // No loops after all
if( !_ltree_root->_child ) C->set_has_loops(false); if( !_ltree_root->_child && !_verify_only ) C->set_has_loops(false);
// There should always be an outer loop containing the Root and Return nodes. // There should always be an outer loop containing the Root and Return nodes.
// If not, we have a degenerate empty program. Bail out in this case. // If not, we have a degenerate empty program. Bail out in this case.
if (!has_node(C->root())) { if (!has_node(C->root())) {
if (!_verify_only) {
C->clear_major_progress(); C->clear_major_progress();
C->record_method_not_compilable("empty program detected during loop optimization"); C->record_method_not_compilable("empty program detected during loop optimization");
}
return; return;
} }
// Nothing to do, so get out // Nothing to do, so get out
if( !C->has_loops() && !do_split_ifs && !verify_me) { if( !C->has_loops() && !do_split_ifs && !_verify_me && !_verify_only ) {
_igvn.optimize(); // Cleanup NeverBranches _igvn.optimize(); // Cleanup NeverBranches
return; return;
} }
...@@ -1486,7 +1487,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1486,7 +1487,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
// Split shared headers and insert loop landing pads. // Split shared headers and insert loop landing pads.
// Do not bother doing this on the Root loop of course. // Do not bother doing this on the Root loop of course.
if( !verify_me && _ltree_root->_child ) { if( !_verify_me && !_verify_only && _ltree_root->_child ) {
if( _ltree_root->_child->beautify_loops( this ) ) { if( _ltree_root->_child->beautify_loops( this ) ) {
// Re-build loop tree! // Re-build loop tree!
_ltree_root->_child = NULL; _ltree_root->_child = NULL;
...@@ -1515,6 +1516,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1515,6 +1516,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
Dominators(); Dominators();
if (!_verify_only) {
// As a side effect, Dominators removed any unreachable CFG paths // As a side effect, Dominators removed any unreachable CFG paths
// into RegionNodes. It doesn't do this test against Root, so // into RegionNodes. It doesn't do this test against Root, so
// we do it here. // we do it here.
...@@ -1532,6 +1534,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1532,6 +1534,7 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
// not need a separate safepoint. // not need a separate safepoint.
Node_List cisstack(a); Node_List cisstack(a);
_ltree_root->check_safepts(visited, cisstack); _ltree_root->check_safepts(visited, cisstack);
}
// Walk the DATA nodes and place into loops. Find earliest control // Walk the DATA nodes and place into loops. Find earliest control
// node. For CFG nodes, the _nodes array starts out and remains // node. For CFG nodes, the _nodes array starts out and remains
...@@ -1548,11 +1551,11 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1548,11 +1551,11 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
// it will be processed among C->top() inputs // it will be processed among C->top() inputs
worklist.push( C->top() ); worklist.push( C->top() );
visited.set( C->top()->_idx ); // Set C->top() as visited now visited.set( C->top()->_idx ); // Set C->top() as visited now
build_loop_early( visited, worklist, nstack, verify_me ); build_loop_early( visited, worklist, nstack );
// Given early legal placement, try finding counted loops. This placement // Given early legal placement, try finding counted loops. This placement
// is good enough to discover most loop invariants. // is good enough to discover most loop invariants.
if( !verify_me ) if( !_verify_me && !_verify_only )
_ltree_root->counted_loop( this ); _ltree_root->counted_loop( this );
// Find latest loop placement. Find ideal loop placement. // Find latest loop placement. Find ideal loop placement.
...@@ -1562,16 +1565,25 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify ...@@ -1562,16 +1565,25 @@ PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify
worklist.push( C->root() ); worklist.push( C->root() );
NOT_PRODUCT( C->verify_graph_edges(); ) NOT_PRODUCT( C->verify_graph_edges(); )
worklist.push( C->top() ); worklist.push( C->top() );
build_loop_late( visited, worklist, nstack, verify_me ); build_loop_late( visited, worklist, nstack );
if (_verify_only) {
// restore major progress flag
for (int i = 0; i < old_progress; i++)
C->set_major_progress();
assert(C->unique() == unique, "verification mode made Nodes? ? ?");
assert(_igvn._worklist.size() == 0, "shouldn't push anything");
return;
}
// clear out the dead code // clear out the dead code
while(_deadlist.size()) { while(_deadlist.size()) {
igvn.remove_globally_dead_node(_deadlist.pop()); _igvn.remove_globally_dead_node(_deadlist.pop());
} }
#ifndef PRODUCT #ifndef PRODUCT
C->verify_graph_edges(); C->verify_graph_edges();
if( verify_me ) { // Nested verify pass? if( _verify_me ) { // Nested verify pass?
// Check to see if the verify mode is broken // Check to see if the verify mode is broken
assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?"); assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?");
return; return;
...@@ -1678,7 +1690,7 @@ static int fail; // debug only, so its multi-thread dont care ...@@ -1678,7 +1690,7 @@ static int fail; // debug only, so its multi-thread dont care
void PhaseIdealLoop::verify() const { void PhaseIdealLoop::verify() const {
int old_progress = C->major_progress(); int old_progress = C->major_progress();
ResourceMark rm; ResourceMark rm;
PhaseIdealLoop loop_verify( _igvn, this, false ); PhaseIdealLoop loop_verify( _igvn, this );
VectorSet visited(Thread::current()->resource_area()); VectorSet visited(Thread::current()->resource_area());
fail = 0; fail = 0;
...@@ -2138,6 +2150,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) { ...@@ -2138,6 +2150,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
// optimizing an infinite loop? // optimizing an infinite loop?
l = _ltree_root; // Oops, found infinite loop l = _ltree_root; // Oops, found infinite loop
if (!_verify_only) {
// Insert the NeverBranch between 'm' and it's control user. // Insert the NeverBranch between 'm' and it's control user.
NeverBranchNode *iff = new (C, 1) NeverBranchNode( m ); NeverBranchNode *iff = new (C, 1) NeverBranchNode( m );
_igvn.register_new_node_with_optimizer(iff); _igvn.register_new_node_with_optimizer(iff);
...@@ -2171,12 +2184,14 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) { ...@@ -2171,12 +2184,14 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
_igvn.register_new_node_with_optimizer(halt); _igvn.register_new_node_with_optimizer(halt);
set_loop(halt, l); set_loop(halt, l);
C->root()->add_req(halt); C->root()->add_req(halt);
}
set_loop(C->root(), _ltree_root); set_loop(C->root(), _ltree_root);
} }
} }
// Weeny check for irreducible. This child was already visited (this // Weeny check for irreducible. This child was already visited (this
// IS the post-work phase). Is this child's loop header post-visited // IS the post-work phase). Is this child's loop header post-visited
// as well? If so, then I found another entry into the loop. // as well? If so, then I found another entry into the loop.
if (!_verify_only) {
while( is_postvisited(l->_head) ) { while( is_postvisited(l->_head) ) {
// found irreducible // found irreducible
l->_irreducible = 1; // = true l->_irreducible = 1; // = true
...@@ -2188,6 +2203,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) { ...@@ -2188,6 +2203,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
return pre_order; return pre_order;
} }
} }
}
// This Node might be a decision point for loops. It is only if // This Node might be a decision point for loops. It is only if
// it's children belong to several different loops. The sort call // it's children belong to several different loops. The sort call
...@@ -2253,7 +2269,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) { ...@@ -2253,7 +2269,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping. // Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// First pass computes the earliest controlling node possible. This is the // First pass computes the earliest controlling node possible. This is the
// controlling input with the deepest dominating depth. // controlling input with the deepest dominating depth.
void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ) { void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ) {
while (worklist.size() != 0) { while (worklist.size() != 0) {
// Use local variables nstack_top_n & nstack_top_i to cache values // Use local variables nstack_top_n & nstack_top_i to cache values
// on nstack's top. // on nstack's top.
...@@ -2285,7 +2301,7 @@ void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, ...@@ -2285,7 +2301,7 @@ void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist,
// (the old code here would yank a 2nd safepoint after seeing a // (the old code here would yank a 2nd safepoint after seeing a
// first one, even though the 1st did not dominate in the loop body // first one, even though the 1st did not dominate in the loop body
// and thus could be avoided indefinitely) // and thus could be avoided indefinitely)
if( !verify_me && ilt->_has_sfpt && n->Opcode() == Op_SafePoint && if( !_verify_only && !_verify_me && ilt->_has_sfpt && n->Opcode() == Op_SafePoint &&
is_deleteable_safept(n)) { is_deleteable_safept(n)) {
Node *in = n->in(TypeFunc::Control); Node *in = n->in(TypeFunc::Control);
lazy_replace(n,in); // Pull safepoint now lazy_replace(n,in); // Pull safepoint now
...@@ -2408,12 +2424,31 @@ Node *PhaseIdealLoop::compute_idom( Node *region ) const { ...@@ -2408,12 +2424,31 @@ Node *PhaseIdealLoop::compute_idom( Node *region ) const {
return LCA; return LCA;
} }
//------------------------------get_late_ctrl---------------------------------- bool PhaseIdealLoop::verify_dominance(Node* n, Node* use, Node* LCA, Node* early) {
// Compute latest legal control. bool had_error = false;
Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) { #ifdef ASSERT
assert(early != NULL, "early control should not be NULL"); if (early != C->root()) {
// Make sure that there's a dominance path from use to LCA
Node* d = use;
while (d != LCA) {
d = idom(d);
if (d == C->root()) {
tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx);
n->dump();
use->dump();
had_error = true;
break;
}
}
}
#endif
return had_error;
}
Node* PhaseIdealLoop::compute_lca_of_uses(Node* n, Node* early, bool verify) {
// Compute LCA over list of uses // Compute LCA over list of uses
bool had_error = false;
Node *LCA = NULL; Node *LCA = NULL;
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax && LCA != early; i++) { for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax && LCA != early; i++) {
Node* c = n->fast_out(i); Node* c = n->fast_out(i);
...@@ -2423,15 +2458,34 @@ Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) { ...@@ -2423,15 +2458,34 @@ Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) {
for( uint j=1; j<c->req(); j++ ) {// For all inputs for( uint j=1; j<c->req(); j++ ) {// For all inputs
if( c->in(j) == n ) { // Found matching input? if( c->in(j) == n ) { // Found matching input?
Node *use = c->in(0)->in(j); Node *use = c->in(0)->in(j);
if (_verify_only && use->is_top()) continue;
LCA = dom_lca_for_get_late_ctrl( LCA, use, n ); LCA = dom_lca_for_get_late_ctrl( LCA, use, n );
if (verify) had_error = verify_dominance(n, use, LCA, early) || had_error;
} }
} }
} else { } else {
// For CFG data-users, use is in the block just prior // For CFG data-users, use is in the block just prior
Node *use = has_ctrl(c) ? get_ctrl(c) : c->in(0); Node *use = has_ctrl(c) ? get_ctrl(c) : c->in(0);
LCA = dom_lca_for_get_late_ctrl( LCA, use, n ); LCA = dom_lca_for_get_late_ctrl( LCA, use, n );
if (verify) had_error = verify_dominance(n, use, LCA, early) || had_error;
} }
} }
assert(!had_error, "bad dominance");
return LCA;
}
//------------------------------get_late_ctrl----------------------------------
// Compute latest legal control.
Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) {
assert(early != NULL, "early control should not be NULL");
Node* LCA = compute_lca_of_uses(n, early);
#ifdef ASSERT
if (LCA == C->root() && LCA != early) {
// def doesn't dominate uses so print some useful debugging output
compute_lca_of_uses(n, early, true);
}
#endif
// if this is a load, check for anti-dependent stores // if this is a load, check for anti-dependent stores
// We use a conservative algorithm to identify potential interfering // We use a conservative algorithm to identify potential interfering
...@@ -2576,7 +2630,7 @@ void PhaseIdealLoop::clear_dom_lca_tags() { ...@@ -2576,7 +2630,7 @@ void PhaseIdealLoop::clear_dom_lca_tags() {
//------------------------------build_loop_late-------------------------------- //------------------------------build_loop_late--------------------------------
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping. // Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// Second pass finds latest legal placement, and ideal loop placement. // Second pass finds latest legal placement, and ideal loop placement.
void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ) { void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ) {
while (worklist.size() != 0) { while (worklist.size() != 0) {
Node *n = worklist.pop(); Node *n = worklist.pop();
// Only visit once // Only visit once
...@@ -2612,7 +2666,7 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N ...@@ -2612,7 +2666,7 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N
} }
} else { } else {
// All of n's children have been processed, complete post-processing. // All of n's children have been processed, complete post-processing.
build_loop_late_post(n, verify_me); build_loop_late_post(n);
if (nstack.is_empty()) { if (nstack.is_empty()) {
// Finished all nodes on stack. // Finished all nodes on stack.
// Process next node on the worklist. // Process next node on the worklist.
...@@ -2631,9 +2685,9 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N ...@@ -2631,9 +2685,9 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N
//------------------------------build_loop_late_post--------------------------- //------------------------------build_loop_late_post---------------------------
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping. // Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// Second pass finds latest legal placement, and ideal loop placement. // Second pass finds latest legal placement, and ideal loop placement.
void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify_me ) { void PhaseIdealLoop::build_loop_late_post( Node *n ) {
if (n->req() == 2 && n->Opcode() == Op_ConvI2L && !C->major_progress()) { if (n->req() == 2 && n->Opcode() == Op_ConvI2L && !C->major_progress() && !_verify_only) {
_igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops. _igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops.
} }
...@@ -2714,6 +2768,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify ...@@ -2714,6 +2768,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify
if( get_loop(legal)->_nest < get_loop(least)->_nest ) if( get_loop(legal)->_nest < get_loop(least)->_nest )
least = legal; least = legal;
} }
assert(early == legal || legal != C->root(), "bad dominance of inputs");
// Try not to place code on a loop entry projection // Try not to place code on a loop entry projection
// which can inhibit range check elimination. // which can inhibit range check elimination.
...@@ -2731,8 +2786,8 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify ...@@ -2731,8 +2786,8 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify
#ifdef ASSERT #ifdef ASSERT
// If verifying, verify that 'verify_me' has a legal location // If verifying, verify that 'verify_me' has a legal location
// and choose it as our location. // and choose it as our location.
if( verify_me ) { if( _verify_me ) {
Node *v_ctrl = verify_me->get_ctrl_no_update(n); Node *v_ctrl = _verify_me->get_ctrl_no_update(n);
Node *legal = LCA; Node *legal = LCA;
while( early != legal ) { // While not at earliest legal while( early != legal ) { // While not at earliest legal
if( legal == v_ctrl ) break; // Check for prior good location if( legal == v_ctrl ) break; // Check for prior good location
......
/* /*
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -442,6 +442,9 @@ class PhaseIdealLoop : public PhaseTransform { ...@@ -442,6 +442,9 @@ class PhaseIdealLoop : public PhaseTransform {
uint *_preorders; uint *_preorders;
uint _max_preorder; uint _max_preorder;
const PhaseIdealLoop* _verify_me;
bool _verify_only;
// Allocate _preorders[] array // Allocate _preorders[] array
void allocate_preorders() { void allocate_preorders() {
_max_preorder = C->unique()+8; _max_preorder = C->unique()+8;
...@@ -497,6 +500,12 @@ class PhaseIdealLoop : public PhaseTransform { ...@@ -497,6 +500,12 @@ class PhaseIdealLoop : public PhaseTransform {
Node_Array _dom_lca_tags; Node_Array _dom_lca_tags;
void init_dom_lca_tags(); void init_dom_lca_tags();
void clear_dom_lca_tags(); void clear_dom_lca_tags();
// Helper for debugging bad dominance relationships
bool verify_dominance(Node* n, Node* use, Node* LCA, Node* early);
Node* compute_lca_of_uses(Node* n, Node* early, bool verify = false);
// Inline wrapper for frequent cases: // Inline wrapper for frequent cases:
// 1) only one use // 1) only one use
// 2) a use is the same as the current LCA passed as 'n1' // 2) a use is the same as the current LCA passed as 'n1'
...@@ -511,6 +520,7 @@ class PhaseIdealLoop : public PhaseTransform { ...@@ -511,6 +520,7 @@ class PhaseIdealLoop : public PhaseTransform {
return find_non_split_ctrl(n); return find_non_split_ctrl(n);
} }
Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag ); Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag );
// true if CFG node d dominates CFG node n // true if CFG node d dominates CFG node n
bool is_dominator(Node *d, Node *n); bool is_dominator(Node *d, Node *n);
...@@ -621,9 +631,9 @@ private: ...@@ -621,9 +631,9 @@ private:
IdealLoopTree *sort( IdealLoopTree *loop, IdealLoopTree *innermost ); IdealLoopTree *sort( IdealLoopTree *loop, IdealLoopTree *innermost );
// Place Data nodes in some loop nest // Place Data nodes in some loop nest
void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ); void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack );
void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ); void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack );
void build_loop_late_post ( Node* n, const PhaseIdealLoop *verify_me ); void build_loop_late_post ( Node* n );
// Array of immediate dominance info for each CFG node indexed by node idx // Array of immediate dominance info for each CFG node indexed by node idx
private: private:
...@@ -662,6 +672,19 @@ private: ...@@ -662,6 +672,19 @@ private:
// Is safept not required by an outer loop? // Is safept not required by an outer loop?
bool is_deleteable_safept(Node* sfpt); bool is_deleteable_safept(Node* sfpt);
// Perform verification that the graph is valid.
PhaseIdealLoop( PhaseIterGVN &igvn) :
PhaseTransform(Ideal_Loop),
_igvn(igvn),
_dom_lca_tags(C->comp_arena()),
_verify_me(NULL),
_verify_only(true) {
build_and_optimize(false);
}
// build the loop tree and perform any requested optimizations
void build_and_optimize(bool do_split_if);
public: public:
// Dominators for the sea of nodes // Dominators for the sea of nodes
void Dominators(); void Dominators();
...@@ -671,7 +694,32 @@ public: ...@@ -671,7 +694,32 @@ public:
Node *dom_lca_internal( Node *n1, Node *n2 ) const; Node *dom_lca_internal( Node *n1, Node *n2 ) const;
// Compute the Ideal Node to Loop mapping // Compute the Ideal Node to Loop mapping
PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me, bool do_split_ifs ); PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs) :
PhaseTransform(Ideal_Loop),
_igvn(igvn),
_dom_lca_tags(C->comp_arena()),
_verify_me(NULL),
_verify_only(false) {
build_and_optimize(do_split_ifs);
}
// Verify that verify_me made the same decisions as a fresh run.
PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) :
PhaseTransform(Ideal_Loop),
_igvn(igvn),
_dom_lca_tags(C->comp_arena()),
_verify_me(verify_me),
_verify_only(false) {
build_and_optimize(false);
}
// Build and verify the loop tree without modifying the graph. This
// is useful to verify that all inputs properly dominate their uses.
static void verify(PhaseIterGVN& igvn) {
#ifdef ASSERT
PhaseIdealLoop v(igvn);
#endif
}
// True if the method has at least 1 irreducible loop // True if the method has at least 1 irreducible loop
bool _has_irreducible_loops; bool _has_irreducible_loops;
......
/* /*
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -53,6 +53,7 @@ elapsedTimer Phase::_t_codeGeneration; ...@@ -53,6 +53,7 @@ elapsedTimer Phase::_t_codeGeneration;
elapsedTimer Phase::_t_registerMethod; elapsedTimer Phase::_t_registerMethod;
elapsedTimer Phase::_t_temporaryTimer1; elapsedTimer Phase::_t_temporaryTimer1;
elapsedTimer Phase::_t_temporaryTimer2; elapsedTimer Phase::_t_temporaryTimer2;
elapsedTimer Phase::_t_idealLoopVerify;
// Subtimers for _t_optimizer // Subtimers for _t_optimizer
elapsedTimer Phase::_t_iterGVN; elapsedTimer Phase::_t_iterGVN;
...@@ -101,6 +102,7 @@ void Phase::print_timers() { ...@@ -101,6 +102,7 @@ void Phase::print_timers() {
if( Verbose || WizardMode ) { if( Verbose || WizardMode ) {
tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds()); tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds());
tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds()); tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds());
tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds());
tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds()); tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds());
tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds()); tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds());
tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds()); tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds());
...@@ -117,7 +119,7 @@ void Phase::print_timers() { ...@@ -117,7 +119,7 @@ void Phase::print_timers() {
tty->print_cr (" ctorChaitin : %3.3f sec", Phase::_t_ctorChaitin.seconds()); tty->print_cr (" ctorChaitin : %3.3f sec", Phase::_t_ctorChaitin.seconds());
tty->print_cr (" buildIFG : %3.3f sec", Phase::_t_buildIFGphysical.seconds()); tty->print_cr (" buildIFG : %3.3f sec", Phase::_t_buildIFGphysical.seconds());
tty->print_cr (" computeLive : %3.3f sec", Phase::_t_computeLive.seconds()); tty->print_cr (" computeLive : %3.3f sec", Phase::_t_computeLive.seconds());
tty->print_cr (" regAllocSplit: %3.3f sec", Phase::_t_regAllocSplit.seconds()); tty->print_cr (" regAllocSplit : %3.3f sec", Phase::_t_regAllocSplit.seconds());
tty->print_cr (" postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds()); tty->print_cr (" postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds());
tty->print_cr (" fixupSpills : %3.3f sec", Phase::_t_fixupSpills.seconds()); tty->print_cr (" fixupSpills : %3.3f sec", Phase::_t_fixupSpills.seconds());
double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() + double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() +
...@@ -128,11 +130,11 @@ void Phase::print_timers() { ...@@ -128,11 +130,11 @@ void Phase::print_timers() {
tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc); tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
} }
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds()); tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" blockOrdering: %3.3f sec", Phase::_t_blockOrdering.seconds()); tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds());
tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds()); tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds()); tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
tty->print_cr (" ------------ : ----------"); tty->print_cr (" -------------- : ----------");
double phase_subtotal = Phase::_t_parser.seconds() + double phase_subtotal = Phase::_t_parser.seconds() +
(DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) + (DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() + Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
...@@ -159,6 +161,6 @@ void Phase::print_timers() { ...@@ -159,6 +161,6 @@ void Phase::print_timers() {
} }
tty->print_cr (" output : %3.3f sec", Phase::_t_output.seconds()); tty->print_cr (" output : %3.3f sec", Phase::_t_output.seconds());
tty->print_cr (" isched : %3.3f sec", Phase::_t_instrSched.seconds()); tty->print_cr (" isched : %3.3f sec", Phase::_t_instrSched.seconds());
tty->print_cr (" bldOopMaps: %3.3f sec", Phase::_t_buildOopMaps.seconds()); tty->print_cr (" bldOopMaps : %3.3f sec", Phase::_t_buildOopMaps.seconds());
} }
#endif #endif
/* /*
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -83,6 +83,7 @@ protected: ...@@ -83,6 +83,7 @@ protected:
static elapsedTimer _t_registerMethod; static elapsedTimer _t_registerMethod;
static elapsedTimer _t_temporaryTimer1; static elapsedTimer _t_temporaryTimer1;
static elapsedTimer _t_temporaryTimer2; static elapsedTimer _t_temporaryTimer2;
static elapsedTimer _t_idealLoopVerify;
// Subtimers for _t_optimizer // Subtimers for _t_optimizer
static elapsedTimer _t_iterGVN; static elapsedTimer _t_iterGVN;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册