提交 08398f56 编写于 作者: K kvn

7107042: assert(no_dead_loop) failed: dead loop detected

Summary: Use dead nodes elimination code in PhaseIdealLoop before executing EA.
Reviewed-by: never, twisti
上级 f2a17338
...@@ -1743,11 +1743,12 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { ...@@ -1743,11 +1743,12 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
collect_statistics(thread, time, task); collect_statistics(thread, time, task);
if (PrintCompilation && PrintInlining) { if (PrintCompilation && PrintCompilation2) {
tty->print("%7d ", (int) tty->time_stamp().milliseconds()); // print timestamp tty->print("%7d ", (int) tty->time_stamp().milliseconds()); // print timestamp
tty->print("%4d ", compile_id); // print compilation number tty->print("%4d ", compile_id); // print compilation number
tty->print("%s ", (is_osr ? "%" : " ")); tty->print("%s ", (is_osr ? "%" : " "));
tty->print_cr("size: %d time: %d inlined: %d bytes", task->code()->total_size(), time.milliseconds(), task->num_inlined_bytecodes()); int code_size = (task->code() == NULL) ? 0 : task->code()->total_size();
tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, time.milliseconds(), task->num_inlined_bytecodes());
} }
if (compilable == ciEnv::MethodCompilable_never) { if (compilable == ciEnv::MethodCompilable_never) {
......
...@@ -346,15 +346,15 @@ void Compile::identify_useful_nodes(Unique_Node_List &useful) { ...@@ -346,15 +346,15 @@ void Compile::identify_useful_nodes(Unique_Node_List &useful) {
// Disconnect all useless nodes by disconnecting those at the boundary. // Disconnect all useless nodes by disconnecting those at the boundary.
void Compile::remove_useless_nodes(Unique_Node_List &useful) { void Compile::remove_useless_nodes(Unique_Node_List &useful) {
uint next = 0; uint next = 0;
while( next < useful.size() ) { while (next < useful.size()) {
Node *n = useful.at(next++); Node *n = useful.at(next++);
// Use raw traversal of out edges since this code removes out edges // Use raw traversal of out edges since this code removes out edges
int max = n->outcnt(); int max = n->outcnt();
for (int j = 0; j < max; ++j ) { for (int j = 0; j < max; ++j) {
Node* child = n->raw_out(j); Node* child = n->raw_out(j);
if( ! useful.member(child) ) { if (! useful.member(child)) {
assert( !child->is_top() || child != top(), assert(!child->is_top() || child != top(),
"If top is cached in Compile object it is in useful list"); "If top is cached in Compile object it is in useful list");
// Only need to remove this out-edge to the useless node // Only need to remove this out-edge to the useless node
n->raw_del_out(j); n->raw_del_out(j);
--j; --j;
...@@ -362,7 +362,14 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) { ...@@ -362,7 +362,14 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
} }
} }
if (n->outcnt() == 1 && n->has_special_unique_user()) { if (n->outcnt() == 1 && n->has_special_unique_user()) {
record_for_igvn( n->unique_out() ); record_for_igvn(n->unique_out());
}
}
// Remove useless macro and predicate opaq nodes
for (int i = C->macro_count()-1; i >= 0; i--) {
Node* n = C->macro_node(i);
if (!useful.member(n)) {
remove_macro_node(n);
} }
} }
debug_only(verify_graph_edges(true/*check for no_dead_code*/);) debug_only(verify_graph_edges(true/*check for no_dead_code*/);)
...@@ -719,6 +726,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -719,6 +726,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
while (_late_inlines.length() > 0) { while (_late_inlines.length() > 0) {
CallGenerator* cg = _late_inlines.pop(); CallGenerator* cg = _late_inlines.pop();
cg->do_late_inline(); cg->do_late_inline();
if (failing()) return;
} }
} }
assert(_late_inlines.length() == 0, "should have been processed"); assert(_late_inlines.length() == 0, "should have been processed");
...@@ -1691,13 +1699,20 @@ void Compile::Optimize() { ...@@ -1691,13 +1699,20 @@ void Compile::Optimize() {
// Perform escape analysis // Perform escape analysis
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
if (has_loops()) {
// Cleanup graph (remove dead nodes).
TracePhase t2("idealLoop", &_t_idealLoop, true);
PhaseIdealLoop ideal_loop( igvn, false, true );
if (major_progress()) print_method("PhaseIdealLoop before EA", 2);
if (failing()) return;
}
TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true); TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
ConnectionGraph::do_analysis(this, &igvn); ConnectionGraph::do_analysis(this, &igvn);
if (failing()) return; if (failing()) return;
igvn.optimize(); igvn.optimize();
print_method("Iter GVN 3", 2); print_method("Iter GVN after EA", 2);
if (failing()) return; if (failing()) return;
......
...@@ -1883,7 +1883,7 @@ void PhaseIdealLoop::eliminate_useless_predicates() { ...@@ -1883,7 +1883,7 @@ void PhaseIdealLoop::eliminate_useless_predicates() {
//----------------------------build_and_optimize------------------------------- //----------------------------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.
void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) {
ResourceMark rm; ResourceMark rm;
int old_progress = C->major_progress(); int old_progress = C->major_progress();
...@@ -2072,6 +2072,16 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { ...@@ -2072,6 +2072,16 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) {
} }
#endif #endif
if (skip_loop_opts) {
// Cleanup any modified bits
_igvn.optimize();
if (C->log() != NULL) {
log_loop_tree(_ltree_root, _ltree_root, C->log());
}
return;
}
if (ReassociateInvariants) { if (ReassociateInvariants) {
// Reassociate invariants and prep for split_thru_phi // Reassociate invariants and prep for split_thru_phi
for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
......
...@@ -747,11 +747,11 @@ private: ...@@ -747,11 +747,11 @@ private:
_dom_lca_tags(arena()), // Thread::resource_area _dom_lca_tags(arena()), // Thread::resource_area
_verify_me(NULL), _verify_me(NULL),
_verify_only(true) { _verify_only(true) {
build_and_optimize(false); build_and_optimize(false, false);
} }
// build the loop tree and perform any requested optimizations // build the loop tree and perform any requested optimizations
void build_and_optimize(bool do_split_if); void build_and_optimize(bool do_split_if, bool skip_loop_opts);
public: public:
// Dominators for the sea of nodes // Dominators for the sea of nodes
...@@ -762,13 +762,13 @@ public: ...@@ -762,13 +762,13 @@ 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, bool do_split_ifs) : PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool skip_loop_opts = false) :
PhaseTransform(Ideal_Loop), PhaseTransform(Ideal_Loop),
_igvn(igvn), _igvn(igvn),
_dom_lca_tags(arena()), // Thread::resource_area _dom_lca_tags(arena()), // Thread::resource_area
_verify_me(NULL), _verify_me(NULL),
_verify_only(false) { _verify_only(false) {
build_and_optimize(do_split_ifs); build_and_optimize(do_split_ifs, skip_loop_opts);
} }
// Verify that verify_me made the same decisions as a fresh run. // Verify that verify_me made the same decisions as a fresh run.
...@@ -778,7 +778,7 @@ public: ...@@ -778,7 +778,7 @@ public:
_dom_lca_tags(arena()), // Thread::resource_area _dom_lca_tags(arena()), // Thread::resource_area
_verify_me(verify_me), _verify_me(verify_me),
_verify_only(false) { _verify_only(false) {
build_and_optimize(false); build_and_optimize(false, false);
} }
// Build and verify the loop tree without modifying the graph. This // Build and verify the loop tree without modifying the graph. This
......
...@@ -629,9 +629,10 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) { ...@@ -629,9 +629,10 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
if (TraceLoopOpts) { if (TraceLoopOpts) {
tty->print("CMOV "); tty->print("CMOV ");
r_loop->dump_head(); r_loop->dump_head();
if (Verbose) if (Verbose) {
bol->in(1)->dump(1); bol->in(1)->dump(1);
cmov->dump(1); cmov->dump(1);
}
} }
if (VerifyLoopOptimizations) verify(); if (VerifyLoopOptimizations) verify();
#endif #endif
......
...@@ -1915,7 +1915,7 @@ void Matcher::find_shared( Node *n ) { ...@@ -1915,7 +1915,7 @@ void Matcher::find_shared( Node *n ) {
set_dontcare(n); set_dontcare(n);
break; break;
case Op_Jump: case Op_Jump:
mstack.push(n->in(1), Visit); // Switch Value mstack.push(n->in(1), Pre_Visit); // Switch Value (could be shared)
mstack.push(n->in(0), Pre_Visit); // Visit Control input mstack.push(n->in(0), Pre_Visit); // Visit Control input
continue; // while (mstack.is_nonempty()) continue; // while (mstack.is_nonempty())
case Op_StrComp: case Op_StrComp:
......
...@@ -1421,6 +1421,12 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1421,6 +1421,12 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
const TypeOopPtr *t_oop = addr_t->isa_oopptr(); const TypeOopPtr *t_oop = addr_t->isa_oopptr();
if (can_reshape && opt_mem->is_Phi() && if (can_reshape && opt_mem->is_Phi() &&
(t_oop != NULL) && t_oop->is_known_instance_field()) { (t_oop != NULL) && t_oop->is_known_instance_field()) {
PhaseIterGVN *igvn = phase->is_IterGVN();
if (igvn != NULL && igvn->_worklist.member(opt_mem)) {
// Delay this transformation until memory Phi is processed.
phase->is_IterGVN()->_worklist.push(this);
return NULL;
}
// Split instance field load through Phi. // Split instance field load through Phi.
Node* result = split_through_phi(phase); Node* result = split_through_phi(phase);
if (result != NULL) return result; if (result != NULL) return result;
......
...@@ -322,11 +322,12 @@ void NodeHash::remove_useless_nodes(VectorSet &useful) { ...@@ -322,11 +322,12 @@ void NodeHash::remove_useless_nodes(VectorSet &useful) {
void NodeHash::dump() { void NodeHash::dump() {
_total_inserts += _inserts; _total_inserts += _inserts;
_total_insert_probes += _insert_probes; _total_insert_probes += _insert_probes;
if( PrintCompilation && PrintOptoStatistics && Verbose && (_inserts > 0) ) { // PrintOptoGVN if (PrintCompilation && PrintOptoStatistics && Verbose && (_inserts > 0)) {
if( PrintCompilation2 ) { if (WizardMode) {
for( uint i=0; i<_max; i++ ) for (uint i=0; i<_max; i++) {
if( _table[i] ) if (_table[i])
tty->print("%d/%d/%d ",i,_table[i]->hash()&(_max-1),_table[i]->_idx); tty->print("%d/%d/%d ",i,_table[i]->hash()&(_max-1),_table[i]->_idx);
}
} }
tty->print("\nGVN Hash stats: %d grows to %d max_size\n", _grows, _max); tty->print("\nGVN Hash stats: %d grows to %d max_size\n", _grows, _max);
tty->print(" %d/%d (%8.1f%% full)\n", _inserts, _max, (double)_inserts/_max*100.0); tty->print(" %d/%d (%8.1f%% full)\n", _inserts, _max, (double)_inserts/_max*100.0);
......
...@@ -904,7 +904,7 @@ class CommandLineFlags { ...@@ -904,7 +904,7 @@ class CommandLineFlags {
product(bool, AlwaysRestoreFPU, false, \ product(bool, AlwaysRestoreFPU, false, \
"Restore the FPU control word after every JNI call (expensive)") \ "Restore the FPU control word after every JNI call (expensive)") \
\ \
notproduct(bool, PrintCompilation2, false, \ diagnostic(bool, PrintCompilation2, false, \
"Print additional statistics per compilation") \ "Print additional statistics per compilation") \
\ \
diagnostic(bool, PrintAdapterHandlers, false, \ diagnostic(bool, PrintAdapterHandlers, false, \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册