Mon, 23 Feb 2009 16:03:19 -0800
6791572: assert("duplicating node that's already been matched")
Summary: Mark inputs for an address expression as shared if there are other uses besides address expressions.
Reviewed-by: never
src/share/vm/opto/matcher.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/opto/matcher.cpp Mon Feb 23 12:02:30 2009 -0800 1.2 +++ b/src/share/vm/opto/matcher.cpp Mon Feb 23 16:03:19 2009 -0800 1.3 @@ -1707,11 +1707,18 @@ 1.4 void Matcher::find_shared( Node *n ) { 1.5 // Allocate stack of size C->unique() * 2 to avoid frequent realloc 1.6 MStack mstack(C->unique() * 2); 1.7 + // Mark nodes as address_visited if they are inputs to an address expression 1.8 + VectorSet address_visited(Thread::current()->resource_area()); 1.9 mstack.push(n, Visit); // Don't need to pre-visit root node 1.10 while (mstack.is_nonempty()) { 1.11 n = mstack.node(); // Leave node on stack 1.12 Node_State nstate = mstack.state(); 1.13 + uint nop = n->Opcode(); 1.14 if (nstate == Pre_Visit) { 1.15 + if (address_visited.test(n->_idx)) { // Visited in address already? 1.16 + // Flag as visited and shared now. 1.17 + set_visited(n); 1.18 + } 1.19 if (is_visited(n)) { // Visited already? 1.20 // Node is shared and has no reason to clone. Flag it as shared. 1.21 // This causes it to match into a register for the sharing. 1.22 @@ -1726,7 +1733,7 @@ 1.23 set_visited(n); // Flag as visited now 1.24 bool mem_op = false; 1.25 1.26 - switch( n->Opcode() ) { // Handle some opcodes special 1.27 + switch( nop ) { // Handle some opcodes special 1.28 case Op_Phi: // Treat Phis as shared roots 1.29 case Op_Parm: 1.30 case Op_Proj: // All handled specially during matching 1.31 @@ -1887,34 +1894,51 @@ 1.32 // to have a single use so force sharing here. 1.33 set_shared(m->in(AddPNode::Base)->in(1)); 1.34 } 1.35 + 1.36 + // Some inputs for address expression are not put on stack 1.37 + // to avoid marking them as shared and forcing them into register 1.38 + // if they are used only in address expressions. 1.39 + // But they should be marked as shared if there are other uses 1.40 + // besides address expressions. 1.41 + 1.42 Node *off = m->in(AddPNode::Offset); 1.43 - if( off->is_Con() ) { 1.44 - set_visited(m); // Flag as visited now 1.45 + if( off->is_Con() && 1.46 + // When there are other uses besides address expressions 1.47 + // put it on stack and mark as shared. 1.48 + !is_visited(m) ) { 1.49 + address_visited.test_set(m->_idx); // Flag as address_visited 1.50 Node *adr = m->in(AddPNode::Address); 1.51 1.52 // Intel, ARM and friends can handle 2 adds in addressing mode 1.53 if( clone_shift_expressions && adr->is_AddP() && 1.54 // AtomicAdd is not an addressing expression. 1.55 // Cheap to find it by looking for screwy base. 1.56 - !adr->in(AddPNode::Base)->is_top() ) { 1.57 - set_visited(adr); // Flag as visited now 1.58 + !adr->in(AddPNode::Base)->is_top() && 1.59 + // Are there other uses besides address expressions? 1.60 + !is_visited(adr) ) { 1.61 + address_visited.set(adr->_idx); // Flag as address_visited 1.62 Node *shift = adr->in(AddPNode::Offset); 1.63 // Check for shift by small constant as well 1.64 if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() && 1.65 - shift->in(2)->get_int() <= 3 ) { 1.66 - set_visited(shift); // Flag as visited now 1.67 + shift->in(2)->get_int() <= 3 && 1.68 + // Are there other uses besides address expressions? 1.69 + !is_visited(shift) ) { 1.70 + address_visited.set(shift->_idx); // Flag as address_visited 1.71 mstack.push(shift->in(2), Visit); 1.72 + Node *conv = shift->in(1); 1.73 #ifdef _LP64 1.74 // Allow Matcher to match the rule which bypass 1.75 // ConvI2L operation for an array index on LP64 1.76 // if the index value is positive. 1.77 - if( shift->in(1)->Opcode() == Op_ConvI2L && 1.78 - shift->in(1)->as_Type()->type()->is_long()->_lo >= 0 ) { 1.79 - set_visited(shift->in(1)); // Flag as visited now 1.80 - mstack.push(shift->in(1)->in(1), Pre_Visit); 1.81 + if( conv->Opcode() == Op_ConvI2L && 1.82 + conv->as_Type()->type()->is_long()->_lo >= 0 && 1.83 + // Are there other uses besides address expressions? 1.84 + !is_visited(conv) ) { 1.85 + address_visited.set(conv->_idx); // Flag as address_visited 1.86 + mstack.push(conv->in(1), Pre_Visit); 1.87 } else 1.88 #endif 1.89 - mstack.push(shift->in(1), Pre_Visit); 1.90 + mstack.push(conv, Pre_Visit); 1.91 } else { 1.92 mstack.push(shift, Pre_Visit); 1.93 }