Mercurial > hg > graal-compiler
comparison src/share/vm/opto/domgraph.cpp @ 14412:e2722a66aba7
Merge
author | kvn |
---|---|
date | Thu, 05 Sep 2013 11:04:39 -0700 |
parents | adb9a7d94cb5 |
children | 650868c062a9 |
comparison
equal
deleted
inserted
replaced
14411:bdd155477289 | 14412:e2722a66aba7 |
---|---|
30 #include "opto/phaseX.hpp" | 30 #include "opto/phaseX.hpp" |
31 #include "opto/rootnode.hpp" | 31 #include "opto/rootnode.hpp" |
32 | 32 |
33 // Portions of code courtesy of Clifford Click | 33 // Portions of code courtesy of Clifford Click |
34 | 34 |
35 // Optimization - Graph Style | |
36 | |
37 //------------------------------Tarjan----------------------------------------- | |
38 // A data structure that holds all the information needed to find dominators. | 35 // A data structure that holds all the information needed to find dominators. |
39 struct Tarjan { | 36 struct Tarjan { |
40 Block *_block; // Basic block for this info | 37 Block *_block; // Basic block for this info |
41 | 38 |
42 uint _semi; // Semi-dominators | 39 uint _semi; // Semi-dominators |
58 | 55 |
59 void setdepth( uint size ); | 56 void setdepth( uint size ); |
60 | 57 |
61 }; | 58 }; |
62 | 59 |
63 //------------------------------Dominator-------------------------------------- | |
64 // Compute the dominator tree of the CFG. The CFG must already have been | 60 // Compute the dominator tree of the CFG. The CFG must already have been |
65 // constructed. This is the Lengauer & Tarjan O(E-alpha(E,V)) algorithm. | 61 // constructed. This is the Lengauer & Tarjan O(E-alpha(E,V)) algorithm. |
66 void PhaseCFG::Dominators( ) { | 62 void PhaseCFG::build_dominator_tree() { |
67 // Pre-grow the blocks array, prior to the ResourceMark kicking in | 63 // Pre-grow the blocks array, prior to the ResourceMark kicking in |
68 _blocks.map(_num_blocks,0); | 64 _blocks.map(number_of_blocks(), 0); |
69 | 65 |
70 ResourceMark rm; | 66 ResourceMark rm; |
71 // Setup mappings from my Graph to Tarjan's stuff and back | 67 // Setup mappings from my Graph to Tarjan's stuff and back |
72 // Note: Tarjan uses 1-based arrays | 68 // Note: Tarjan uses 1-based arrays |
73 Tarjan *tarjan = NEW_RESOURCE_ARRAY(Tarjan,_num_blocks+1); | 69 Tarjan* tarjan = NEW_RESOURCE_ARRAY(Tarjan, number_of_blocks() + 1); |
74 | 70 |
75 // Tarjan's algorithm, almost verbatim: | 71 // Tarjan's algorithm, almost verbatim: |
76 // Step 1: | 72 // Step 1: |
77 _rpo_ctr = _num_blocks; | 73 uint dfsnum = do_DFS(tarjan, number_of_blocks()); |
78 uint dfsnum = DFS( tarjan ); | 74 if (dfsnum - 1 != number_of_blocks()) { // Check for unreachable loops! |
79 if( dfsnum-1 != _num_blocks ) {// Check for unreachable loops! | |
80 // If the returned dfsnum does not match the number of blocks, then we | 75 // If the returned dfsnum does not match the number of blocks, then we |
81 // must have some unreachable loops. These can be made at any time by | 76 // must have some unreachable loops. These can be made at any time by |
82 // IterGVN. They are cleaned up by CCP or the loop opts, but the last | 77 // IterGVN. They are cleaned up by CCP or the loop opts, but the last |
83 // IterGVN can always make more that are not cleaned up. Highly unlikely | 78 // IterGVN can always make more that are not cleaned up. Highly unlikely |
84 // except in ZKM.jar, where endless irreducible loops cause the loop opts | 79 // except in ZKM.jar, where endless irreducible loops cause the loop opts |
91 // Since this situation is so unlikely, instead I've decided to bail out. | 86 // Since this situation is so unlikely, instead I've decided to bail out. |
92 // CNC 7/24/2001 | 87 // CNC 7/24/2001 |
93 C->record_method_not_compilable("unreachable loop"); | 88 C->record_method_not_compilable("unreachable loop"); |
94 return; | 89 return; |
95 } | 90 } |
96 _blocks._cnt = _num_blocks; | 91 _blocks._cnt = number_of_blocks(); |
97 | 92 |
98 // Tarjan is using 1-based arrays, so these are some initialize flags | 93 // Tarjan is using 1-based arrays, so these are some initialize flags |
99 tarjan[0]._size = tarjan[0]._semi = 0; | 94 tarjan[0]._size = tarjan[0]._semi = 0; |
100 tarjan[0]._label = &tarjan[0]; | 95 tarjan[0]._label = &tarjan[0]; |
101 | 96 |
102 uint i; | 97 for (uint i = number_of_blocks(); i >= 2; i--) { // For all vertices in DFS order |
103 for( i=_num_blocks; i>=2; i-- ) { // For all vertices in DFS order | |
104 Tarjan *w = &tarjan[i]; // Get vertex from DFS | 98 Tarjan *w = &tarjan[i]; // Get vertex from DFS |
105 | 99 |
106 // Step 2: | 100 // Step 2: |
107 Node *whead = w->_block->head(); | 101 Node *whead = w->_block->head(); |
108 for( uint j=1; j < whead->req(); j++ ) { | 102 for (uint j = 1; j < whead->req(); j++) { |
109 Block *b = _bbs[whead->in(j)->_idx]; | 103 Block* b = get_block_for_node(whead->in(j)); |
110 Tarjan *vx = &tarjan[b->_pre_order]; | 104 Tarjan *vx = &tarjan[b->_pre_order]; |
111 Tarjan *u = vx->EVAL(); | 105 Tarjan *u = vx->EVAL(); |
112 if( u->_semi < w->_semi ) | 106 if( u->_semi < w->_semi ) |
113 w->_semi = u->_semi; | 107 w->_semi = u->_semi; |
114 } | 108 } |
128 vx->_dom = (u->_semi < vx->_semi) ? u : w->_parent; | 122 vx->_dom = (u->_semi < vx->_semi) ? u : w->_parent; |
129 } | 123 } |
130 } | 124 } |
131 | 125 |
132 // Step 4: | 126 // Step 4: |
133 for( i=2; i <= _num_blocks; i++ ) { | 127 for (uint i = 2; i <= number_of_blocks(); i++) { |
134 Tarjan *w = &tarjan[i]; | 128 Tarjan *w = &tarjan[i]; |
135 if( w->_dom != &tarjan[w->_semi] ) | 129 if( w->_dom != &tarjan[w->_semi] ) |
136 w->_dom = w->_dom->_dom; | 130 w->_dom = w->_dom->_dom; |
137 w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later | 131 w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later |
138 } | 132 } |
139 // No immediate dominator for the root | 133 // No immediate dominator for the root |
140 Tarjan *w = &tarjan[_broot->_pre_order]; | 134 Tarjan *w = &tarjan[get_root_block()->_pre_order]; |
141 w->_dom = NULL; | 135 w->_dom = NULL; |
142 w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later | 136 w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later |
143 | 137 |
144 // Convert the dominator tree array into my kind of graph | 138 // Convert the dominator tree array into my kind of graph |
145 for( i=1; i<=_num_blocks;i++){// For all Tarjan vertices | 139 for(uint i = 1; i <= number_of_blocks(); i++){ // For all Tarjan vertices |
146 Tarjan *t = &tarjan[i]; // Handy access | 140 Tarjan *t = &tarjan[i]; // Handy access |
147 Tarjan *tdom = t->_dom; // Handy access to immediate dominator | 141 Tarjan *tdom = t->_dom; // Handy access to immediate dominator |
148 if( tdom ) { // Root has no immediate dominator | 142 if( tdom ) { // Root has no immediate dominator |
149 t->_block->_idom = tdom->_block; // Set immediate dominator | 143 t->_block->_idom = tdom->_block; // Set immediate dominator |
150 t->_dom_next = tdom->_dom_child; // Make me a sibling of parent's child | 144 t->_dom_next = tdom->_dom_child; // Make me a sibling of parent's child |
151 tdom->_dom_child = t; // Make me a child of my parent | 145 tdom->_dom_child = t; // Make me a child of my parent |
152 } else | 146 } else |
153 t->_block->_idom = NULL; // Root | 147 t->_block->_idom = NULL; // Root |
154 } | 148 } |
155 w->setdepth( _num_blocks+1 ); // Set depth in dominator tree | 149 w->setdepth(number_of_blocks() + 1); // Set depth in dominator tree |
156 | 150 |
157 } | 151 } |
158 | 152 |
159 //----------------------------Block_Stack-------------------------------------- | |
160 class Block_Stack { | 153 class Block_Stack { |
161 private: | 154 private: |
162 struct Block_Descr { | 155 struct Block_Descr { |
163 Block *block; // Block | 156 Block *block; // Block |
164 int index; // Index of block's successor pushed on stack | 157 int index; // Index of block's successor pushed on stack |
212 _stack_top->index = i; | 205 _stack_top->index = i; |
213 return _stack_top->block->_succs[ i ]; | 206 return _stack_top->block->_succs[ i ]; |
214 } | 207 } |
215 }; | 208 }; |
216 | 209 |
217 //-------------------------most_frequent_successor----------------------------- | |
218 // Find the index into the b->succs[] array of the most frequent successor. | 210 // Find the index into the b->succs[] array of the most frequent successor. |
219 uint Block_Stack::most_frequent_successor( Block *b ) { | 211 uint Block_Stack::most_frequent_successor( Block *b ) { |
220 uint freq_idx = 0; | 212 uint freq_idx = 0; |
221 int eidx = b->end_idx(); | 213 int eidx = b->end_idx(); |
222 Node *n = b->_nodes[eidx]; | 214 Node *n = b->_nodes[eidx]; |
256 ShouldNotReachHere(); | 248 ShouldNotReachHere(); |
257 } | 249 } |
258 return freq_idx; | 250 return freq_idx; |
259 } | 251 } |
260 | 252 |
261 //------------------------------DFS-------------------------------------------- | |
262 // Perform DFS search. Setup 'vertex' as DFS to vertex mapping. Setup | 253 // Perform DFS search. Setup 'vertex' as DFS to vertex mapping. Setup |
263 // 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent. | 254 // 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent. |
264 uint PhaseCFG::DFS( Tarjan *tarjan ) { | 255 uint PhaseCFG::do_DFS(Tarjan *tarjan, uint rpo_counter) { |
265 Block *b = _broot; | 256 Block* root_block = get_root_block(); |
266 uint pre_order = 1; | 257 uint pre_order = 1; |
267 // Allocate stack of size _num_blocks+1 to avoid frequent realloc | 258 // Allocate stack of size number_of_blocks() + 1 to avoid frequent realloc |
268 Block_Stack bstack(tarjan, _num_blocks+1); | 259 Block_Stack bstack(tarjan, number_of_blocks() + 1); |
269 | 260 |
270 // Push on stack the state for the first block | 261 // Push on stack the state for the first block |
271 bstack.push(pre_order, b); | 262 bstack.push(pre_order, root_block); |
272 ++pre_order; | 263 ++pre_order; |
273 | 264 |
274 while (bstack.is_nonempty()) { | 265 while (bstack.is_nonempty()) { |
275 if (!bstack.last_successor()) { | 266 if (!bstack.last_successor()) { |
276 // Walk over all successors in pre-order (DFS). | 267 // Walk over all successors in pre-order (DFS). |
277 Block *s = bstack.next_successor(); | 268 Block* next_block = bstack.next_successor(); |
278 if (s->_pre_order == 0) { // Check for no-pre-order, not-visited | 269 if (next_block->_pre_order == 0) { // Check for no-pre-order, not-visited |
279 // Push on stack the state of successor | 270 // Push on stack the state of successor |
280 bstack.push(pre_order, s); | 271 bstack.push(pre_order, next_block); |
281 ++pre_order; | 272 ++pre_order; |
282 } | 273 } |
283 } | 274 } |
284 else { | 275 else { |
285 // Build a reverse post-order in the CFG _blocks array | 276 // Build a reverse post-order in the CFG _blocks array |
286 Block *stack_top = bstack.pop(); | 277 Block *stack_top = bstack.pop(); |
287 stack_top->_rpo = --_rpo_ctr; | 278 stack_top->_rpo = --rpo_counter; |
288 _blocks.map(stack_top->_rpo, stack_top); | 279 _blocks.map(stack_top->_rpo, stack_top); |
289 } | 280 } |
290 } | 281 } |
291 return pre_order; | 282 return pre_order; |
292 } | 283 } |
293 | 284 |
294 //------------------------------COMPRESS--------------------------------------- | |
295 void Tarjan::COMPRESS() | 285 void Tarjan::COMPRESS() |
296 { | 286 { |
297 assert( _ancestor != 0, "" ); | 287 assert( _ancestor != 0, "" ); |
298 if( _ancestor->_ancestor != 0 ) { | 288 if( _ancestor->_ancestor != 0 ) { |
299 _ancestor->COMPRESS( ); | 289 _ancestor->COMPRESS( ); |
301 _label = _ancestor->_label; | 291 _label = _ancestor->_label; |
302 _ancestor = _ancestor->_ancestor; | 292 _ancestor = _ancestor->_ancestor; |
303 } | 293 } |
304 } | 294 } |
305 | 295 |
306 //------------------------------EVAL------------------------------------------- | |
307 Tarjan *Tarjan::EVAL() { | 296 Tarjan *Tarjan::EVAL() { |
308 if( !_ancestor ) return _label; | 297 if( !_ancestor ) return _label; |
309 COMPRESS(); | 298 COMPRESS(); |
310 return (_ancestor->_label->_semi >= _label->_semi) ? _label : _ancestor->_label; | 299 return (_ancestor->_label->_semi >= _label->_semi) ? _label : _ancestor->_label; |
311 } | 300 } |
312 | 301 |
313 //------------------------------LINK------------------------------------------- | |
314 void Tarjan::LINK( Tarjan *w, Tarjan *tarjan0 ) { | 302 void Tarjan::LINK( Tarjan *w, Tarjan *tarjan0 ) { |
315 Tarjan *s = w; | 303 Tarjan *s = w; |
316 while( w->_label->_semi < s->_child->_label->_semi ) { | 304 while( w->_label->_semi < s->_child->_label->_semi ) { |
317 if( s->_size + s->_child->_child->_size >= (s->_child->_size << 1) ) { | 305 if( s->_size + s->_child->_child->_size >= (s->_child->_size << 1) ) { |
318 s->_child->_ancestor = s; | 306 s->_child->_ancestor = s; |
331 s->_ancestor = this; | 319 s->_ancestor = this; |
332 s = s->_child; | 320 s = s->_child; |
333 } | 321 } |
334 } | 322 } |
335 | 323 |
336 //------------------------------setdepth--------------------------------------- | |
337 void Tarjan::setdepth( uint stack_size ) { | 324 void Tarjan::setdepth( uint stack_size ) { |
338 Tarjan **top = NEW_RESOURCE_ARRAY(Tarjan*, stack_size); | 325 Tarjan **top = NEW_RESOURCE_ARRAY(Tarjan*, stack_size); |
339 Tarjan **next = top; | 326 Tarjan **next = top; |
340 Tarjan **last; | 327 Tarjan **last; |
341 uint depth = 0; | 328 uint depth = 0; |
360 } while (t != NULL); | 347 } while (t != NULL); |
361 } while (next < last); | 348 } while (next < last); |
362 } while (last < top); | 349 } while (last < top); |
363 } | 350 } |
364 | 351 |
365 //*********************** DOMINATORS ON THE SEA OF NODES*********************** | 352 // Compute dominators on the Sea of Nodes form |
366 //------------------------------NTarjan---------------------------------------- | |
367 // A data structure that holds all the information needed to find dominators. | 353 // A data structure that holds all the information needed to find dominators. |
368 struct NTarjan { | 354 struct NTarjan { |
369 Node *_control; // Control node associated with this info | 355 Node *_control; // Control node associated with this info |
370 | 356 |
371 uint _semi; // Semi-dominators | 357 uint _semi; // Semi-dominators |
394 #ifndef PRODUCT | 380 #ifndef PRODUCT |
395 void dump(int offset) const; | 381 void dump(int offset) const; |
396 #endif | 382 #endif |
397 }; | 383 }; |
398 | 384 |
399 //------------------------------Dominator-------------------------------------- | |
400 // Compute the dominator tree of the sea of nodes. This version walks all CFG | 385 // Compute the dominator tree of the sea of nodes. This version walks all CFG |
401 // nodes (using the is_CFG() call) and places them in a dominator tree. Thus, | 386 // nodes (using the is_CFG() call) and places them in a dominator tree. Thus, |
402 // it needs a count of the CFG nodes for the mapping table. This is the | 387 // it needs a count of the CFG nodes for the mapping table. This is the |
403 // Lengauer & Tarjan O(E-alpha(E,V)) algorithm. | 388 // Lengauer & Tarjan O(E-alpha(E,V)) algorithm. |
404 void PhaseIdealLoop::Dominators() { | 389 void PhaseIdealLoop::Dominators() { |
515 w->dump(0); | 500 w->dump(0); |
516 #endif | 501 #endif |
517 } | 502 } |
518 } | 503 } |
519 | 504 |
520 //------------------------------DFS-------------------------------------------- | |
521 // Perform DFS search. Setup 'vertex' as DFS to vertex mapping. Setup | 505 // Perform DFS search. Setup 'vertex' as DFS to vertex mapping. Setup |
522 // 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent. | 506 // 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent. |
523 int NTarjan::DFS( NTarjan *ntarjan, VectorSet &visited, PhaseIdealLoop *pil, uint *dfsorder) { | 507 int NTarjan::DFS( NTarjan *ntarjan, VectorSet &visited, PhaseIdealLoop *pil, uint *dfsorder) { |
524 // Allocate stack of size C->unique()/8 to avoid frequent realloc | 508 // Allocate stack of size C->unique()/8 to avoid frequent realloc |
525 GrowableArray <Node *> dfstack(pil->C->unique() >> 3); | 509 GrowableArray <Node *> dfstack(pil->C->unique() >> 3); |
558 } | 542 } |
559 | 543 |
560 return dfsnum; | 544 return dfsnum; |
561 } | 545 } |
562 | 546 |
563 //------------------------------COMPRESS--------------------------------------- | |
564 void NTarjan::COMPRESS() | 547 void NTarjan::COMPRESS() |
565 { | 548 { |
566 assert( _ancestor != 0, "" ); | 549 assert( _ancestor != 0, "" ); |
567 if( _ancestor->_ancestor != 0 ) { | 550 if( _ancestor->_ancestor != 0 ) { |
568 _ancestor->COMPRESS( ); | 551 _ancestor->COMPRESS( ); |
570 _label = _ancestor->_label; | 553 _label = _ancestor->_label; |
571 _ancestor = _ancestor->_ancestor; | 554 _ancestor = _ancestor->_ancestor; |
572 } | 555 } |
573 } | 556 } |
574 | 557 |
575 //------------------------------EVAL------------------------------------------- | |
576 NTarjan *NTarjan::EVAL() { | 558 NTarjan *NTarjan::EVAL() { |
577 if( !_ancestor ) return _label; | 559 if( !_ancestor ) return _label; |
578 COMPRESS(); | 560 COMPRESS(); |
579 return (_ancestor->_label->_semi >= _label->_semi) ? _label : _ancestor->_label; | 561 return (_ancestor->_label->_semi >= _label->_semi) ? _label : _ancestor->_label; |
580 } | 562 } |
581 | 563 |
582 //------------------------------LINK------------------------------------------- | |
583 void NTarjan::LINK( NTarjan *w, NTarjan *ntarjan0 ) { | 564 void NTarjan::LINK( NTarjan *w, NTarjan *ntarjan0 ) { |
584 NTarjan *s = w; | 565 NTarjan *s = w; |
585 while( w->_label->_semi < s->_child->_label->_semi ) { | 566 while( w->_label->_semi < s->_child->_label->_semi ) { |
586 if( s->_size + s->_child->_child->_size >= (s->_child->_size << 1) ) { | 567 if( s->_size + s->_child->_child->_size >= (s->_child->_size << 1) ) { |
587 s->_child->_ancestor = s; | 568 s->_child->_ancestor = s; |
600 s->_ancestor = this; | 581 s->_ancestor = this; |
601 s = s->_child; | 582 s = s->_child; |
602 } | 583 } |
603 } | 584 } |
604 | 585 |
605 //------------------------------setdepth--------------------------------------- | |
606 void NTarjan::setdepth( uint stack_size, uint *dom_depth ) { | 586 void NTarjan::setdepth( uint stack_size, uint *dom_depth ) { |
607 NTarjan **top = NEW_RESOURCE_ARRAY(NTarjan*, stack_size); | 587 NTarjan **top = NEW_RESOURCE_ARRAY(NTarjan*, stack_size); |
608 NTarjan **next = top; | 588 NTarjan **next = top; |
609 NTarjan **last; | 589 NTarjan **last; |
610 uint depth = 0; | 590 uint depth = 0; |
629 } while (t != NULL); | 609 } while (t != NULL); |
630 } while (next < last); | 610 } while (next < last); |
631 } while (last < top); | 611 } while (last < top); |
632 } | 612 } |
633 | 613 |
634 //------------------------------dump------------------------------------------- | |
635 #ifndef PRODUCT | 614 #ifndef PRODUCT |
636 void NTarjan::dump(int offset) const { | 615 void NTarjan::dump(int offset) const { |
637 // Dump the data from this node | 616 // Dump the data from this node |
638 int i; | 617 int i; |
639 for(i = offset; i >0; i--) // Use indenting for tree structure | 618 for(i = offset; i >0; i--) // Use indenting for tree structure |