comparison src/share/vm/opto/memnode.cpp @ 74:2a9af0b9cb1c

6674600: (Escape Analysis) Optimize memory graph for instance's fields Summary: EA gives opportunite to do more aggressive memory optimizations. Reviewed-by: never, jrose
author kvn
date Thu, 20 Mar 2008 15:11:44 -0700
parents daf38130e60d
children de93acbb64fc
comparison
equal deleted inserted replaced
73:a8880a78d355 74:2a9af0b9cb1c
27 // Optimization - Graph Style 27 // Optimization - Graph Style
28 28
29 #include "incls/_precompiled.incl" 29 #include "incls/_precompiled.incl"
30 #include "incls/_memnode.cpp.incl" 30 #include "incls/_memnode.cpp.incl"
31 31
32 static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const TypePtr *tp, const TypePtr *adr_check, outputStream *st);
33
32 //============================================================================= 34 //=============================================================================
33 uint MemNode::size_of() const { return sizeof(*this); } 35 uint MemNode::size_of() const { return sizeof(*this); }
34 36
35 const TypePtr *MemNode::adr_type() const { 37 const TypePtr *MemNode::adr_type() const {
36 Node* adr = in(Address); 38 Node* adr = in(Address);
84 } 86 }
85 87
86 extern void print_alias_types(); 88 extern void print_alias_types();
87 89
88 #endif 90 #endif
91
92 Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) {
93 const TypeOopPtr *tinst = t_adr->isa_oopptr();
94 if (tinst == NULL || !tinst->is_instance_field())
95 return mchain; // don't try to optimize non-instance types
96 uint instance_id = tinst->instance_id();
97 Node *prev = NULL;
98 Node *result = mchain;
99 while (prev != result) {
100 prev = result;
101 // skip over a call which does not affect this memory slice
102 if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
103 Node *proj_in = result->in(0);
104 if (proj_in->is_Call()) {
105 CallNode *call = proj_in->as_Call();
106 if (!call->may_modify(t_adr, phase)) {
107 result = call->in(TypeFunc::Memory);
108 }
109 } else if (proj_in->is_Initialize()) {
110 AllocateNode* alloc = proj_in->as_Initialize()->allocation();
111 // Stop if this is the initialization for the object instance which
112 // which contains this memory slice, otherwise skip over it.
113 if (alloc != NULL && alloc->_idx != instance_id) {
114 result = proj_in->in(TypeFunc::Memory);
115 }
116 } else if (proj_in->is_MemBar()) {
117 result = proj_in->in(TypeFunc::Memory);
118 }
119 } else if (result->is_MergeMem()) {
120 result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty);
121 }
122 }
123 return result;
124 }
125
126 Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGVN *phase) {
127 const TypeOopPtr *t_oop = t_adr->isa_oopptr();
128 bool is_instance = (t_oop != NULL) && t_oop->is_instance_field();
129 PhaseIterGVN *igvn = phase->is_IterGVN();
130 Node *result = mchain;
131 result = optimize_simple_memory_chain(result, t_adr, phase);
132 if (is_instance && igvn != NULL && result->is_Phi()) {
133 PhiNode *mphi = result->as_Phi();
134 assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
135 const TypePtr *t = mphi->adr_type();
136 if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM) {
137 // clone the Phi with our address type
138 result = mphi->split_out_instance(t_adr, igvn);
139 } else {
140 assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain");
141 }
142 }
143 return result;
144 }
89 145
90 static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const TypePtr *tp, const TypePtr *adr_check, outputStream *st) { 146 static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const TypePtr *tp, const TypePtr *adr_check, outputStream *st) {
91 uint alias_idx = phase->C->get_alias_index(tp); 147 uint alias_idx = phase->C->get_alias_index(tp);
92 Node *mem = mmem; 148 Node *mem = mmem;
93 #ifdef ASSERT 149 #ifdef ASSERT
264 AllocateNode* alloc = AllocateNode::Ideal_allocation(base, phase); 320 AllocateNode* alloc = AllocateNode::Ideal_allocation(base, phase);
265 321
266 if (offset == Type::OffsetBot) 322 if (offset == Type::OffsetBot)
267 return NULL; // cannot unalias unless there are precise offsets 323 return NULL; // cannot unalias unless there are precise offsets
268 324
325 const TypeOopPtr *addr_t = adr->bottom_type()->isa_oopptr();
326
269 intptr_t size_in_bytes = memory_size(); 327 intptr_t size_in_bytes = memory_size();
270 328
271 Node* mem = in(MemNode::Memory); // start searching here... 329 Node* mem = in(MemNode::Memory); // start searching here...
272 330
273 int cnt = 50; // Cycle limiter 331 int cnt = 50; // Cycle limiter
343 if (known_identical) { 401 if (known_identical) {
344 // From caller, can_see_stored_value will consult find_captured_store. 402 // From caller, can_see_stored_value will consult find_captured_store.
345 return mem; // let caller handle steps (c), (d) 403 return mem; // let caller handle steps (c), (d)
346 } 404 }
347 405
406 } else if (addr_t != NULL && addr_t->is_instance_field()) {
407 // Can't use optimize_simple_memory_chain() since it needs PhaseGVN.
408 if (mem->is_Proj() && mem->in(0)->is_Call()) {
409 CallNode *call = mem->in(0)->as_Call();
410 if (!call->may_modify(addr_t, phase)) {
411 mem = call->in(TypeFunc::Memory);
412 continue; // (a) advance through independent call memory
413 }
414 } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) {
415 mem = mem->in(0)->in(TypeFunc::Memory);
416 continue; // (a) advance through independent MemBar memory
417 } else if (mem->is_MergeMem()) {
418 int alias_idx = phase->C->get_alias_index(adr_type());
419 mem = mem->as_MergeMem()->memory_at(alias_idx);
420 continue; // (a) advance through independent MergeMem memory
421 }
348 } 422 }
349 423
350 // Unless there is an explicit 'continue', we must bail out here, 424 // Unless there is an explicit 'continue', we must bail out here,
351 // because 'mem' is an inscrutable memory state (e.g., a call). 425 // because 'mem' is an inscrutable memory state (e.g., a call).
352 break; 426 break;
1005 if (base != NULL) { 1079 if (base != NULL) {
1006 Compile::AliasType* atp = phase->C->alias_type(adr_type()); 1080 Compile::AliasType* atp = phase->C->alias_type(adr_type());
1007 if (is_autobox_object(atp)) { 1081 if (is_autobox_object(atp)) {
1008 Node* result = eliminate_autobox(phase); 1082 Node* result = eliminate_autobox(phase);
1009 if (result != NULL) return result; 1083 if (result != NULL) return result;
1084 }
1085 }
1086 }
1087
1088 Node* mem = in(MemNode::Memory);
1089 const TypePtr *addr_t = phase->type(address)->isa_ptr();
1090
1091 if (addr_t != NULL) {
1092 // try to optimize our memory input
1093 Node* opt_mem = MemNode::optimize_memory_chain(mem, addr_t, phase);
1094 if (opt_mem != mem) {
1095 set_req(MemNode::Memory, opt_mem);
1096 return this;
1097 }
1098 const TypeOopPtr *t_oop = addr_t->isa_oopptr();
1099 if (can_reshape && opt_mem->is_Phi() &&
1100 (t_oop != NULL) && t_oop->is_instance_field()) {
1101 assert(t_oop->offset() != Type::OffsetBot && t_oop->offset() != Type::OffsetTop, "");
1102 Node *region = opt_mem->in(0);
1103 uint cnt = opt_mem->req();
1104 for( uint i = 1; i < cnt; i++ ) {
1105 Node *in = opt_mem->in(i);
1106 if( in == NULL ) {
1107 region = NULL; // Wait stable graph
1108 break;
1109 }
1110 }
1111 if (region != NULL) {
1112 // Check for loop invariant.
1113 if (cnt == 3) {
1114 for( uint i = 1; i < cnt; i++ ) {
1115 Node *in = opt_mem->in(i);
1116 Node* m = MemNode::optimize_memory_chain(in, addr_t, phase);
1117 if (m == opt_mem) {
1118 set_req(MemNode::Memory, opt_mem->in(cnt - i)); // Skip this phi.
1119 return this;
1120 }
1121 }
1122 }
1123 // Split through Phi (see original code in loopopts.cpp).
1124 assert(phase->C->have_alias_type(addr_t), "instance should have alias type");
1125 const Type* this_type = this->bottom_type();
1126 int this_index = phase->C->get_alias_index(addr_t);
1127 int this_offset = addr_t->offset();
1128 int this_iid = addr_t->is_oopptr()->instance_id();
1129 int wins = 0;
1130 PhaseIterGVN *igvn = phase->is_IterGVN();
1131 Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
1132 for( uint i = 1; i < region->req(); i++ ) {
1133 Node *x;
1134 Node* the_clone = NULL;
1135 if( region->in(i) == phase->C->top() ) {
1136 x = phase->C->top(); // Dead path? Use a dead data op
1137 } else {
1138 x = this->clone(); // Else clone up the data op
1139 the_clone = x; // Remember for possible deletion.
1140 // Alter data node to use pre-phi inputs
1141 if( this->in(0) == region ) {
1142 x->set_req( 0, region->in(i) );
1143 } else {
1144 x->set_req( 0, NULL );
1145 }
1146 for( uint j = 1; j < this->req(); j++ ) {
1147 Node *in = this->in(j);
1148 if( in->is_Phi() && in->in(0) == region )
1149 x->set_req( j, in->in(i) ); // Use pre-Phi input for the clone
1150 }
1151 }
1152 // Check for a 'win' on some paths
1153 const Type *t = x->Value(igvn);
1154
1155 bool singleton = t->singleton();
1156
1157 // See comments in PhaseIdealLoop::split_thru_phi().
1158 if( singleton && t == Type::TOP ) {
1159 singleton &= region->is_Loop() && (i != LoopNode::EntryControl);
1160 }
1161
1162 if( singleton ) {
1163 wins++;
1164 x = igvn->makecon(t);
1165 } else {
1166 // We now call Identity to try to simplify the cloned node.
1167 // Note that some Identity methods call phase->type(this).
1168 // Make sure that the type array is big enough for
1169 // our new node, even though we may throw the node away.
1170 // (This tweaking with igvn only works because x is a new node.)
1171 igvn->set_type(x, t);
1172 Node *y = x->Identity(igvn);
1173 if( y != x ) {
1174 wins++;
1175 x = y;
1176 } else {
1177 y = igvn->hash_find(x);
1178 if( y ) {
1179 wins++;
1180 x = y;
1181 } else {
1182 // Else x is a new node we are keeping
1183 // We do not need register_new_node_with_optimizer
1184 // because set_type has already been called.
1185 igvn->_worklist.push(x);
1186 }
1187 }
1188 }
1189 if (x != the_clone && the_clone != NULL)
1190 igvn->remove_dead_node(the_clone);
1191 phi->set_req(i, x);
1192 }
1193 if( wins > 0 ) {
1194 // Record Phi
1195 igvn->register_new_node_with_optimizer(phi);
1196 return phi;
1197 } else {
1198 igvn->remove_dead_node(phi);
1199 }
1010 } 1200 }
1011 } 1201 }
1012 } 1202 }
1013 1203
1014 // Check for prior store with a different base or offset; make Load 1204 // Check for prior store with a different base or offset; make Load