/* Generic dominator tree walker
- Copyright (C) 2003-2019 Free Software Foundation, Inc.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
which is currently an abstraction over walking tree statements. Thus
the dominator walker is currently only useful for trees. */
-/* Reverse postorder index of each basic block. */
-static int *bb_postorder;
-
static int
-cmp_bb_postorder (const void *a, const void *b)
+cmp_bb_postorder (const void *a, const void *b, void *data)
{
basic_block bb1 = *(const basic_block *)(a);
basic_block bb2 = *(const basic_block *)(b);
+ int *bb_postorder = (int *)data;
/* Place higher completion number first (pop off lower number first). */
return bb_postorder[bb2->index] - bb_postorder[bb1->index];
}
i.e. by descending number in BB_POSTORDER array. */
static void
-sort_bbs_postorder (basic_block *bbs, int n)
+sort_bbs_postorder (basic_block *bbs, int n, int *bb_postorder)
{
if (__builtin_expect (n == 2, true))
{
bbs[0] = bb0, bbs[1] = bb1, bbs[2] = bb2;
}
else
- qsort (bbs, n, sizeof *bbs, cmp_bb_postorder);
+ gcc_sort_r (bbs, n, sizeof *bbs, cmp_bb_postorder, bb_postorder);
}
/* Set EDGE_EXECUTABLE on every edge within FN's CFG. */
enum reachability reachability,
int *bb_index_to_rpo)
: m_dom_direction (direction),
- m_skip_unreachable_blocks (reachability != ALL_BLOCKS),
- m_user_bb_to_rpo (true),
+ m_reachability (reachability),
+ m_user_bb_to_rpo (bb_index_to_rpo != NULL),
m_unreachable_dom (NULL),
m_bb_to_rpo (bb_index_to_rpo)
{
- /* Set up edge flags if need be. */
- switch (reachability)
- {
- default:
- gcc_unreachable ();
- case ALL_BLOCKS:
- /* No need to touch edge flags. */
- break;
-
- case REACHABLE_BLOCKS:
- set_all_edges_as_executable (cfun);
- break;
-
- case REACHABLE_BLOCKS_PRESERVING_FLAGS:
- /* Preserve the edge flags. */
- break;
- }
-}
-
-/* Constructor for a dom walker. */
-
-dom_walker::dom_walker (cdi_direction direction,
- enum reachability reachability)
- : m_dom_direction (direction),
- m_skip_unreachable_blocks (reachability != ALL_BLOCKS),
- m_user_bb_to_rpo (false),
- m_unreachable_dom (NULL),
- m_bb_to_rpo (NULL)
-{
- /* Compute the basic-block index to RPO mapping. */
- if (direction == CDI_DOMINATORS)
- {
- int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
- int postorder_num = pre_and_rev_post_order_compute (NULL, postorder,
- true);
- m_bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
- for (int i = 0; i < postorder_num; ++i)
- m_bb_to_rpo[postorder[i]] = i;
- free (postorder);
- }
-
- /* Set up edge flags if need be. */
- switch (reachability)
- {
- default:
- gcc_unreachable ();
- case ALL_BLOCKS:
- /* No need to touch edge flags. */
- break;
-
- case REACHABLE_BLOCKS:
- set_all_edges_as_executable (cfun);
- break;
-
- case REACHABLE_BLOCKS_PRESERVING_FLAGS:
- /* Preserve the edge flags. */
- break;
- }
}
/* Destructor. */
{
/* If we're not skipping unreachable blocks, then assume everything
is reachable. */
- if (!m_skip_unreachable_blocks)
+ if (m_reachability == ALL_BLOCKS)
return true;
/* If any of the predecessor edges that do not come from blocks dominated
void
dom_walker::walk (basic_block bb)
{
+ /* Compute the basic-block index to RPO mapping lazily. */
+ if (!m_bb_to_rpo
+ && m_dom_direction == CDI_DOMINATORS)
+ {
+ int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
+ int postorder_num = pre_and_rev_post_order_compute (NULL, postorder,
+ true);
+ m_bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
+ for (int i = 0; i < postorder_num; ++i)
+ m_bb_to_rpo[postorder[i]] = i;
+ free (postorder);
+ }
+
+ /* Set up edge flags if need be. */
+ if (m_reachability == REACHABLE_BLOCKS)
+ set_all_edges_as_executable (cfun);
+
basic_block dest;
basic_block *worklist = XNEWVEC (basic_block,
n_basic_blocks_for_fn (cfun) * 2);
int sp = 0;
- bb_postorder = m_bb_to_rpo;
while (true)
{
if (sp - saved_sp > 1
&& m_dom_direction == CDI_DOMINATORS
&& m_bb_to_rpo)
- sort_bbs_postorder (&worklist[saved_sp], sp - saved_sp);
+ sort_bbs_postorder (&worklist[saved_sp], sp - saved_sp,
+ m_bb_to_rpo);
}
}
/* NULL is used to mark pop operations in the recursion stack. */
else
break;
}
- bb_postorder = NULL;
free (worklist);
}