Fri, 02 May 2014 16:44:54 -0700
8039298: assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)->higher_equal(TypePtr::NULL_PTR))
Summary: Convert the assert into the runtime check to skip IGVN optimizations for problematic memory nodes. Eliminate dead nodes more aggressively.
Reviewed-by: twisti, iveresov
1.1 --- a/src/share/vm/opto/compile.cpp Tue Apr 29 12:20:53 2014 -0700 1.2 +++ b/src/share/vm/opto/compile.cpp Fri May 02 16:44:54 2014 -0700 1.3 @@ -693,6 +693,7 @@ 1.4 #endif 1.5 set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining)); 1.6 set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics")); 1.7 + set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it 1.8 1.9 if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) { 1.10 // Make sure the method being compiled gets its own MDO, 1.11 @@ -977,6 +978,8 @@ 1.12 set_print_assembly(PrintFrameConverterAssembly); 1.13 set_parsed_irreducible_loop(false); 1.14 #endif 1.15 + set_has_irreducible_loop(false); // no loops 1.16 + 1.17 CompileWrapper cw(this); 1.18 Init(/*AliasLevel=*/ 0); 1.19 init_tf((*generator)()); 1.20 @@ -1147,7 +1150,7 @@ 1.21 if( start->is_Start() ) 1.22 return start->as_Start(); 1.23 } 1.24 - ShouldNotReachHere(); 1.25 + fatal("Did not find Start node!"); 1.26 return NULL; 1.27 } 1.28
2.1 --- a/src/share/vm/opto/compile.hpp Tue Apr 29 12:20:53 2014 -0700 2.2 +++ b/src/share/vm/opto/compile.hpp Fri May 02 16:44:54 2014 -0700 2.3 @@ -319,6 +319,7 @@ 2.4 bool _trace_opto_output; 2.5 bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing 2.6 #endif 2.7 + bool _has_irreducible_loop; // Found irreducible loops 2.8 // JSR 292 2.9 bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. 2.10 RTMState _rtm_state; // State of Restricted Transactional Memory usage 2.11 @@ -605,6 +606,8 @@ 2.12 void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; } 2.13 int _in_dump_cnt; // Required for dumping ir nodes. 2.14 #endif 2.15 + bool has_irreducible_loop() const { return _has_irreducible_loop; } 2.16 + void set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; } 2.17 2.18 // JSR 292 2.19 bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
3.1 --- a/src/share/vm/opto/loopnode.cpp Tue Apr 29 12:20:53 2014 -0700 3.2 +++ b/src/share/vm/opto/loopnode.cpp Fri May 02 16:44:54 2014 -0700 3.3 @@ -266,9 +266,9 @@ 3.4 3.5 // Counted loop head must be a good RegionNode with only 3 not NULL 3.6 // control input edges: Self, Entry, LoopBack. 3.7 - if (x->in(LoopNode::Self) == NULL || x->req() != 3) 3.8 + if (x->in(LoopNode::Self) == NULL || x->req() != 3 || loop->_irreducible) { 3.9 return false; 3.10 - 3.11 + } 3.12 Node *init_control = x->in(LoopNode::EntryControl); 3.13 Node *back_control = x->in(LoopNode::LoopBackControl); 3.14 if (init_control == NULL || back_control == NULL) // Partially dead 3.15 @@ -1522,11 +1522,11 @@ 3.16 3.17 // If I have one hot backedge, peel off myself loop. 3.18 // I better be the outermost loop. 3.19 - if( _head->req() > 3 ) { 3.20 + if (_head->req() > 3 && !_irreducible) { 3.21 split_outer_loop( phase ); 3.22 result = true; 3.23 3.24 - } else if( !_head->is_Loop() && !_irreducible ) { 3.25 + } else if (!_head->is_Loop() && !_irreducible) { 3.26 // Make a new LoopNode to replace the old loop head 3.27 Node *l = new (phase->C) LoopNode( _head->in(1), _head->in(2) ); 3.28 l = igvn.register_new_node_with_optimizer(l, _head); 3.29 @@ -2938,6 +2938,7 @@ 3.30 return pre_order; 3.31 } 3.32 } 3.33 + C->set_has_irreducible_loop(_has_irreducible_loops); 3.34 } 3.35 3.36 // This Node might be a decision point for loops. It is only if
4.1 --- a/src/share/vm/opto/memnode.cpp Tue Apr 29 12:20:53 2014 -0700 4.2 +++ b/src/share/vm/opto/memnode.cpp Fri May 02 16:44:54 2014 -0700 4.3 @@ -306,33 +306,16 @@ 4.4 int alias_idx = phase->C->get_alias_index(t_adr->is_ptr()); 4.5 } 4.6 4.7 -#ifdef ASSERT 4.8 Node* base = NULL; 4.9 - if (address->is_AddP()) 4.10 + if (address->is_AddP()) { 4.11 base = address->in(AddPNode::Base); 4.12 + } 4.13 if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) && 4.14 !t_adr->isa_rawptr()) { 4.15 // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true. 4.16 - Compile* C = phase->C; 4.17 - tty->cr(); 4.18 - tty->print_cr("===== NULL+offs not RAW address ====="); 4.19 - if (C->is_dead_node(this->_idx)) tty->print_cr("'this' is dead"); 4.20 - if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead"); 4.21 - if (C->is_dead_node(mem->_idx)) tty->print_cr("'mem' is dead"); 4.22 - if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead"); 4.23 - if (C->is_dead_node(base->_idx)) tty->print_cr("'base' is dead"); 4.24 - tty->cr(); 4.25 - base->dump(1); 4.26 - tty->cr(); 4.27 - this->dump(2); 4.28 - tty->print("this->adr_type(): "); adr_type()->dump(); tty->cr(); 4.29 - tty->print("phase->type(address): "); t_adr->dump(); tty->cr(); 4.30 - tty->print("phase->type(base): "); phase->type(address)->dump(); tty->cr(); 4.31 - tty->cr(); 4.32 + // Skip this node optimization if its address has TOP base. 4.33 + return NodeSentinel; // caller will return NULL 4.34 } 4.35 - assert(base == NULL || t_adr->isa_rawptr() || 4.36 - !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?"); 4.37 -#endif 4.38 4.39 // Avoid independent memory operations 4.40 Node* old_mem = mem;
5.1 --- a/src/share/vm/opto/node.cpp Tue Apr 29 12:20:53 2014 -0700 5.2 +++ b/src/share/vm/opto/node.cpp Fri May 02 16:44:54 2014 -0700 5.3 @@ -27,6 +27,7 @@ 5.4 #include "memory/allocation.inline.hpp" 5.5 #include "opto/cfgnode.hpp" 5.6 #include "opto/connode.hpp" 5.7 +#include "opto/loopnode.hpp" 5.8 #include "opto/machnode.hpp" 5.9 #include "opto/matcher.hpp" 5.10 #include "opto/node.hpp" 5.11 @@ -1255,6 +1256,7 @@ 5.12 5.13 Node *top = igvn->C->top(); 5.14 nstack.push(dead); 5.15 + bool has_irreducible_loop = igvn->C->has_irreducible_loop(); 5.16 5.17 while (nstack.size() > 0) { 5.18 dead = nstack.pop(); 5.19 @@ -1269,13 +1271,31 @@ 5.20 assert (!use->is_Con(), "Control for Con node should be Root node."); 5.21 use->set_req(0, top); // Cut dead edge to prevent processing 5.22 nstack.push(use); // the dead node again. 5.23 + } else if (!has_irreducible_loop && // Backedge could be alive in irreducible loop 5.24 + use->is_Loop() && !use->is_Root() && // Don't kill Root (RootNode extends LoopNode) 5.25 + use->in(LoopNode::EntryControl) == dead) { // Dead loop if its entry is dead 5.26 + use->set_req(LoopNode::EntryControl, top); // Cut dead edge to prevent processing 5.27 + use->set_req(0, top); // Cut self edge 5.28 + nstack.push(use); 5.29 } else { // Else found a not-dead user 5.30 + // Dead if all inputs are top or null 5.31 + bool dead_use = !use->is_Root(); // Keep empty graph alive 5.32 for (uint j = 1; j < use->req(); j++) { 5.33 - if (use->in(j) == dead) { // Turn all dead inputs into TOP 5.34 + Node* in = use->in(j); 5.35 + if (in == dead) { // Turn all dead inputs into TOP 5.36 use->set_req(j, top); 5.37 + } else if (in != NULL && !in->is_top()) { 5.38 + dead_use = false; 5.39 } 5.40 } 5.41 - igvn->_worklist.push(use); 5.42 + if (dead_use) { 5.43 + if (use->is_Region()) { 5.44 + use->set_req(0, top); // Cut self edge 5.45 + } 5.46 + nstack.push(use); 5.47 + } else { 5.48 + igvn->_worklist.push(use); 5.49 + } 5.50 } 5.51 // Refresh the iterator, since any number of kills might have happened. 5.52 k = dead->last_outs(kmin);