Mercurial > hg > truffle
comparison src/share/vm/opto/macro.cpp @ 356:1ee8caae33af
Merge
author | tonyp |
---|---|
date | Thu, 21 Aug 2008 23:36:31 -0400 |
parents | fab5f738c515 b0fe4deeb9fb |
children | f8199438385b |
comparison
equal
deleted
inserted
replaced
355:0edda524b58c | 356:1ee8caae33af |
---|---|
1 /* | 1 /* |
2 * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. | 2 * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
192 _igvn.replace_node(st, st->in(MemNode::Memory)); | 192 _igvn.replace_node(st, st->in(MemNode::Memory)); |
193 } | 193 } |
194 } | 194 } |
195 | 195 |
196 // Search for a memory operation for the specified memory slice. | 196 // Search for a memory operation for the specified memory slice. |
197 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc) { | 197 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) { |
198 Node *orig_mem = mem; | 198 Node *orig_mem = mem; |
199 Node *alloc_mem = alloc->in(TypeFunc::Memory); | 199 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
200 const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr(); | |
200 while (true) { | 201 while (true) { |
201 if (mem == alloc_mem || mem == start_mem ) { | 202 if (mem == alloc_mem || mem == start_mem ) { |
202 return mem; // hit one of our sentinals | 203 return mem; // hit one of our sentinals |
203 } else if (mem->is_MergeMem()) { | 204 } else if (mem->is_MergeMem()) { |
204 mem = mem->as_MergeMem()->memory_at(alias_idx); | 205 mem = mem->as_MergeMem()->memory_at(alias_idx); |
206 Node *in = mem->in(0); | 207 Node *in = mem->in(0); |
207 // we can safely skip over safepoints, calls, locks and membars because we | 208 // we can safely skip over safepoints, calls, locks and membars because we |
208 // already know that the object is safe to eliminate. | 209 // already know that the object is safe to eliminate. |
209 if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { | 210 if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { |
210 return in; | 211 return in; |
211 } else if (in->is_Call() || in->is_MemBar()) { | 212 } else if (in->is_Call()) { |
213 CallNode *call = in->as_Call(); | |
214 if (!call->may_modify(tinst, phase)) { | |
215 mem = call->in(TypeFunc::Memory); | |
216 } | |
217 mem = in->in(TypeFunc::Memory); | |
218 } else if (in->is_MemBar()) { | |
212 mem = in->in(TypeFunc::Memory); | 219 mem = in->in(TypeFunc::Memory); |
213 } else { | 220 } else { |
214 assert(false, "unexpected projection"); | 221 assert(false, "unexpected projection"); |
215 } | 222 } |
216 } else if (mem->is_Store()) { | 223 } else if (mem->is_Store()) { |
229 } | 236 } |
230 mem = mem->in(MemNode::Memory); | 237 mem = mem->in(MemNode::Memory); |
231 } else { | 238 } else { |
232 return mem; | 239 return mem; |
233 } | 240 } |
234 if (mem == orig_mem) | 241 assert(mem != orig_mem, "dead memory loop"); |
235 return mem; | |
236 } | 242 } |
237 } | 243 } |
238 | 244 |
239 // | 245 // |
240 // Given a Memory Phi, compute a value Phi containing the values from stores | 246 // Given a Memory Phi, compute a value Phi containing the values from stores |
241 // on the input paths. | 247 // on the input paths. |
242 // Note: this function is recursive, its depth is limied by the "level" argument | 248 // Note: this function is recursive, its depth is limied by the "level" argument |
243 // Returns the computed Phi, or NULL if it cannot compute it. | 249 // Returns the computed Phi, or NULL if it cannot compute it. |
244 Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, int level) { | 250 Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) { |
245 | 251 assert(mem->is_Phi(), "sanity"); |
246 if (level <= 0) { | |
247 return NULL; | |
248 } | |
249 int alias_idx = C->get_alias_index(adr_t); | 252 int alias_idx = C->get_alias_index(adr_t); |
250 int offset = adr_t->offset(); | 253 int offset = adr_t->offset(); |
251 int instance_id = adr_t->instance_id(); | 254 int instance_id = adr_t->instance_id(); |
252 | 255 |
256 // Check if an appropriate value phi already exists. | |
257 Node* region = mem->in(0); | |
258 for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { | |
259 Node* phi = region->fast_out(k); | |
260 if (phi->is_Phi() && phi != mem && | |
261 phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { | |
262 return phi; | |
263 } | |
264 } | |
265 // Check if an appropriate new value phi already exists. | |
266 Node* new_phi = NULL; | |
267 uint size = value_phis->size(); | |
268 for (uint i=0; i < size; i++) { | |
269 if ( mem->_idx == value_phis->index_at(i) ) { | |
270 return value_phis->node_at(i); | |
271 } | |
272 } | |
273 | |
274 if (level <= 0) { | |
275 return NULL; // Give up: phi tree too deep | |
276 } | |
253 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); | 277 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
254 Node *alloc_mem = alloc->in(TypeFunc::Memory); | 278 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
255 | 279 |
256 uint length = mem->req(); | 280 uint length = mem->req(); |
257 GrowableArray <Node *> values(length, length, NULL); | 281 GrowableArray <Node *> values(length, length, NULL); |
282 | |
283 // create a new Phi for the value | |
284 PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); | |
285 transform_later(phi); | |
286 value_phis->push(phi, mem->_idx); | |
258 | 287 |
259 for (uint j = 1; j < length; j++) { | 288 for (uint j = 1; j < length; j++) { |
260 Node *in = mem->in(j); | 289 Node *in = mem->in(j); |
261 if (in == NULL || in->is_top()) { | 290 if (in == NULL || in->is_top()) { |
262 values.at_put(j, in); | 291 values.at_put(j, in); |
263 } else { | 292 } else { |
264 Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc); | 293 Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc, &_igvn); |
265 if (val == start_mem || val == alloc_mem) { | 294 if (val == start_mem || val == alloc_mem) { |
266 // hit a sentinel, return appropriate 0 value | 295 // hit a sentinel, return appropriate 0 value |
267 values.at_put(j, _igvn.zerocon(ft)); | 296 values.at_put(j, _igvn.zerocon(ft)); |
268 continue; | 297 continue; |
269 } | 298 } |
278 } else if (val->is_Store()) { | 307 } else if (val->is_Store()) { |
279 values.at_put(j, val->in(MemNode::ValueIn)); | 308 values.at_put(j, val->in(MemNode::ValueIn)); |
280 } else if(val->is_Proj() && val->in(0) == alloc) { | 309 } else if(val->is_Proj() && val->in(0) == alloc) { |
281 values.at_put(j, _igvn.zerocon(ft)); | 310 values.at_put(j, _igvn.zerocon(ft)); |
282 } else if (val->is_Phi()) { | 311 } else if (val->is_Phi()) { |
283 // Check if an appropriate node already exists. | 312 val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1); |
284 Node* region = val->in(0); | 313 if (val == NULL) { |
285 Node* old_phi = NULL; | 314 return NULL; |
286 for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { | 315 } |
287 Node* phi = region->fast_out(k); | 316 values.at_put(j, val); |
288 if (phi->is_Phi() && phi != val && | |
289 phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { | |
290 old_phi = phi; | |
291 break; | |
292 } | |
293 } | |
294 if (old_phi == NULL) { | |
295 val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, level-1); | |
296 if (val == NULL) { | |
297 return NULL; | |
298 } | |
299 values.at_put(j, val); | |
300 } else { | |
301 values.at_put(j, old_phi); | |
302 } | |
303 } else { | 317 } else { |
304 return NULL; // unknown node on this path | 318 assert(false, "unknown node on this path"); |
305 } | 319 return NULL; // unknown node on this path |
306 } | 320 } |
307 } | 321 } |
308 // create a new Phi for the value | 322 } |
309 PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); | 323 // Set Phi's inputs |
310 for (uint j = 1; j < length; j++) { | 324 for (uint j = 1; j < length; j++) { |
311 if (values.at(j) == mem) { | 325 if (values.at(j) == mem) { |
312 phi->init_req(j, phi); | 326 phi->init_req(j, phi); |
313 } else { | 327 } else { |
314 phi->init_req(j, values.at(j)); | 328 phi->init_req(j, values.at(j)); |
315 } | 329 } |
316 } | 330 } |
317 transform_later(phi); | |
318 return phi; | 331 return phi; |
319 } | 332 } |
320 | 333 |
321 // Search the last value stored into the object's field. | 334 // Search the last value stored into the object's field. |
322 Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) { | 335 Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) { |
327 int alias_idx = C->get_alias_index(adr_t); | 340 int alias_idx = C->get_alias_index(adr_t); |
328 int offset = adr_t->offset(); | 341 int offset = adr_t->offset(); |
329 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); | 342 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
330 Node *alloc_ctrl = alloc->in(TypeFunc::Control); | 343 Node *alloc_ctrl = alloc->in(TypeFunc::Control); |
331 Node *alloc_mem = alloc->in(TypeFunc::Memory); | 344 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
332 VectorSet visited(Thread::current()->resource_area()); | 345 Arena *a = Thread::current()->resource_area(); |
346 VectorSet visited(a); | |
333 | 347 |
334 | 348 |
335 bool done = sfpt_mem == alloc_mem; | 349 bool done = sfpt_mem == alloc_mem; |
336 Node *mem = sfpt_mem; | 350 Node *mem = sfpt_mem; |
337 while (!done) { | 351 while (!done) { |
338 if (visited.test_set(mem->_idx)) { | 352 if (visited.test_set(mem->_idx)) { |
339 return NULL; // found a loop, give up | 353 return NULL; // found a loop, give up |
340 } | 354 } |
341 mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc); | 355 mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc, &_igvn); |
342 if (mem == start_mem || mem == alloc_mem) { | 356 if (mem == start_mem || mem == alloc_mem) { |
343 done = true; // hit a sentinel, return appropriate 0 value | 357 done = true; // hit a sentinel, return appropriate 0 value |
344 } else if (mem->is_Initialize()) { | 358 } else if (mem->is_Initialize()) { |
345 mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); | 359 mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); |
346 if (mem == NULL) { | 360 if (mem == NULL) { |
360 } else if (mem->is_Phi()) { | 374 } else if (mem->is_Phi()) { |
361 // try to find a phi's unique input | 375 // try to find a phi's unique input |
362 Node *unique_input = NULL; | 376 Node *unique_input = NULL; |
363 Node *top = C->top(); | 377 Node *top = C->top(); |
364 for (uint i = 1; i < mem->req(); i++) { | 378 for (uint i = 1; i < mem->req(); i++) { |
365 Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc); | 379 Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc, &_igvn); |
366 if (n == NULL || n == top || n == mem) { | 380 if (n == NULL || n == top || n == mem) { |
367 continue; | 381 continue; |
368 } else if (unique_input == NULL) { | 382 } else if (unique_input == NULL) { |
369 unique_input = n; | 383 unique_input = n; |
370 } else if (unique_input != n) { | 384 } else if (unique_input != n) { |
387 return _igvn.zerocon(ft); | 401 return _igvn.zerocon(ft); |
388 } else if (mem->is_Store()) { | 402 } else if (mem->is_Store()) { |
389 return mem->in(MemNode::ValueIn); | 403 return mem->in(MemNode::ValueIn); |
390 } else if (mem->is_Phi()) { | 404 } else if (mem->is_Phi()) { |
391 // attempt to produce a Phi reflecting the values on the input paths of the Phi | 405 // attempt to produce a Phi reflecting the values on the input paths of the Phi |
392 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, 8); | 406 Node_Stack value_phis(a, 8); |
407 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit); | |
393 if (phi != NULL) { | 408 if (phi != NULL) { |
394 return phi; | 409 return phi; |
410 } else { | |
411 // Kill all new Phis | |
412 while(value_phis.is_nonempty()) { | |
413 Node* n = value_phis.node(); | |
414 _igvn.hash_delete(n); | |
415 _igvn.subsume_node(n, C->top()); | |
416 value_phis.pop(); | |
417 } | |
395 } | 418 } |
396 } | 419 } |
397 } | 420 } |
398 // Something go wrong. | 421 // Something go wrong. |
399 return NULL; | 422 return NULL; |
446 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); | 469 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
447 k < kmax && can_eliminate; k++) { | 470 k < kmax && can_eliminate; k++) { |
448 Node* n = use->fast_out(k); | 471 Node* n = use->fast_out(k); |
449 if (!n->is_Store() && n->Opcode() != Op_CastP2X) { | 472 if (!n->is_Store() && n->Opcode() != Op_CastP2X) { |
450 DEBUG_ONLY(disq_node = n;) | 473 DEBUG_ONLY(disq_node = n;) |
451 if (n->is_Load()) { | 474 if (n->is_Load() || n->is_LoadStore()) { |
452 NOT_PRODUCT(fail_eliminate = "Field load";) | 475 NOT_PRODUCT(fail_eliminate = "Field load";) |
453 } else { | 476 } else { |
454 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) | 477 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
455 } | 478 } |
456 can_eliminate = false; | 479 can_eliminate = false; |