src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/memnode.cpp Tue Mar 17 11:32:56 2015
--- new/src/share/vm/opto/memnode.cpp Tue Mar 17 11:32:56 2015
*** 650,869 ****
--- 650,659 ----
#endif
return tp;
}
}
//------------------------adr_phi_is_loop_invariant----------------------------
// A helper function for Ideal_DU_postCCP to check if a Phi in a counted
// loop is loop invariant. Make a quick traversal of Phi and associated
// CastPP nodes, looking to see if they are a closed group within the loop.
bool MemNode::adr_phi_is_loop_invariant(Node* adr_phi, Node* cast) {
// The idea is that the phi-nest must boil down to only CastPP nodes
// with the same data. This implies that any path into the loop already
// includes such a CastPP, and so the original cast, whatever its input,
// must be covered by an equivalent cast, with an earlier control input.
ResourceMark rm;
// The loop entry input of the phi should be the unique dominating
// node for every Phi/CastPP in the loop.
Unique_Node_List closure;
closure.push(adr_phi->in(LoopNode::EntryControl));
// Add the phi node and the cast to the worklist.
Unique_Node_List worklist;
worklist.push(adr_phi);
if( cast != NULL ){
if( !cast->is_ConstraintCast() ) return false;
worklist.push(cast);
}
// Begin recursive walk of phi nodes.
while( worklist.size() ){
// Take a node off the worklist
Node *n = worklist.pop();
if( !closure.member(n) ){
// Add it to the closure.
closure.push(n);
// Make a sanity check to ensure we don't waste too much time here.
if( closure.size() > 20) return false;
// This node is OK if:
// - it is a cast of an identical value
// - or it is a phi node (then we add its inputs to the worklist)
// Otherwise, the node is not OK, and we presume the cast is not invariant
if( n->is_ConstraintCast() ){
worklist.push(n->in(1));
} else if( n->is_Phi() ) {
for( uint i = 1; i < n->req(); i++ ) {
worklist.push(n->in(i));
}
} else {
return false;
}
}
}
// Quit when the worklist is empty, and we've found no offending nodes.
return true;
}
//------------------------------Ideal_DU_postCCP-------------------------------
// Find any cast-away of null-ness and keep its control. Null cast-aways are
// going away in this pass and we need to make this memory op depend on the
// gating null check.
Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
return Ideal_common_DU_postCCP(ccp, this, in(MemNode::Address));
}
// I tried to leave the CastPP's in. This makes the graph more accurate in
// some sense; we get to keep around the knowledge that an oop is not-null
// after some test. Alas, the CastPP's interfere with GVN (some values are
// the regular oop, some are the CastPP of the oop, all merge at Phi's which
// cannot collapse, etc). This cost us 10% on SpecJVM, even when I removed
// some of the more trivial cases in the optimizer. Removing more useless
// Phi's started allowing Loads to illegally float above null checks. I gave
// up on this approach. CNC 10/20/2000
// This static method may be called not from MemNode (EncodePNode calls it).
// Only the control edge of the node 'n' might be updated.
Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) {
Node *skipped_cast = NULL;
// Need a null check? Regular static accesses do not because they are
// from constant addresses. Array ops are gated by the range check (which
// always includes a NULL check). Just check field ops.
if( n->in(MemNode::Control) == NULL ) {
// Scan upwards for the highest location we can place this memory op.
while( true ) {
switch( adr->Opcode() ) {
case Op_AddP: // No change to NULL-ness, so peek thru AddP's
adr = adr->in(AddPNode::Base);
continue;
case Op_DecodeN: // No change to NULL-ness, so peek thru
case Op_DecodeNKlass:
adr = adr->in(1);
continue;
case Op_EncodeP:
case Op_EncodePKlass:
// EncodeP node's control edge could be set by this method
// when EncodeP node depends on CastPP node.
//
// Use its control edge for memory op because EncodeP may go away
// later when it is folded with following or preceding DecodeN node.
if (adr->in(0) == NULL) {
// Keep looking for cast nodes.
adr = adr->in(1);
continue;
}
ccp->hash_delete(n);
n->set_req(MemNode::Control, adr->in(0));
ccp->hash_insert(n);
return n;
case Op_CastPP:
// If the CastPP is useless, just peek on through it.
if( ccp->type(adr) == ccp->type(adr->in(1)) ) {
// Remember the cast that we've peeked though. If we peek
// through more than one, then we end up remembering the highest
// one, that is, if in a loop, the one closest to the top.
skipped_cast = adr;
adr = adr->in(1);
continue;
}
// CastPP is going away in this pass! We need this memory op to be
// control-dependent on the test that is guarding the CastPP.
ccp->hash_delete(n);
n->set_req(MemNode::Control, adr->in(0));
ccp->hash_insert(n);
return n;
case Op_Phi:
// Attempt to float above a Phi to some dominating point.
if (adr->in(0) != NULL && adr->in(0)->is_CountedLoop()) {
// If we've already peeked through a Cast (which could have set the
// control), we can't float above a Phi, because the skipped Cast
// may not be loop invariant.
if (adr_phi_is_loop_invariant(adr, skipped_cast)) {
adr = adr->in(1);
continue;
}
}
// Intentional fallthrough!
// No obvious dominating point. The mem op is pinned below the Phi
// by the Phi itself. If the Phi goes away (no true value is merged)
// then the mem op can float, but not indefinitely. It must be pinned
// behind the controls leading to the Phi.
case Op_CheckCastPP:
// These usually stick around to change address type, however a
// useless one can be elided and we still need to pick up a control edge
if (adr->in(0) == NULL) {
// This CheckCastPP node has NO control and is likely useless. But we
// need check further up the ancestor chain for a control input to keep
// the node in place. 4959717.
skipped_cast = adr;
adr = adr->in(1);
continue;
}
ccp->hash_delete(n);
n->set_req(MemNode::Control, adr->in(0));
ccp->hash_insert(n);
return n;
// List of "safe" opcodes; those that implicitly block the memory
// op below any null check.
case Op_CastX2P: // no null checks on native pointers
case Op_Parm: // 'this' pointer is not null
case Op_LoadP: // Loading from within a klass
case Op_LoadN: // Loading from within a klass
case Op_LoadKlass: // Loading from within a klass
case Op_LoadNKlass: // Loading from within a klass
case Op_ConP: // Loading from a klass
case Op_ConN: // Loading from a klass
case Op_ConNKlass: // Loading from a klass
case Op_CreateEx: // Sucking up the guts of an exception oop
case Op_Con: // Reading from TLS
case Op_CMoveP: // CMoveP is pinned
case Op_CMoveN: // CMoveN is pinned
break; // No progress
case Op_Proj: // Direct call to an allocation routine
case Op_SCMemProj: // Memory state from store conditional ops
#ifdef ASSERT
{
assert(adr->as_Proj()->_con == TypeFunc::Parms, "must be return value");
const Node* call = adr->in(0);
if (call->is_CallJava()) {
const CallJavaNode* call_java = call->as_CallJava();
const TypeTuple *r = call_java->tf()->range();
assert(r->cnt() > TypeFunc::Parms, "must return value");
const Type* ret_type = r->field_at(TypeFunc::Parms);
assert(ret_type && ret_type->isa_ptr(), "must return pointer");
// We further presume that this is one of
// new_instance_Java, new_array_Java, or
// the like, but do not assert for this.
} else if (call->is_Allocate()) {
// similar case to new_instance_Java, etc.
} else if (!call->is_CallLeaf()) {
// Projections from fetch_oop (OSR) are allowed as well.
ShouldNotReachHere();
}
}
#endif
break;
default:
ShouldNotReachHere();
}
break;
}
}
return NULL; // No progress
}
//=============================================================================
// Should LoadNode::Ideal() attempt to remove control edges?
bool LoadNode::can_remove_control() const {
return true;
}
src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File