From fecf008e6754053a30ed037d8e47999577722bcd Mon Sep 17 00:00:00 2001 From: kvn Date: Mon, 23 Feb 2009 16:03:19 -0800 Subject: [PATCH] 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 | 48 ++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp index e911c065c..9f424c0e4 100644 --- a/src/share/vm/opto/matcher.cpp +++ b/src/share/vm/opto/matcher.cpp @@ -1707,11 +1707,18 @@ OptoReg::Name Matcher::find_receiver( bool is_outgoing ) { void Matcher::find_shared( Node *n ) { // Allocate stack of size C->unique() * 2 to avoid frequent realloc MStack mstack(C->unique() * 2); + // Mark nodes as address_visited if they are inputs to an address expression + VectorSet address_visited(Thread::current()->resource_area()); mstack.push(n, Visit); // Don't need to pre-visit root node while (mstack.is_nonempty()) { n = mstack.node(); // Leave node on stack Node_State nstate = mstack.state(); + uint nop = n->Opcode(); if (nstate == Pre_Visit) { + if (address_visited.test(n->_idx)) { // Visited in address already? + // Flag as visited and shared now. + set_visited(n); + } if (is_visited(n)) { // Visited already? // Node is shared and has no reason to clone. Flag it as shared. // This causes it to match into a register for the sharing. @@ -1726,7 +1733,7 @@ void Matcher::find_shared( Node *n ) { set_visited(n); // Flag as visited now bool mem_op = false; - switch( n->Opcode() ) { // Handle some opcodes special + switch( nop ) { // Handle some opcodes special case Op_Phi: // Treat Phis as shared roots case Op_Parm: case Op_Proj: // All handled specially during matching @@ -1887,34 +1894,51 @@ void Matcher::find_shared( Node *n ) { // to have a single use so force sharing here. set_shared(m->in(AddPNode::Base)->in(1)); } + + // Some inputs for address expression are not put on stack + // to avoid marking them as shared and forcing them into register + // if they are used only in address expressions. + // But they should be marked as shared if there are other uses + // besides address expressions. + Node *off = m->in(AddPNode::Offset); - if( off->is_Con() ) { - set_visited(m); // Flag as visited now + if( off->is_Con() && + // When there are other uses besides address expressions + // put it on stack and mark as shared. + !is_visited(m) ) { + address_visited.test_set(m->_idx); // Flag as address_visited Node *adr = m->in(AddPNode::Address); // Intel, ARM and friends can handle 2 adds in addressing mode if( clone_shift_expressions && adr->is_AddP() && // AtomicAdd is not an addressing expression. // Cheap to find it by looking for screwy base. - !adr->in(AddPNode::Base)->is_top() ) { - set_visited(adr); // Flag as visited now + !adr->in(AddPNode::Base)->is_top() && + // Are there other uses besides address expressions? + !is_visited(adr) ) { + address_visited.set(adr->_idx); // Flag as address_visited Node *shift = adr->in(AddPNode::Offset); // Check for shift by small constant as well if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() && - shift->in(2)->get_int() <= 3 ) { - set_visited(shift); // Flag as visited now + shift->in(2)->get_int() <= 3 && + // Are there other uses besides address expressions? + !is_visited(shift) ) { + address_visited.set(shift->_idx); // Flag as address_visited mstack.push(shift->in(2), Visit); + Node *conv = shift->in(1); #ifdef _LP64 // Allow Matcher to match the rule which bypass // ConvI2L operation for an array index on LP64 // if the index value is positive. - if( shift->in(1)->Opcode() == Op_ConvI2L && - shift->in(1)->as_Type()->type()->is_long()->_lo >= 0 ) { - set_visited(shift->in(1)); // Flag as visited now - mstack.push(shift->in(1)->in(1), Pre_Visit); + if( conv->Opcode() == Op_ConvI2L && + conv->as_Type()->type()->is_long()->_lo >= 0 && + // Are there other uses besides address expressions? + !is_visited(conv) ) { + address_visited.set(conv->_idx); // Flag as address_visited + mstack.push(conv->in(1), Pre_Visit); } else #endif - mstack.push(shift->in(1), Pre_Visit); + mstack.push(conv, Pre_Visit); } else { mstack.push(shift, Pre_Visit); } -- GitLab