--- a/hotspot/src/share/vm/opto/chaitin.hpp Fri Aug 14 00:02:12 2009 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.hpp Fri Aug 14 15:55:26 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 );
--- a/hotspot/src/share/vm/opto/postaloc.cpp Fri Aug 14 00:02:12 2009 -0700
+++ b/hotspot/src/share/vm/opto/postaloc.cpp Fri Aug 14 15:55:26 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);
}
}