< prev index next > src/hotspot/share/opto/lcm.cpp
Print this page
} else {
// only regular oops are expected here
tptr = base->bottom_type()->is_ptr();
}
// Give up if offset is not a compile-time constant.
! if (offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot)
continue;
! offset += tptr->_offset; // correct if base is offsetted
// Give up if reference is beyond page size.
if (MacroAssembler::needs_explicit_null_check(offset))
continue;
// Give up if base is a decode node and the heap base is not protected.
if (base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_DecodeN &&
} else {
// only regular oops are expected here
tptr = base->bottom_type()->is_ptr();
}
// Give up if offset is not a compile-time constant.
! if (offset == Type::OffsetBot || tptr->offset() == Type::OffsetBot)
continue;
! offset += tptr->offset(); // correct if base is offsetted
// Give up if reference is beyond page size.
if (MacroAssembler::needs_explicit_null_check(offset))
continue;
// Give up if base is a decode node and the heap base is not protected.
if (base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_DecodeN &&
vidx = j;
// Ignore DecodeN val which could be hoisted to where needed.
if( is_decoden ) continue;
}
// Block of memory-op input
! Block *inb = get_block_for_node(mach->in(j));
Block *b = block; // Start from nul check
while( b != inb && b->_dom_depth > inb->_dom_depth )
b = b->_idom; // search upwards for input
// See if input dominates null check
if( b != inb )
vidx = j;
// Ignore DecodeN val which could be hoisted to where needed.
if( is_decoden ) continue;
}
// Block of memory-op input
! Block* inb = get_block_for_node(mach->in(j));
+ if (mach->in(j)->is_Con() && mach->in(j)->req() == 1 && inb == get_block_for_node(mach)) {
+ // Ignore constant loads scheduled in the same block (we can simply hoist them as well)
+ continue;
+ }
Block *b = block; // Start from nul check
while( b != inb && b->_dom_depth > inb->_dom_depth )
b = b->_idom; // search upwards for input
// See if input dominates null check
if( b != inb )
map_node_to_block(n, block);
}
}
}
}
+
+ // Hoist constant load inputs as well.
+ for (uint i = 1; i < best->req(); ++i) {
+ Node* n = best->in(i);
+ if (n->is_Con() && get_block_for_node(n) == get_block_for_node(best)) {
+ get_block_for_node(n)->find_remove(n);
+ block->add_inst(n);
+ map_node_to_block(n, block);
+ // Constant loads may kill flags (for example, when XORing a register).
+ // Check for flag-killing projections that also need to be hoisted.
+ for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
+ Node* proj = n->fast_out(j);
+ if (proj->is_MachProj()) {
+ get_block_for_node(proj)->find_remove(proj);
+ block->add_inst(proj);
+ map_node_to_block(proj, block);
+ }
+ }
+ }
+ }
+
// Hoist the memory candidate up to the end of the test block.
Block *old_block = get_block_for_node(best);
old_block->find_remove(best);
block->add_inst(best);
map_node_to_block(best, block);
// Act as if the call defines the Frame Pointer.
// Certainly the FP is alive and well after the call.
regs.Insert(_matcher.c_frame_pointer());
// 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 MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj );
map_node_to_block(proj, block);
block->insert_node(proj, node_cnt++);
// Act as if the call defines the Frame Pointer.
// Certainly the FP is alive and well after the call.
regs.Insert(_matcher.c_frame_pointer());
// Set all registers killed and not already defined by the call.
! uint r_cnt = mcall->tf()->range_cc()->cnt();
int op = mcall->ideal_Opcode();
MachProjNode *proj = new MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj );
map_node_to_block(proj, block);
block->insert_node(proj, node_cnt++);
< prev index next >