< prev index next >
src/share/vm/opto/output.cpp
Print this page
*** 103,114 ****
// Insert epilogs before every return
for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
Block* block = _cfg->get_block(i);
if (!block->is_connector() && block->non_connector_successor(0) == _cfg->get_root_block()) { // Found a program exit point?
Node* m = block->end();
! if (m->is_Mach() && m->as_Mach()->ideal_Opcode() != Op_Halt) {
! MachEpilogNode* epilog = new MachEpilogNode(m->as_Mach()->ideal_Opcode() == Op_Return);
block->add_inst(epilog);
_cfg->map_node_to_block(epilog, block);
}
}
}
--- 103,114 ----
// Insert epilogs before every return
for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
Block* block = _cfg->get_block(i);
if (!block->is_connector() && block->non_connector_successor(0) == _cfg->get_root_block()) { // Found a program exit point?
Node* m = block->end();
! if (m->is_Mach() && m->as_Mach()->ideal_Opcode() != Opcodes::Op_Halt) {
! MachEpilogNode* epilog = new MachEpilogNode(m->as_Mach()->ideal_Opcode() == Opcodes::Op_Return);
block->add_inst(epilog);
_cfg->map_node_to_block(epilog, block);
}
}
}
*** 379,389 ****
assert(jmp_size[i] > 0 && mach->is_MachBranch(), "sanity");
int j;
// Find the branch; ignore trailing NOPs.
for (j = block->number_of_nodes()-1; j>=0; j--) {
Node* n = block->get_node(j);
! if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Op_Con)
break;
}
assert(j >= 0 && j == idx && block->get_node(j) == (Node*)mach, "sanity");
#endif
int br_size = jmp_size[i];
--- 379,389 ----
assert(jmp_size[i] > 0 && mach->is_MachBranch(), "sanity");
int j;
// Find the branch; ignore trailing NOPs.
for (j = block->number_of_nodes()-1; j>=0; j--) {
Node* n = block->get_node(j);
! if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Opcodes::Op_Con)
break;
}
assert(j >= 0 && j == idx && block->get_node(j) == (Node*)mach, "sanity");
#endif
int br_size = jmp_size[i];
*** 1311,1321 ****
n = replacement;
mach = replacement;
}
}
mach->as_MachBranch()->label_set( &blk_labels[block_num], block_num );
! } else if (mach->ideal_Opcode() == Op_Jump) {
for (uint h = 0; h < block->_num_succs; h++) {
Block* succs_block = block->_succs[h];
for (uint j = 1; j < succs_block->num_preds(); j++) {
Node* jpn = succs_block->pred(j);
if (jpn->is_JumpProj() && jpn->in(0) == mach) {
--- 1311,1321 ----
n = replacement;
mach = replacement;
}
}
mach->as_MachBranch()->label_set( &blk_labels[block_num], block_num );
! } else if (mach->ideal_Opcode() == Opcodes::Op_Jump) {
for (uint h = 0; h < block->_num_succs; h++) {
Block* succs_block = block->_succs[h];
for (uint j = 1; j < succs_block->num_preds(); j++) {
Node* jpn = succs_block->pred(j);
if (jpn->is_JumpProj() && jpn->in(0) == mach) {
*** 1326,1336 ****
}
}
}
#ifdef ASSERT
// Check that oop-store precedes the card-mark
! else if (mach->ideal_Opcode() == Op_StoreCM) {
uint storeCM_idx = j;
int count = 0;
for (uint prec = mach->req(); prec < mach->len(); prec++) {
Node *oop_store = mach->in(prec); // Precedence edge
if (oop_store == NULL) continue;
--- 1326,1336 ----
}
}
}
#ifdef ASSERT
// Check that oop-store precedes the card-mark
! else if (mach->ideal_Opcode() == Opcodes::Op_StoreCM) {
uint storeCM_idx = j;
int count = 0;
for (uint prec = mach->req(); prec < mach->len(); prec++) {
Node *oop_store = mach->in(prec); // Precedence edge
if (oop_store == NULL) continue;
*** 1570,1580 ****
int j;
// Find the branch; ignore trailing NOPs.
for (j = block->number_of_nodes() - 1; j >= 0; j--) {
n = block->get_node(j);
! if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Op_Con) {
break;
}
}
// If we didn't find anything, continue
--- 1570,1580 ----
int j;
// Find the branch; ignore trailing NOPs.
for (j = block->number_of_nodes() - 1; j >= 0; j--) {
n = block->get_node(j);
! if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Opcodes::Op_Con) {
break;
}
}
// If we didn't find anything, continue
*** 1965,1983 ****
if (_current_latency[_available[i]->_idx] > latency)
break;
// Special Check for compares following branches
if( n->is_Mach() && _scheduled.size() > 0 ) {
! int op = n->as_Mach()->ideal_Opcode();
Node *last = _scheduled[0];
if( last->is_MachIf() && last->in(1) == n &&
! ( op == Op_CmpI ||
! op == Op_CmpU ||
! op == Op_CmpP ||
! op == Op_CmpF ||
! op == Op_CmpD ||
! op == Op_CmpL ) ) {
// Recalculate position, moving to front of same latency
for ( i=0 ; i < _available.size(); i++ )
if (_current_latency[_available[i]->_idx] >= latency)
break;
--- 1965,1983 ----
if (_current_latency[_available[i]->_idx] > latency)
break;
// Special Check for compares following branches
if( n->is_Mach() && _scheduled.size() > 0 ) {
! Opcodes op = n->as_Mach()->ideal_Opcode();
Node *last = _scheduled[0];
if( last->is_MachIf() && last->in(1) == n &&
! ( op == Opcodes::Op_CmpI ||
! op == Opcodes::Op_CmpU ||
! op == Opcodes::Op_CmpP ||
! op == Opcodes::Op_CmpF ||
! op == Opcodes::Op_CmpD ||
! op == Opcodes::Op_CmpL ) ) {
// Recalculate position, moving to front of same latency
for ( i=0 ; i < _available.size(); i++ )
if (_current_latency[_available[i]->_idx] >= latency)
break;
*** 2198,2212 ****
// It's possible to have a BoxLock in the graph and in the _bbs mapping but
// not in the bb->_nodes array. This happens for debug-info-only BoxLocks.
// 'Schedule' them (basically ignore in the schedule) but do not insert them
// into the block. All other scheduled nodes get put in the schedule here.
! int op = n->Opcode();
! if( (op == Op_Node && n->req() == 0) || // anti-dependence node OR
! (op != Op_Node && // Not an unused antidepedence node and
// not an unallocated boxlock
! (OptoReg::is_valid(_regalloc->get_reg_first(n)) || op != Op_BoxLock)) ) {
// Push any trailing projections
if( bb->get_node(bb->number_of_nodes()-1) != n ) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node *foi = n->fast_out(i);
--- 2198,2212 ----
// It's possible to have a BoxLock in the graph and in the _bbs mapping but
// not in the bb->_nodes array. This happens for debug-info-only BoxLocks.
// 'Schedule' them (basically ignore in the schedule) but do not insert them
// into the block. All other scheduled nodes get put in the schedule here.
! Opcodes op = n->Opcode();
! if( (op == Opcodes::Op_Node && n->req() == 0) || // anti-dependence node OR
! (op != Opcodes::Op_Node && // Not an unused antidepedence node and
// not an unallocated boxlock
! (OptoReg::is_valid(_regalloc->get_reg_first(n)) || op != Opcodes::Op_BoxLock)) ) {
// Push any trailing projections
if( bb->get_node(bb->number_of_nodes()-1) != n ) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node *foi = n->fast_out(i);
*** 2353,2366 ****
Node *n = bb->get_node(_bb_start);
// Things not matched, like Phinodes and ProjNodes don't get scheduled.
// Also, MachIdealNodes do not get scheduled
if( !n->is_Mach() ) continue; // Skip non-machine nodes
MachNode *mach = n->as_Mach();
! int iop = mach->ideal_Opcode();
! if( iop == Op_CreateEx ) continue; // CreateEx is pinned
! if( iop == Op_Con ) continue; // Do not schedule Top
! if( iop == Op_Node && // Do not schedule PhiNodes, ProjNodes
mach->pipeline() == MachNode::pipeline_class() &&
!n->is_SpillCopy() && !n->is_MachMerge() ) // Breakpoints, Prolog, etc
continue;
break; // Funny loop structure to be sure...
}
--- 2353,2366 ----
Node *n = bb->get_node(_bb_start);
// Things not matched, like Phinodes and ProjNodes don't get scheduled.
// Also, MachIdealNodes do not get scheduled
if( !n->is_Mach() ) continue; // Skip non-machine nodes
MachNode *mach = n->as_Mach();
! Opcodes iop = mach->ideal_Opcode();
! if( iop == Opcodes::Op_CreateEx ) continue; // CreateEx is pinned
! if( iop == Opcodes::Op_Con ) continue; // Do not schedule Top
! if( iop == Opcodes::Op_Node && // Do not schedule PhiNodes, ProjNodes
mach->pipeline() == MachNode::pipeline_class() &&
!n->is_SpillCopy() && !n->is_MachMerge() ) // Breakpoints, Prolog, etc
continue;
break; // Funny loop structure to be sure...
}
*** 2371,2387 ****
// have their delay slots filled in the template expansions, so we don't
// bother scheduling them.
Node *last = bb->get_node(_bb_end);
// Ignore trailing NOPs.
while (_bb_end > 0 && last->is_Mach() &&
! last->as_Mach()->ideal_Opcode() == Op_Con) {
last = bb->get_node(--_bb_end);
}
! assert(!last->is_Mach() || last->as_Mach()->ideal_Opcode() != Op_Con, "");
if( last->is_Catch() ||
// Exclude unreachable path case when Halt node is in a separate block.
! (_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
// There must be a prior call. Skip it.
while( !bb->get_node(--_bb_end)->is_MachCall() ) {
assert( bb->get_node(_bb_end)->is_MachProj(), "skipping projections after expected call" );
}
} else if( last->is_MachNullCheck() ) {
--- 2371,2387 ----
// have their delay slots filled in the template expansions, so we don't
// bother scheduling them.
Node *last = bb->get_node(_bb_end);
// Ignore trailing NOPs.
while (_bb_end > 0 && last->is_Mach() &&
! last->as_Mach()->ideal_Opcode() == Opcodes::Op_Con) {
last = bb->get_node(--_bb_end);
}
! assert(!last->is_Mach() || last->as_Mach()->ideal_Opcode() != Opcodes::Op_Con, "");
if( last->is_Catch() ||
// Exclude unreachable path case when Halt node is in a separate block.
! (_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Opcodes::Op_Halt) ) {
// There must be a prior call. Skip it.
while( !bb->get_node(--_bb_end)->is_MachCall() ) {
assert( bb->get_node(_bb_end)->is_MachProj(), "skipping projections after expected call" );
}
} else if( last->is_MachNullCheck() ) {
*** 2500,2519 ****
// Walk over the block backwards. Check to make sure each DEF doesn't
// kill a live value (other than the one it's supposed to). Add each
// USE to the live set.
for( uint i = b->number_of_nodes()-1; i >= _bb_start; i-- ) {
Node *n = b->get_node(i);
! int n_op = n->Opcode();
! if( n_op == Op_MachProj && n->ideal_reg() == MachProjNode::fat_proj ) {
// Fat-proj kills a slew of registers
RegMask rm = n->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
OptoReg::Name kill = rm.find_first_elem();
rm.Remove(kill);
verify_do_def( n, kill, msg );
}
! } else if( n_op != Op_Node ) { // Avoid brand new antidependence nodes
// Get DEF'd registers the normal way
verify_do_def( n, _regalloc->get_reg_first(n), msg );
verify_do_def( n, _regalloc->get_reg_second(n), msg );
}
--- 2500,2519 ----
// Walk over the block backwards. Check to make sure each DEF doesn't
// kill a live value (other than the one it's supposed to). Add each
// USE to the live set.
for( uint i = b->number_of_nodes()-1; i >= _bb_start; i-- ) {
Node *n = b->get_node(i);
! Opcodes n_op = n->Opcode();
! if( n_op == Opcodes::Op_MachProj && n->ideal_reg() == static_cast<Opcodes>(MachProjNode::projType::fat_proj) ) {
// Fat-proj kills a slew of registers
RegMask rm = n->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
OptoReg::Name kill = rm.find_first_elem();
rm.Remove(kill);
verify_do_def( n, kill, msg );
}
! } else if( n_op != Opcodes::Op_Node ) { // Avoid brand new antidependence nodes
// Get DEF'd registers the normal way
verify_do_def( n, _regalloc->get_reg_first(n), msg );
verify_do_def( n, _regalloc->get_reg_second(n), msg );
}
*** 2569,2579 ****
Node *later_def = NULL;
// Finding a kill requires a real pinch-point.
// Check for not already having a pinch-point.
// Pinch points are Op_Node's.
! if( pinch->Opcode() != Op_Node ) { // Or later-def/kill as pinch-point?
later_def = pinch; // Must be def/kill as optimistic pinch-point
if ( _pinch_free_list.size() > 0) {
pinch = _pinch_free_list.pop();
} else {
pinch = new Node(1); // Pinch point to-be
--- 2569,2579 ----
Node *later_def = NULL;
// Finding a kill requires a real pinch-point.
// Check for not already having a pinch-point.
// Pinch points are Op_Node's.
! if( pinch->Opcode() != Opcodes::Op_Node ) { // Or later-def/kill as pinch-point?
later_def = pinch; // Must be def/kill as optimistic pinch-point
if ( _pinch_free_list.size() > 0) {
pinch = _pinch_free_list.pop();
} else {
pinch = new Node(1); // Pinch point to-be
*** 2583,2593 ****
return;
}
_cfg->map_node_to_block(pinch, b); // Pretend it's valid in this block (lazy init)
_reg_node.map(def_reg,pinch); // Record pinch-point
//_regalloc->set_bad(pinch->_idx); // Already initialized this way.
! if( later_def->outcnt() == 0 || later_def->ideal_reg() == MachProjNode::fat_proj ) { // Distinguish def from kill
pinch->init_req(0, _cfg->C->top()); // set not NULL for the next call
add_prec_edge_from_to(later_def,pinch); // Add edge from kill to pinch
later_def = NULL; // and no later def
}
pinch->set_req(0,later_def); // Hook later def so we can find it
--- 2583,2593 ----
return;
}
_cfg->map_node_to_block(pinch, b); // Pretend it's valid in this block (lazy init)
_reg_node.map(def_reg,pinch); // Record pinch-point
//_regalloc->set_bad(pinch->_idx); // Already initialized this way.
! if( later_def->outcnt() == 0 || later_def->ideal_reg() == static_cast<Opcodes>(MachProjNode::projType::fat_proj) ) { // Distinguish def from kill
pinch->init_req(0, _cfg->C->top()); // set not NULL for the next call
add_prec_edge_from_to(later_def,pinch); // Add edge from kill to pinch
later_def = NULL; // and no later def
}
pinch->set_req(0,later_def); // Hook later def so we can find it
*** 2599,2609 ****
// Add output-dependence edge from later def to kill
if( later_def ) // If there is some original def
add_prec_edge_from_to(later_def,kill); // Add edge from def to kill
// See if current kill is also a use, and so is forced to be the pinch-point.
! if( pinch->Opcode() == Op_Node ) {
Node *uses = kill->is_Proj() ? kill->in(0) : kill;
for( uint i=1; i<uses->req(); i++ ) {
if( _regalloc->get_reg_first(uses->in(i)) == def_reg ||
_regalloc->get_reg_second(uses->in(i)) == def_reg ) {
// Yes, found a use/kill pinch-point
--- 2599,2609 ----
// Add output-dependence edge from later def to kill
if( later_def ) // If there is some original def
add_prec_edge_from_to(later_def,kill); // Add edge from def to kill
// See if current kill is also a use, and so is forced to be the pinch-point.
! if( pinch->Opcode() == Opcodes::Op_Node ) {
Node *uses = kill->is_Proj() ? kill->in(0) : kill;
for( uint i=1; i<uses->req(); i++ ) {
if( _regalloc->get_reg_first(uses->in(i)) == def_reg ||
_regalloc->get_reg_second(uses->in(i)) == def_reg ) {
// Yes, found a use/kill pinch-point
*** 2626,2636 ****
Node *pinch = _reg_node[use_reg]; // Get pinch point
// Check for no later def_reg/kill in block
if ((pinch != NULL) && _cfg->get_block_for_node(pinch) == b &&
// Use has to be block-local as well
_cfg->get_block_for_node(use) == b) {
! if( pinch->Opcode() == Op_Node && // Real pinch-point (not optimistic?)
pinch->req() == 1 ) { // pinch not yet in block?
pinch->del_req(0); // yank pointer to later-def, also set flag
// Insert the pinch-point in the block just after the last use
b->insert_node(pinch, b->find_node(use) + 1);
_bb_end++; // Increase size scheduled region in block
--- 2626,2636 ----
Node *pinch = _reg_node[use_reg]; // Get pinch point
// Check for no later def_reg/kill in block
if ((pinch != NULL) && _cfg->get_block_for_node(pinch) == b &&
// Use has to be block-local as well
_cfg->get_block_for_node(use) == b) {
! if( pinch->Opcode() == Opcodes::Op_Node && // Real pinch-point (not optimistic?)
pinch->req() == 1 ) { // pinch not yet in block?
pinch->del_req(0); // yank pointer to later-def, also set flag
// Insert the pinch-point in the block just after the last use
b->insert_node(pinch, b->find_node(use) + 1);
_bb_end++; // Increase size scheduled region in block
*** 2687,2697 ****
Node* end_node = (_bb_end-1 >= _bb_start) ? b->get_node(last_safept) : NULL;
Node* last_safept_node = end_node;
for( uint i = _bb_end-1; i >= _bb_start; i-- ) {
Node *n = b->get_node(i);
int is_def = n->outcnt(); // def if some uses prior to adding precedence edges
! if( n->is_MachProj() && n->ideal_reg() == MachProjNode::fat_proj ) {
// Fat-proj kills a slew of registers
// This can add edges to 'n' and obscure whether or not it was a def,
// hence the is_def flag.
fat_proj_seen = true;
RegMask rm = n->out_RegMask();// Make local copy
--- 2687,2697 ----
Node* end_node = (_bb_end-1 >= _bb_start) ? b->get_node(last_safept) : NULL;
Node* last_safept_node = end_node;
for( uint i = _bb_end-1; i >= _bb_start; i-- ) {
Node *n = b->get_node(i);
int is_def = n->outcnt(); // def if some uses prior to adding precedence edges
! if( n->is_MachProj() && n->ideal_reg() == static_cast<Opcodes>(MachProjNode::projType::fat_proj) ) {
// Fat-proj kills a slew of registers
// This can add edges to 'n' and obscure whether or not it was a def,
// hence the is_def flag.
fat_proj_seen = true;
RegMask rm = n->out_RegMask();// Make local copy
*** 2707,2717 ****
}
// Kill projections on a branch should appear to occur on the
// branch, not afterwards, so grab the masks from the projections
// and process them.
! if (n->is_MachBranch() || n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_Jump) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* use = n->fast_out(i);
if (use->is_Proj()) {
RegMask rm = use->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
--- 2707,2717 ----
}
// Kill projections on a branch should appear to occur on the
// branch, not afterwards, so grab the masks from the projections
// and process them.
! if (n->is_MachBranch() || n->is_Mach() && n->as_Mach()->ideal_Opcode() == Opcodes::Op_Jump) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* use = n->fast_out(i);
if (use->is_Proj()) {
RegMask rm = use->out_RegMask();// Make local copy
while( rm.is_NotEmpty() ) {
*** 2726,2736 ****
// Check each register used by this instruction for a following DEF/KILL
// that must occur afterward and requires an anti-dependence edge.
for( uint j=0; j<n->req(); j++ ) {
Node *def = n->in(j);
if( def ) {
! assert( !def->is_MachProj() || def->ideal_reg() != MachProjNode::fat_proj, "" );
anti_do_use( b, n, _regalloc->get_reg_first(def) );
anti_do_use( b, n, _regalloc->get_reg_second(def) );
}
}
// Do not allow defs of new derived values to float above GC
--- 2726,2736 ----
// Check each register used by this instruction for a following DEF/KILL
// that must occur afterward and requires an anti-dependence edge.
for( uint j=0; j<n->req(); j++ ) {
Node *def = n->in(j);
if( def ) {
! assert( !def->is_MachProj() || def->ideal_reg() != static_cast<Opcodes>(MachProjNode::projType::fat_proj), "" );
anti_do_use( b, n, _regalloc->get_reg_first(def) );
anti_do_use( b, n, _regalloc->get_reg_second(def) );
}
}
// Do not allow defs of new derived values to float above GC
*** 2756,2766 ****
if( b->get_node(last_safept) != last_safept_node ) {
last_safept = b->find_node(last_safept_node);
}
for( uint j=last_safept; j > i; j-- ) {
Node *mach = b->get_node(j);
! if( mach->is_Mach() && mach->as_Mach()->ideal_Opcode() == Op_AddP )
mach->add_prec( n );
}
last_safept = i;
last_safept_node = m;
}
--- 2756,2766 ----
if( b->get_node(last_safept) != last_safept_node ) {
last_safept = b->find_node(last_safept_node);
}
for( uint j=last_safept; j > i; j-- ) {
Node *mach = b->get_node(j);
! if( mach->is_Mach() && mach->as_Mach()->ideal_Opcode() == Opcodes::Op_AddP )
mach->add_prec( n );
}
last_safept = i;
last_safept_node = m;
}
*** 2802,2812 ****
if (_cfg->C->trace_opto_output()) tty->print("Reclaimed pinch nodes:");
#endif
int trace_cnt = 0;
for (uint k = 0; k < _reg_node.Size(); k++) {
Node* pinch = _reg_node[k];
! if ((pinch != NULL) && pinch->Opcode() == Op_Node &&
// no predecence input edges
(pinch->req() == pinch->len() || pinch->in(pinch->req()) == NULL) ) {
cleanup_pinch(pinch);
_pinch_free_list.push(pinch);
_reg_node.map(k, NULL);
--- 2802,2812 ----
if (_cfg->C->trace_opto_output()) tty->print("Reclaimed pinch nodes:");
#endif
int trace_cnt = 0;
for (uint k = 0; k < _reg_node.Size(); k++) {
Node* pinch = _reg_node[k];
! if ((pinch != NULL) && pinch->Opcode() == Opcodes::Op_Node &&
// no predecence input edges
(pinch->req() == pinch->len() || pinch->in(pinch->req()) == NULL) ) {
cleanup_pinch(pinch);
_pinch_free_list.push(pinch);
_reg_node.map(k, NULL);
*** 2827,2837 ****
#endif
}
// Clean up a pinch node for reuse.
void Scheduling::cleanup_pinch( Node *pinch ) {
! assert (pinch && pinch->Opcode() == Op_Node && pinch->req() == 1, "just checking");
for (DUIterator_Last imin, i = pinch->last_outs(imin); i >= imin; ) {
Node* use = pinch->last_out(i);
uint uses_found = 0;
for (uint j = use->req(); j < use->len(); j++) {
--- 2827,2837 ----
#endif
}
// Clean up a pinch node for reuse.
void Scheduling::cleanup_pinch( Node *pinch ) {
! assert (pinch && pinch->Opcode() == Opcodes::Op_Node && pinch->req() == 1, "just checking");
for (DUIterator_Last imin, i = pinch->last_outs(imin); i >= imin; ) {
Node* use = pinch->last_out(i);
uint uses_found = 0;
for (uint j = use->req(); j < use->len(); j++) {
< prev index next >