void do_DFS (struct node *tree) // Perform a depth-first traversal of the given suffix tree // and store the string depths of the nodes in the order visited. { struct node *curr; if (tree) { curr = tree -> leftchild; while (curr) { do_DFS (curr); curr = curr -> rightsib; } if (tree -> sfxnum == -1) { ++numints; } else { ++numleaves; } } }
// Compute the dominator tree of the CFG. The CFG must already have been // constructed. This is the Lengauer & Tarjan O(E-alpha(E,V)) algorithm. void PhaseCFG::build_dominator_tree() { // Pre-grow the blocks array, prior to the ResourceMark kicking in _blocks.map(number_of_blocks(), 0); ResourceMark rm; // Setup mappings from my Graph to Tarjan's stuff and back // Note: Tarjan uses 1-based arrays Tarjan* tarjan = NEW_RESOURCE_ARRAY(Tarjan, number_of_blocks() + 1); // Tarjan's algorithm, almost verbatim: // Step 1: uint dfsnum = do_DFS(tarjan, number_of_blocks()); if (dfsnum - 1 != number_of_blocks()) { // Check for unreachable loops! // If the returned dfsnum does not match the number of blocks, then we // must have some unreachable loops. These can be made at any time by // IterGVN. They are cleaned up by CCP or the loop opts, but the last // IterGVN can always make more that are not cleaned up. Highly unlikely // except in ZKM.jar, where endless irreducible loops cause the loop opts // to not get run. // // Having found unreachable loops, we have made a bad RPO _block layout. // We can re-run the above DFS pass with the correct number of blocks, // and hack the Tarjan algorithm below to be robust in the presence of // such dead loops (as was done for the NTarjan code farther below). // Since this situation is so unlikely, instead I've decided to bail out. // CNC 7/24/2001 C->record_method_not_compilable("unreachable loop"); return; } _blocks._cnt = number_of_blocks(); // Tarjan is using 1-based arrays, so these are some initialize flags tarjan[0]._size = tarjan[0]._semi = 0; tarjan[0]._label = &tarjan[0]; for (uint i = number_of_blocks(); i >= 2; i--) { // For all vertices in DFS order Tarjan *w = &tarjan[i]; // Get vertex from DFS // Step 2: Node *whead = w->_block->head(); for (uint j = 1; j < whead->req(); j++) { Block* b = get_block_for_node(whead->in(j)); Tarjan *vx = &tarjan[b->_pre_order]; Tarjan *u = vx->EVAL(); if( u->_semi < w->_semi ) w->_semi = u->_semi; } // w is added to a bucket here, and only here. // Thus w is in at most one bucket and the sum of all bucket sizes is O(n). // Thus bucket can be a linked list. // Thus we do not need a small integer name for each Block. w->_bucket = tarjan[w->_semi]._bucket; tarjan[w->_semi]._bucket = w; w->_parent->LINK( w, &tarjan[0] ); // Step 3: for( Tarjan *vx = w->_parent->_bucket; vx; vx = vx->_bucket ) { Tarjan *u = vx->EVAL(); vx->_dom = (u->_semi < vx->_semi) ? u : w->_parent; } } // Step 4: for (uint i = 2; i <= number_of_blocks(); i++) { Tarjan *w = &tarjan[i]; if( w->_dom != &tarjan[w->_semi] ) w->_dom = w->_dom->_dom; w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later } // No immediate dominator for the root Tarjan *w = &tarjan[get_root_block()->_pre_order]; w->_dom = NULL; w->_dom_next = w->_dom_child = NULL; // Initialize for building tree later // Convert the dominator tree array into my kind of graph for(uint i = 1; i <= number_of_blocks(); i++){ // For all Tarjan vertices Tarjan *t = &tarjan[i]; // Handy access Tarjan *tdom = t->_dom; // Handy access to immediate dominator if( tdom ) { // Root has no immediate dominator t->_block->_idom = tdom->_block; // Set immediate dominator t->_dom_next = tdom->_dom_child; // Make me a sibling of parent's child tdom->_dom_child = t; // Make me a child of my parent } else t->_block->_idom = NULL; // Root } w->setdepth(number_of_blocks() + 1); // Set depth in dominator tree }