# HG changeset patch # User never # Date 1250290426 25200 # Node ID a70508bb21c394b3cca77a6c960e6cb0b17282da # Parent ef671fb22f73f2a93a0b8fe879856dee106a2495 6862863: C2 compiler fails in elide_copy() Reviewed-by: kvn diff -r ef671fb22f73 -r a70508bb21c3 src/share/vm/opto/chaitin.hpp --- a/src/share/vm/opto/chaitin.hpp Thu Aug 06 12:24:41 2009 -0700 +++ b/src/share/vm/opto/chaitin.hpp Fri Aug 14 15:53:46 2009 -0700 @@ -458,6 +458,16 @@ // Post-Allocation peephole copy removal void post_allocate_copy_removal(); Node *skip_copies( Node *c ); + // Replace the old node with the current live version of that value + // and yank the old value if it's dead. + int replace_and_yank_if_dead( Node *old, OptoReg::Name nreg, + Block *current_block, Node_List& value, Node_List& regnd ) { + Node* v = regnd[nreg]; + assert(v->outcnt() != 0, "no dead values"); + old->replace_by(v); + return yank_if_dead(old, current_block, &value, ®nd); + } + int yank_if_dead( Node *old, Block *current_block, Node_List *value, Node_List *regnd ); int elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs ); int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd ); diff -r ef671fb22f73 -r a70508bb21c3 src/share/vm/opto/postaloc.cpp --- a/src/share/vm/opto/postaloc.cpp Thu Aug 06 12:24:41 2009 -0700 +++ b/src/share/vm/opto/postaloc.cpp Fri Aug 14 15:53:46 2009 -0700 @@ -88,6 +88,7 @@ value->map(old_reg,NULL); // Yank from value/regnd maps regnd->map(old_reg,NULL); // This register's value is now unknown } + assert(old->req() <= 2, "can't handle more inputs"); Node *tmp = old->req() > 1 ? old->in(1) : NULL; old->disconnect_inputs(NULL); if( !tmp ) break; @@ -530,6 +531,16 @@ // Do not change from int to pointer Node *val = skip_copies(n); + // Clear out a dead definition before starting so that the + // elimination code doesn't have to guard against it. The + // definition could in fact be a kill projection with a count of + // 0 which is safe but since those are uninteresting for copy + // elimination just delete them as well. + if (regnd[nreg] != NULL && regnd[nreg]->outcnt() == 0) { + regnd.map(nreg, NULL); + value.map(nreg, NULL); + } + uint n_ideal_reg = n->ideal_reg(); if( is_single_register(n_ideal_reg) ) { // If Node 'n' does not change the value mapped by the register, @@ -537,8 +548,7 @@ // mapping so 'n' will go dead. if( value[nreg] != val ) { if (eliminate_copy_of_constant(val, n, b, value, regnd, nreg, OptoReg::Bad)) { - n->replace_by(regnd[nreg]); - j -= yank_if_dead(n,b,&value,®nd); + j -= replace_and_yank_if_dead(n, nreg, b, value, regnd); } else { // Update the mapping: record new Node defined by the register regnd.map(nreg,n); @@ -546,10 +556,9 @@ // Node after skipping all copies. value.map(nreg,val); } - } else if( !may_be_copy_of_callee(n) && regnd[nreg]->outcnt() != 0 ) { + } else if( !may_be_copy_of_callee(n) ) { assert( n->is_Copy(), "" ); - n->replace_by(regnd[nreg]); - j -= yank_if_dead(n,b,&value,®nd); + j -= replace_and_yank_if_dead(n, nreg, b, value, regnd); } } else { // If the value occupies a register pair, record same info @@ -565,18 +574,16 @@ } if( value[nreg] != val || value[nreg_lo] != val ) { if (eliminate_copy_of_constant(val, n, b, value, regnd, nreg, nreg_lo)) { - n->replace_by(regnd[nreg]); - j -= yank_if_dead(n,b,&value,®nd); + j -= replace_and_yank_if_dead(n, nreg, b, value, regnd); } else { regnd.map(nreg , n ); regnd.map(nreg_lo, n ); value.map(nreg ,val); value.map(nreg_lo,val); } - } else if( !may_be_copy_of_callee(n) && regnd[nreg]->outcnt() != 0 ) { + } else if( !may_be_copy_of_callee(n) ) { assert( n->is_Copy(), "" ); - n->replace_by(regnd[nreg]); - j -= yank_if_dead(n,b,&value,®nd); + j -= replace_and_yank_if_dead(n, nreg, b, value, regnd); } }