From: John Wehle Date: Wed, 12 Dec 2001 05:01:32 +0000 (+0000) Subject: basic-block.h (flow_preorder_transversal_compute): Declare. X-Git-Tag: prereleases/libstdc++-3.0.95~236 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3dba42519e2aba3e1e48a75c29dd5d2554e1789f;p=thirdparty%2Fgcc.git basic-block.h (flow_preorder_transversal_compute): Declare. * basic-block.h (flow_preorder_transversal_compute): Declare. * cfganal.c (flow_preorder_transversal_compute): Implement. From-SVN: r47920 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb6ddb83337f..53cd3069d425 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Tue Dec 11 23:58:39 EST 2001 John Wehle (john@feith.com) + + * basic-block.h (flow_preorder_transversal_compute): Declare. + * cfganal.c (flow_preorder_transversal_compute): Implement. + Tue Dec 11 23:54:27 EST 2001 John Wehle (john@feith.com) * cfganal.c (flow_depth_first_order_compute): Always diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 253e1fd3e605..f31b46569822 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -321,6 +321,7 @@ extern void tidy_fallthru_edge PARAMS ((edge, basic_block, extern void tidy_fallthru_edges PARAMS ((void)); extern void flow_reverse_top_sort_order_compute PARAMS ((int *)); extern int flow_depth_first_order_compute PARAMS ((int *, int *)); +extern void flow_preorder_transversal_compute PARAMS ((int *)); extern void dump_edge_info PARAMS ((FILE *, edge, int)); extern void clear_edges PARAMS ((void)); extern void mark_critical_edges PARAMS ((void)); diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 3ec6f6e76006..0175a94892f7 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -923,6 +923,132 @@ flow_depth_first_order_compute (dfs_order, rc_order) return dfsnum; } +struct dfst_node { + unsigned nnodes; + struct dfst_node **node; + struct dfst_node *up; +}; + +/* Compute a preorder transversal ordering such that a sub-tree which + is the source of a cross edge appears before the sub-tree which is + the destination of the cross edge. This allows for easy detection + of all the entry blocks for a loop. + + The ordering is compute by: + + 1) Generating a depth first spanning tree. + + 2) Walking the resulting tree from right to left. */ + +void +flow_preorder_transversal_compute (pot_order) + int *pot_order; +{ + edge e; + edge *stack; + int i; + int max_successors; + int sp; + sbitmap visited; + struct dfst_node *node; + struct dfst_node *dfst; + + /* Allocate stack for back-tracking up CFG. */ + stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge)); + sp = 0; + + /* Allocate the tree. */ + dfst + = (struct dfst_node *) xcalloc (n_basic_blocks, sizeof (struct dfst_node)); + for (i = 0; i < n_basic_blocks; i++) + { + max_successors = 0; + for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next) + max_successors++; + dfst[i].node = max_successors ? (struct dfst_node **) + xcalloc (max_successors, + sizeof (struct dfst_node *)) + : NULL; + } + + /* Allocate bitmap to track nodes that have been visited. */ + visited = sbitmap_alloc (n_basic_blocks); + + /* None of the nodes in the CFG have been visited yet. */ + sbitmap_zero (visited); + + /* Push the first edge on to the stack. */ + stack[sp++] = ENTRY_BLOCK_PTR->succ; + + while (sp) + { + basic_block src; + basic_block dest; + + /* Look at the edge on the top of the stack. */ + e = stack[sp - 1]; + src = e->src; + dest = e->dest; + + /* Check if the edge destination has been visited yet. */ + if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index)) + { + /* Mark that we have visited the destination. */ + SET_BIT (visited, dest->index); + + /* Add the destination to the preorder tree. */ + if (src != ENTRY_BLOCK_PTR) + { + dfst[src->index].node[dfst[src->index].nnodes++] + = &dfst[dest->index]; + dfst[dest->index].up = &dfst[src->index]; + } + + if (dest->succ) + { + /* Since the DEST node has been visited for the first + time, check its successors. */ + stack[sp++] = dest->succ; + } + } + else + { + if (e->succ_next) + stack[sp - 1] = e->succ_next; + else + sp--; + } + } + + free (stack); + sbitmap_free (visited); + + /* Record the preorder transversal order by + walking the tree from right to left. */ + + i = 0; + node = &dfst[0]; + pot_order[i++] = 0; + + while (node) + { + if (node->nnodes) + { + node = node->node[--node->nnodes]; + pot_order[i++] = node - dfst; + } + else + node = node->up; + } + + /* Free the tree. */ + + for (i = 0; i < n_basic_blocks; i++) + if (dfst[i].node) + free (dfst[i].node); + free (dfst); +} + /* Compute the depth first search order on the _reverse_ graph and store in the array DFS_ORDER, marking the nodes visited in VISITED. Returns the number of nodes visited.