src/share/vm/opto/lcm.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/lcm.cpp Fri Aug 23 23:47:49 2013
--- new/src/share/vm/opto/lcm.cpp Fri Aug 23 23:47:48 2013
*** 73,87 ****
--- 73,87 ----
bool was_store; // Memory op is a store op
// Get the successor block for if the test ptr is non-null
Block* not_null_block; // this one goes with the proj
Block* null_block;
! if (_nodes[_nodes.size()-1] == proj) {
! if (get_node(number_of_nodes()-1) == proj) {
null_block = _succs[0];
not_null_block = _succs[1];
} else {
! assert(_nodes[_nodes.size()-2] == proj, "proj is one or the other");
! assert(get_node(number_of_nodes()-2) == proj, "proj is one or the other");
not_null_block = _succs[0];
null_block = _succs[1];
}
while (null_block->is_Empty() == Block::empty_with_goto) {
null_block = null_block->_succs[0];
*** 92,102 ****
--- 92,102 ----
// we need an uncommon trap. Briefly, we need a way to
// detect failure of this optimization, as in 6366351.)
{
bool found_trap = false;
for (uint i1 = 0; i1 < null_block->_nodes.size(); i1++) {
! Node* nn = null_block->_nodes[i1];
! Node* nn = null_block->get_node(i1);
if (nn->is_MachCall() &&
nn->as_MachCall()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) {
const Type* trtype = nn->in(TypeFunc::Parms)->bottom_type();
if (trtype->isa_int() && trtype->is_int()->is_con()) {
jint tr_con = trtype->is_int()->get_con();
*** 280,290 ****
--- 280,290 ----
// mach use (faulting) trying to hoist
// n might be blocker to hoisting
while( b != this ) {
uint k;
for( k = 1; k < b->_nodes.size(); k++ ) {
! Node *n = b->_nodes[k];
! Node *n = b->get_node(k);
if( n->needs_anti_dependence_check() &&
n->in(LoadNode::Memory) == mach->in(StoreNode::Memory) )
break; // Found anti-dependent load
}
if( k < b->_nodes.size() )
*** 342,353 ****
--- 342,353 ----
old_block->find_remove(best);
add_inst(best);
cfg->map_node_to_block(best, this);
// Move the control dependence
! if (best->in(0) && best->in(0) == old_block->_nodes[0])
! best->set_req(0, _nodes[0]);
! if (best->in(0) && best->in(0) == old_block->head())
! best->set_req(0, head());
// Check for flag-killing projections that also need to be hoisted
// Should be DU safe because no edge updates.
for (DUIterator_Fast jmax, j = best->fast_outs(jmax); j < jmax; j++) {
Node* n = best->fast_out(j);
*** 366,377 ****
--- 366,377 ----
// NULL checks are always branch-if-eq. If we see a IfTrue projection
// then we are replacing a 'ne' test with a 'eq' NULL check test.
// We need to flip the projections to keep the same semantics.
if( proj->Opcode() == Op_IfTrue ) {
// Swap order of projections in basic block to swap branch targets
! Node *tmp1 = _nodes[end_idx()+1];
! Node *tmp2 = _nodes[end_idx()+2];
! Node *tmp1 = get_node(end_idx()+1);
! Node *tmp2 = get_node(end_idx()+2);
_nodes.map(end_idx()+1, tmp2);
_nodes.map(end_idx()+2, tmp1);
Node *tmp = new (C) Node(C->top()); // Use not NULL input
tmp1->replace_by(tmp);
tmp2->replace_by(tmp1);
*** 622,632 ****
--- 622,632 ----
// Set all registers killed and not already defined by the call.
uint r_cnt = mcall->tf()->range()->cnt();
int op = mcall->ideal_Opcode();
MachProjNode *proj = new (matcher.C) MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj );
cfg->map_node_to_block(proj, this);
! _nodes.insert(node_cnt++, proj);
! insert_node(proj, node_cnt++);
// Select the right register save policy.
const char * save_policy;
switch (op) {
case Op_CallRuntime:
*** 683,693 ****
--- 683,693 ----
#ifndef PRODUCT
if (cfg->trace_opto_pipelining()) {
tty->print_cr("# --- schedule_local B%d, before: ---", _pre_order);
for (uint i = 0;i < _nodes.size();i++) {
tty->print("# ");
! _nodes[i]->fast_dump();
! get_node(i)->fast_dump();
}
tty->print_cr("#");
}
#endif
*** 697,711 ****
--- 697,711 ----
// Move PhiNodes and ParmNodes from 1 to cnt up to the start
uint node_cnt = end_idx();
uint phi_cnt = 1;
uint i;
for( i = 1; i<node_cnt; i++ ) { // Scan for Phi
! Node *n = _nodes[i];
! Node *n = get_node(i);
if( n->is_Phi() || // Found a PhiNode or ParmNode
(n->is_Proj() && n->in(0) == head()) ) {
// Move guy at 'phi_cnt' to the end; makes a hole at phi_cnt
! _nodes.map(i,_nodes[phi_cnt]);
! _nodes.map(i,get_node(phi_cnt));
_nodes.map(phi_cnt++,n); // swap Phi/Parm up front
} else { // All others
// Count block-local inputs to 'n'
uint cnt = n->len(); // Input count
uint local = 0;
*** 746,761 ****
--- 746,761 ----
n->add_prec(x);
}
}
}
for(uint i2=i; i2<_nodes.size(); i2++ ) // Trailing guys get zapped count
! ready_cnt.at_put(_nodes[i2]->_idx, 0);
! ready_cnt.at_put(get_node(i2)->_idx, 0);
// All the prescheduled guys do not hold back internal nodes
uint i3;
for(i3 = 0; i3<phi_cnt; i3++ ) { // For all pre-scheduled
! Node *n = _nodes[i3]; // Get pre-scheduled
! Node *n = get_node(i3); // Get pre-scheduled
for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
Node* m = n->fast_out(j);
if (cfg->get_block_for_node(m) == this) { // Local-block user
int m_cnt = ready_cnt.at(m->_idx)-1;
ready_cnt.at_put(m->_idx, m_cnt); // Fix ready count
*** 765,775 ****
--- 765,775 ----
Node_List delay;
// Make a worklist
Node_List worklist;
for(uint i4=i3; i4<node_cnt; i4++ ) { // Put ready guys on worklist
! Node *m = _nodes[i4];
! Node *m = get_node(i4);
if( !ready_cnt.at(m->_idx) ) { // Zero ready count?
if (m->is_iteratively_computed()) {
// Push induction variable increments last to allow other uses
// of the phi to be scheduled first. The select() method breaks
// ties in scheduling by worklist order.
*** 787,802 ****
--- 787,802 ----
Node* d = delay.pop();
worklist.push(d);
}
// Warm up the 'next_call' heuristic bits
! needed_for_next_call(_nodes[0], next_call, cfg);
! needed_for_next_call(head(), next_call, cfg);
#ifndef PRODUCT
if (cfg->trace_opto_pipelining()) {
for (uint j=0; j<_nodes.size(); j++) {
! Node *n = _nodes[j];
! Node *n = get_node(j);
int idx = n->_idx;
tty->print("# ready cnt:%3d ", ready_cnt.at(idx));
tty->print("latency:%3d ", cfg->get_latency_for_node(n));
tty->print("%4d: %s\n", idx, n->Name());
}
*** 849,859 ****
--- 849,859 ----
regs.Insert(matcher.c_frame_pointer());
regs.OR(n->out_RegMask());
MachProjNode *proj = new (matcher.C) MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj );
cfg->map_node_to_block(proj, this);
! _nodes.insert(phi_cnt++, proj);
! insert_node(proj, phi_cnt++);
add_call_kills(proj, regs, matcher._c_reg_save_policy, false);
}
// Children are now all ready
*** 891,901 ****
--- 891,901 ----
if (cfg->trace_opto_pipelining()) {
tty->print_cr("#");
tty->print_cr("# after schedule_local");
for (uint i = 0;i < _nodes.size();i++) {
tty->print("# ");
! _nodes[i]->fast_dump();
! get_node(i)->fast_dump();
}
tty->cr();
}
#endif
*** 950,960 ****
--- 950,960 ----
}
// Check to see if the use_blk already has an identical phi inserted.
// If it exists, it will be at the first position since all uses of a
// def are processed together.
! Node *phi = use_blk->_nodes[1];
! Node *phi = use_blk->get_node(1);
if( phi->is_Phi() ) {
fixup = phi;
for (uint k = 1; k < use_blk->num_preds(); k++) {
if (phi->in(k) != inputs[k]) {
// Not a match
*** 965,985 ****
--- 965,985 ----
}
// If an existing PhiNode was not found, make a new one.
if (fixup == NULL) {
Node *new_phi = PhiNode::make(use_blk->head(), def);
! use_blk->_nodes.insert(1, new_phi);
! use_blk->insert_node(new_phi, 1);
cfg->map_node_to_block(new_phi, use_blk);
for (uint k = 1; k < use_blk->num_preds(); k++) {
new_phi->set_req(k, inputs[k]);
}
fixup = new_phi;
}
} else {
// Found the use just below the Catch. Make it use the clone.
! fixup = use_blk->_nodes[n_clone_idx];
! fixup = use_blk->get_node(n_clone_idx);
}
return fixup;
}
*** 995,1009 ****
--- 995,1009 ----
uint use_idx = blk->find_node(use);
uint offset_idx = use_idx - beg;
for( uint k = 0; k < blk->_num_succs; k++ ) {
// Get clone in each successor block
Block *sb = blk->_succs[k];
! Node *clone = sb->_nodes[offset_idx+1];
! Node *clone = sb->get_node(offset_idx+1);
assert( clone->Opcode() == use->Opcode(), "" );
// Make use-clone reference the def-clone
! catch_cleanup_fix_all_inputs(clone, def, sb->_nodes[n_clone_idx]);
! catch_cleanup_fix_all_inputs(clone, def, sb->get_node(n_clone_idx));
}
}
//------------------------------catch_cleanup_inter_block---------------------
// Fix all input edges in use that reference "def". The use is in a different
*** 1020,1034 ****
--- 1020,1034 ----
// clone the instructions on all paths below the Catch.
void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) {
// End of region to clone
uint end = end_idx();
! if( !_nodes[end]->is_Catch() ) return;
! if( !get_node(end)->is_Catch() ) return;
// Start of region to clone
uint beg = end;
! while(!_nodes[beg-1]->is_MachProj() ||
! !_nodes[beg-1]->in(0)->is_MachCall() ) {
! while(!get_node(beg-1)->is_MachProj() ||
! !get_node(beg-1)->in(0)->is_MachCall() ) {
beg--;
assert(beg > 0,"Catch cleanup walking beyond block boundary");
}
// Range of inserted instructions is [beg, end)
if( beg == end ) return;
*** 1039,1059 ****
--- 1039,1059 ----
Block *sb = _succs[i];
// Clone the entire area; ignoring the edge fixup for now.
for( uint j = end; j > beg; j-- ) {
// It is safe here to clone a node with anti_dependence
// since clones dominate on each path.
! Node *clone = _nodes[j-1]->clone();
! sb->_nodes.insert( 1, clone );
! Node *clone = get_node(j-1)->clone();
! sb->insert_node(clone, 1);
cfg->map_node_to_block(clone, sb);
}
}
// Fixup edges. Check the def-use info per cloned Node
for(uint i2 = beg; i2 < end; i2++ ) {
uint n_clone_idx = i2-beg+1; // Index of clone of n in each successor block
! Node *n = _nodes[i2]; // Node that got cloned
! Node *n = get_node(i2); // Node that got cloned
// Need DU safe iterator because of edge manipulation in calls.
Unique_Node_List *out = new Unique_Node_List(Thread::current()->resource_area());
for (DUIterator_Fast j1max, j1 = n->fast_outs(j1max); j1 < j1max; j1++) {
out->push(n->fast_out(j1));
}
*** 1079,1111 ****
--- 1079,1111 ----
} // End of for all Nodes in cloned area
// Remove the now-dead cloned ops
for(uint i3 = beg; i3 < end; i3++ ) {
! _nodes[beg]->disconnect_inputs(NULL, C);
! _nodes.remove(beg);
! get_node(beg)->disconnect_inputs(NULL, C);
! remove_node(beg);
}
// If the successor blocks have a CreateEx node, move it back to the top
for(uint i4 = 0; i4 < _num_succs; i4++ ) {
Block *sb = _succs[i4];
uint new_cnt = end - beg;
// Remove any newly created, but dead, nodes.
for( uint j = new_cnt; j > 0; j-- ) {
! Node *n = sb->_nodes[j];
! Node *n = sb->get_node(j);
if (n->outcnt() == 0 &&
(!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){
n->disconnect_inputs(NULL, C);
! sb->_nodes.remove(j);
! sb->remove_node(j);
new_cnt--;
}
}
// If any newly created nodes remain, move the CreateEx node to the top
if (new_cnt > 0) {
! Node *cex = sb->_nodes[1+new_cnt];
! Node *cex = sb->get_node(1+new_cnt);
if( cex->is_Mach() && cex->as_Mach()->ideal_Opcode() == Op_CreateEx ) {
! sb->_nodes.remove(1+new_cnt);
! sb->_nodes.insert(1,cex);
! sb->remove_node(1+new_cnt);
! sb->insert_node(cex, 1);
}
}
}
}
src/share/vm/opto/lcm.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File