comparison src/share/vm/opto/macro.cpp @ 4115:1bd45abaa507

6890673: Eliminate allocations immediately after EA Summary: Try to eliminate allocations and related locks immediately after escape analysis. Reviewed-by: never
author kvn
date Wed, 16 Nov 2011 09:13:57 -0800
parents a92cdbac8b9e
children 069ab3f976d3
comparison
equal deleted inserted replaced
4114:6729bbc1fcd6 4115:1bd45abaa507
79 if (old_in != NULL && old_in->is_SafePointScalarObject()) { 79 if (old_in != NULL && old_in->is_SafePointScalarObject()) {
80 SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject(); 80 SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
81 uint old_unique = C->unique(); 81 uint old_unique = C->unique();
82 Node* new_in = old_sosn->clone(jvms_adj, sosn_map); 82 Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
83 if (old_unique != C->unique()) { 83 if (old_unique != C->unique()) {
84 new_in->set_req(0, newcall->in(0)); // reset control edge 84 new_in->set_req(0, C->root()); // reset control edge
85 new_in = transform_later(new_in); // Register new node. 85 new_in = transform_later(new_in); // Register new node.
86 } 86 }
87 old_in = new_in; 87 old_in = new_in;
88 } 88 }
89 newcall->add_req(old_in); 89 newcall->add_req(old_in);
563 Node* res = alloc->result_cast(); 563 Node* res = alloc->result_cast();
564 const TypeOopPtr* res_type = NULL; 564 const TypeOopPtr* res_type = NULL;
565 if (res == NULL) { 565 if (res == NULL) {
566 // All users were eliminated. 566 // All users were eliminated.
567 } else if (!res->is_CheckCastPP()) { 567 } else if (!res->is_CheckCastPP()) {
568 alloc->_is_scalar_replaceable = false; // don't try again
569 NOT_PRODUCT(fail_eliminate = "Allocation does not have unique CheckCastPP";) 568 NOT_PRODUCT(fail_eliminate = "Allocation does not have unique CheckCastPP";)
570 can_eliminate = false; 569 can_eliminate = false;
571 } else { 570 } else {
572 res_type = _igvn.type(res)->isa_oopptr(); 571 res_type = _igvn.type(res)->isa_oopptr();
573 if (res_type == NULL) { 572 if (res_type == NULL) {
717 SafePointScalarObjectNode* sobj = new (C, 1) SafePointScalarObjectNode(res_type, 716 SafePointScalarObjectNode* sobj = new (C, 1) SafePointScalarObjectNode(res_type,
718 #ifdef ASSERT 717 #ifdef ASSERT
719 alloc, 718 alloc,
720 #endif 719 #endif
721 first_ind, nfields); 720 first_ind, nfields);
722 sobj->init_req(0, sfpt->in(TypeFunc::Control)); 721 sobj->init_req(0, C->root());
723 transform_later(sobj); 722 transform_later(sobj);
724 723
725 // Scan object's fields adding an input to the safepoint for each field. 724 // Scan object's fields adding an input to the safepoint for each field.
726 for (int j = 0; j < nfields; j++) { 725 for (int j = 0; j < nfields; j++) {
727 intptr_t offset; 726 intptr_t offset;
760 759
761 const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr(); 760 const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr();
762 761
763 Node *field_val = value_from_mem(mem, basic_elem_type, field_type, field_addr_type, alloc); 762 Node *field_val = value_from_mem(mem, basic_elem_type, field_type, field_addr_type, alloc);
764 if (field_val == NULL) { 763 if (field_val == NULL) {
765 // we weren't able to find a value for this field, 764 // We weren't able to find a value for this field,
766 // give up on eliminating this allocation 765 // give up on eliminating this allocation.
767 alloc->_is_scalar_replaceable = false; // don't try again 766
768 // remove any extra entries we added to the safepoint 767 // Remove any extra entries we added to the safepoint.
769 uint last = sfpt->req() - 1; 768 uint last = sfpt->req() - 1;
770 for (int k = 0; k < j; k++) { 769 for (int k = 0; k < j; k++) {
771 sfpt->del_req(last--); 770 sfpt->del_req(last--);
772 } 771 }
773 // rollback processed safepoints 772 // rollback processed safepoints
1802 } 1801 }
1803 1802
1804 #ifndef PRODUCT 1803 #ifndef PRODUCT
1805 if (PrintEliminateLocks) { 1804 if (PrintEliminateLocks) {
1806 if (alock->is_Lock()) { 1805 if (alock->is_Lock()) {
1807 tty->print_cr("++++ Eliminating: %d Lock", alock->_idx); 1806 tty->print_cr("++++ Eliminated: %d Lock", alock->_idx);
1808 } else { 1807 } else {
1809 tty->print_cr("++++ Eliminating: %d Unlock", alock->_idx); 1808 tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx);
1810 } 1809 }
1811 } 1810 }
1812 #endif 1811 #endif
1813 1812
1814 Node* mem = alock->in(TypeFunc::Memory); 1813 Node* mem = alock->in(TypeFunc::Memory);
2163 mem_phi->init_req(2, mem); 2162 mem_phi->init_req(2, mem);
2164 transform_later(mem_phi); 2163 transform_later(mem_phi);
2165 _igvn.replace_node(_memproj_fallthrough, mem_phi); 2164 _igvn.replace_node(_memproj_fallthrough, mem_phi);
2166 } 2165 }
2167 2166
2168 //------------------------------expand_macro_nodes---------------------- 2167 //---------------------------eliminate_macro_nodes----------------------
2169 // Returns true if a failure occurred. 2168 // Eliminate scalar replaced allocations and associated locks.
2170 bool PhaseMacroExpand::expand_macro_nodes() { 2169 void PhaseMacroExpand::eliminate_macro_nodes() {
2171 if (C->macro_count() == 0) 2170 if (C->macro_count() == 0)
2172 return false; 2171 return;
2172
2173 // First, attempt to eliminate locks 2173 // First, attempt to eliminate locks
2174 int cnt = C->macro_count(); 2174 int cnt = C->macro_count();
2175 for (int i=0; i < cnt; i++) { 2175 for (int i=0; i < cnt; i++) {
2176 Node *n = C->macro_node(i); 2176 Node *n = C->macro_node(i);
2177 if (n->is_AbstractLock()) { // Lock and Unlock nodes 2177 if (n->is_AbstractLock()) { // Lock and Unlock nodes
2187 Node * n = C->macro_node(i-1); 2187 Node * n = C->macro_node(i-1);
2188 bool success = false; 2188 bool success = false;
2189 debug_only(int old_macro_count = C->macro_count();); 2189 debug_only(int old_macro_count = C->macro_count(););
2190 if (n->is_AbstractLock()) { 2190 if (n->is_AbstractLock()) {
2191 success = eliminate_locking_node(n->as_AbstractLock()); 2191 success = eliminate_locking_node(n->as_AbstractLock());
2192 } else if (n->Opcode() == Op_LoopLimit) {
2193 // Remove it from macro list and put on IGVN worklist to optimize.
2194 C->remove_macro_node(n);
2195 _igvn._worklist.push(n);
2196 success = true;
2197 } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
2198 _igvn.replace_node(n, n->in(1));
2199 success = true;
2200 } 2192 }
2201 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); 2193 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
2202 progress = progress || success; 2194 progress = progress || success;
2203 } 2195 }
2204 } 2196 }
2218 case Node::Class_Lock: 2210 case Node::Class_Lock:
2219 case Node::Class_Unlock: 2211 case Node::Class_Unlock:
2220 assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); 2212 assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
2221 break; 2213 break;
2222 default: 2214 default:
2223 assert(false, "unknown node type in macro list"); 2215 assert(n->Opcode() == Op_LoopLimit ||
2216 n->Opcode() == Op_Opaque1 ||
2217 n->Opcode() == Op_Opaque2, "unknown node type in macro list");
2224 } 2218 }
2225 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); 2219 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
2226 progress = progress || success; 2220 progress = progress || success;
2227 } 2221 }
2228 } 2222 }
2223 }
2224
2225 //------------------------------expand_macro_nodes----------------------
2226 // Returns true if a failure occurred.
2227 bool PhaseMacroExpand::expand_macro_nodes() {
2228 // Last attempt to eliminate macro nodes.
2229 eliminate_macro_nodes();
2230
2229 // Make sure expansion will not cause node limit to be exceeded. 2231 // Make sure expansion will not cause node limit to be exceeded.
2230 // Worst case is a macro node gets expanded into about 50 nodes. 2232 // Worst case is a macro node gets expanded into about 50 nodes.
2231 // Allow 50% more for optimization. 2233 // Allow 50% more for optimization.
2232 if (C->check_node_count(C->macro_count() * 75, "out of nodes before macro expansion" ) ) 2234 if (C->check_node_count(C->macro_count() * 75, "out of nodes before macro expansion" ) )
2233 return true; 2235 return true;
2236
2237 // Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations.
2238 bool progress = true;
2239 while (progress) {
2240 progress = false;
2241 for (int i = C->macro_count(); i > 0; i--) {
2242 Node * n = C->macro_node(i-1);
2243 bool success = false;
2244 debug_only(int old_macro_count = C->macro_count(););
2245 if (n->Opcode() == Op_LoopLimit) {
2246 // Remove it from macro list and put on IGVN worklist to optimize.
2247 C->remove_macro_node(n);
2248 _igvn._worklist.push(n);
2249 success = true;
2250 } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
2251 _igvn.replace_node(n, n->in(1));
2252 success = true;
2253 }
2254 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
2255 progress = progress || success;
2256 }
2257 }
2234 2258
2235 // expand "macro" nodes 2259 // expand "macro" nodes
2236 // nodes are removed from the macro list as they are processed 2260 // nodes are removed from the macro list as they are processed
2237 while (C->macro_count() > 0) { 2261 while (C->macro_count() > 0) {
2238 int macro_count = C->macro_count(); 2262 int macro_count = C->macro_count();
2263 if (C->failing()) return true; 2287 if (C->failing()) return true;
2264 } 2288 }
2265 2289
2266 _igvn.set_delay_transform(false); 2290 _igvn.set_delay_transform(false);
2267 _igvn.optimize(); 2291 _igvn.optimize();
2292 if (C->failing()) return true;
2268 return false; 2293 return false;
2269 } 2294 }