src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
6695810 Cdiff src/share/vm/opto/memnode.cpp
src/share/vm/opto/memnode.cpp
Print this page
*** 131,141 ****
result = optimize_simple_memory_chain(result, t_adr, phase);
if (is_instance && igvn != NULL && result->is_Phi()) {
PhiNode *mphi = result->as_Phi();
assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
const TypePtr *t = mphi->adr_type();
! if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM) {
// clone the Phi with our address type
result = mphi->split_out_instance(t_adr, igvn);
} else {
assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain");
}
--- 131,143 ----
result = optimize_simple_memory_chain(result, t_adr, phase);
if (is_instance && igvn != NULL && result->is_Phi()) {
PhiNode *mphi = result->as_Phi();
assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
const TypePtr *t = mphi->adr_type();
! if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM ||
! t->isa_oopptr() && !t->is_oopptr()->is_instance() &&
! t->is_oopptr()->cast_to_instance(t_oop->instance_id()) == t_oop) {
// clone the Phi with our address type
result = mphi->split_out_instance(t_adr, igvn);
} else {
assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain");
}
*** 261,271 ****
// 'dom' dominates 'sub' if its control edge and control edges
// of all its inputs dominate or equal to sub's control edge.
// Currently 'sub' is either Allocate, Initialize or Start nodes.
! assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start(), "expecting only these nodes");
// Get control edge of 'sub'.
sub = sub->find_exact_control(sub->in(0));
if (sub == NULL || sub->is_top())
return false; // Conservative answer for dead code
--- 263,276 ----
// 'dom' dominates 'sub' if its control edge and control edges
// of all its inputs dominate or equal to sub's control edge.
// Currently 'sub' is either Allocate, Initialize or Start nodes.
! // Or Region for the check in LoadNode::Ideal();
! // 'sub' should have sub->in(0) != NULL.
! assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start() ||
! sub->is_Region(), "expecting only these nodes");
// Get control edge of 'sub'.
sub = sub->find_exact_control(sub->in(0));
if (sub == NULL || sub->is_top())
return false; // Conservative answer for dead code
*** 574,601 ****
//------------------------------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.
// 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
! Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
! Node *ctr = in(MemNode::Control);
! Node *mem = in(MemNode::Memory);
! Node *adr = in(MemNode::Address);
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( !ctr ) {
// 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
--- 579,606 ----
//------------------------------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
! 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
*** 616,629 ****
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(this);
! set_req(MemNode::Control, adr->in(0));
! ccp->hash_insert(this);
! return this;
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
--- 621,634 ----
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
*** 650,672 ****
// the node in place. 4959717.
skipped_cast = adr;
adr = adr->in(1);
continue;
}
! ccp->hash_delete(this);
! set_req(MemNode::Control, adr->in(0));
! ccp->hash_insert(this);
! return this;
// 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_ConP: // 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
break; // No progress
--- 655,678 ----
// 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_ConP: // Loading from a klass
+ case Op_ConN: // 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
break; // No progress
*** 674,685 ****
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_CallStaticJava()) {
! const CallStaticJavaNode* call_java = call->as_CallStaticJava();
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
--- 680,691 ----
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
*** 747,757 ****
case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt );
case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt );
case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() );
case T_OBJECT:
#ifdef _LP64
! if (adr->bottom_type()->is_narrow()) {
const TypeNarrowOop* narrowtype;
if (rt->isa_narrowoop()) {
narrowtype = rt->is_narrowoop();
} else {
narrowtype = rt->is_oopptr()->make_narrowoop();
--- 753,763 ----
case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt );
case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt );
case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() );
case T_OBJECT:
#ifdef _LP64
! if (adr->bottom_type()->is_ptr_to_narrowoop()) {
const TypeNarrowOop* narrowtype;
if (rt->isa_narrowoop()) {
narrowtype = rt->is_narrowoop();
} else {
narrowtype = rt->is_oopptr()->make_narrowoop();
*** 760,770 ****
return DecodeNNode::decode(&gvn, load);
} else
#endif
{
! assert(!adr->bottom_type()->is_narrow(), "should have got back a narrow oop");
return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
}
}
ShouldNotReachHere();
return (LoadNode*)NULL;
--- 766,776 ----
return DecodeNNode::decode(&gvn, load);
} else
#endif
{
! assert(!adr->bottom_type()->is_ptr_to_narrowoop(), "should have got back a narrow oop");
return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
}
}
ShouldNotReachHere();
return (LoadNode*)NULL;
*** 1203,1212 ****
--- 1209,1223 ----
// Do nothing here if Identity will find a value
// (to avoid infinite chain of value phis generation).
if ( !phase->eqv(this, this->Identity(phase)) )
return NULL;
+ // Skip the split if the loop head dominates some control edges
+ // of the address.
+ if (cnt == 3 && !MemNode::all_controls_dominate(address, region))
+ goto find_store;
+
const Type* this_type = this->bottom_type();
int this_index = phase->C->get_alias_index(addr_t);
int this_offset = addr_t->offset();
int this_iid = addr_t->is_oopptr()->instance_id();
int wins = 0;
*** 1281,1291 ****
igvn->remove_dead_node(phi);
}
}
}
}
!
// Check for prior store with a different base or offset; make Load
// independent. Skip through any number of them. Bail out if the stores
// are in an endless dead cycle and report no progress. This is a key
// transform for Reflection. However, if after skipping through the Stores
// we can't then fold up against a prior store do NOT do the transform as
--- 1292,1302 ----
igvn->remove_dead_node(phi);
}
}
}
}
! find_store:
// Check for prior store with a different base or offset; make Load
// independent. Skip through any number of them. Bail out if the stores
// are in an endless dead cycle and report no progress. This is a key
// transform for Reflection. However, if after skipping through the Stores
// we can't then fold up against a prior store do NOT do the transform as
*** 1833,1843 ****
case T_FLOAT: return new (C, 4) StoreFNode(ctl, mem, adr, adr_type, val);
case T_DOUBLE: return new (C, 4) StoreDNode(ctl, mem, adr, adr_type, val);
case T_ADDRESS:
case T_OBJECT:
#ifdef _LP64
! if (adr->bottom_type()->is_narrow() ||
(UseCompressedOops && val->bottom_type()->isa_klassptr() &&
adr->bottom_type()->isa_rawptr())) {
const TypePtr* type = val->bottom_type()->is_ptr();
Node* cp = EncodePNode::encode(&gvn, val);
return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, cp);
--- 1844,1854 ----
case T_FLOAT: return new (C, 4) StoreFNode(ctl, mem, adr, adr_type, val);
case T_DOUBLE: return new (C, 4) StoreDNode(ctl, mem, adr, adr_type, val);
case T_ADDRESS:
case T_OBJECT:
#ifdef _LP64
! if (adr->bottom_type()->is_ptr_to_narrowoop() ||
(UseCompressedOops && val->bottom_type()->isa_klassptr() &&
adr->bottom_type()->isa_rawptr())) {
const TypePtr* type = val->bottom_type()->is_ptr();
Node* cp = EncodePNode::encode(&gvn, val);
return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, cp);
src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File