| /* Calculate (post)dominators in slightly super-linear time. |
| Copyright (C) 2000-2018 Free Software Foundation, Inc. |
| Contributed by Michael Matz (matz@ifh.de). |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
| License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| /* This file implements the well known algorithm from Lengauer and Tarjan |
| to compute the dominators in a control flow graph. A basic block D is said |
| to dominate another block X, when all paths from the entry node of the CFG |
| to X go also over D. The dominance relation is a transitive reflexive |
| relation and its minimal transitive reduction is a tree, called the |
| dominator tree. So for each block X besides the entry block exists a |
| block I(X), called the immediate dominator of X, which is the parent of X |
| in the dominator tree. |
| |
| The algorithm computes this dominator tree implicitly by computing for |
| each block its immediate dominator. We use tree balancing and path |
| compression, so it's the O(e*a(e,v)) variant, where a(e,v) is the very |
| slowly growing functional inverse of the Ackerman function. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "backend.h" |
| #include "timevar.h" |
| #include "diagnostic-core.h" |
| #include "cfganal.h" |
| #include "et-forest.h" |
| #include "graphds.h" |
| |
| /* We name our nodes with integers, beginning with 1. Zero is reserved for |
| 'undefined' or 'end of list'. The name of each node is given by the dfs |
| number of the corresponding basic block. Please note, that we include the |
| artificial ENTRY_BLOCK (or EXIT_BLOCK in the post-dom case) in our lists to |
| support multiple entry points. Its dfs number is of course 1. */ |
| |
| /* Type of Basic Block aka. TBB */ |
| typedef unsigned int TBB; |
| |
| namespace { |
| |
| /* This class holds various arrays reflecting the (sub)structure of the |
| flowgraph. Most of them are of type TBB and are also indexed by TBB. */ |
| |
| class dom_info |
| { |
| public: |
| dom_info (function *, cdi_direction); |
| dom_info (vec <basic_block>, cdi_direction); |
| ~dom_info (); |
| void calc_dfs_tree (); |
| void calc_idoms (); |
| |
| inline basic_block get_idom (basic_block); |
| private: |
| void calc_dfs_tree_nonrec (basic_block); |
| void compress (TBB); |
| void dom_init (void); |
| TBB eval (TBB); |
| void link_roots (TBB, TBB); |
| |
| /* The parent of a node in the DFS tree. */ |
| TBB *m_dfs_parent; |
| /* For a node x m_key[x] is roughly the node nearest to the root from which |
| exists a way to x only over nodes behind x. Such a node is also called |
| semidominator. */ |
| TBB *m_key; |
| /* The value in m_path_min[x] is the node y on the path from x to the root of |
| the tree x is in with the smallest m_key[y]. */ |
| TBB *m_path_min; |
| /* m_bucket[x] points to the first node of the set of nodes having x as |
| key. */ |
| TBB *m_bucket; |
| /* And m_next_bucket[x] points to the next node. */ |
| TBB *m_next_bucket; |
| /* After the algorithm is done, m_dom[x] contains the immediate dominator |
| of x. */ |
| TBB *m_dom; |
| |
| /* The following few fields implement the structures needed for disjoint |
| sets. */ |
| /* m_set_chain[x] is the next node on the path from x to the representative |
| of the set containing x. If m_set_chain[x]==0 then x is a root. */ |
| TBB *m_set_chain; |
| /* m_set_size[x] is the number of elements in the set named by x. */ |
| unsigned int *m_set_size; |
| /* m_set_child[x] is used for balancing the tree representing a set. It can |
| be understood as the next sibling of x. */ |
| TBB *m_set_child; |
| |
| /* If b is the number of a basic block (BB->index), m_dfs_order[b] is the |
| number of that node in DFS order counted from 1. This is an index |
| into most of the other arrays in this structure. */ |
| TBB *m_dfs_order; |
| /* Points to last element in m_dfs_order array. */ |
| TBB *m_dfs_last; |
| /* If x is the DFS-index of a node which corresponds with a basic block, |
| m_dfs_to_bb[x] is that basic block. Note, that in our structure there are |
| more nodes that basic blocks, so only |
| m_dfs_to_bb[m_dfs_order[bb->index]]==bb is true for every basic block bb, |
| but not the opposite. */ |
| basic_block *m_dfs_to_bb; |
| |
| /* This is the next free DFS number when creating the DFS tree. */ |
| unsigned int m_dfsnum; |
| /* The number of nodes in the DFS tree (==m_dfsnum-1). */ |
| unsigned int m_nodes; |
| |
| /* Blocks with bits set here have a fake edge to EXIT. These are used |
| to turn a DFS forest into a proper tree. */ |
| bitmap m_fake_exit_edge; |
| |
| /* Number of basic blocks in the function being compiled. */ |
| unsigned m_n_basic_blocks; |
| |
| /* True, if we are computing postdominators (rather than dominators). */ |
| bool m_reverse; |
| |
| /* Start block (the entry block for forward problem, exit block for backward |
| problem). */ |
| basic_block m_start_block; |
| /* Ending block. */ |
| basic_block m_end_block; |
| }; |
| |
| } // anonymous namespace |
| |
| void debug_dominance_info (cdi_direction); |
| void debug_dominance_tree (cdi_direction, basic_block); |
| |
| /* Allocate and zero-initialize NUM elements of type T (T must be a |
| POD-type). Note: after transition to C++11 or later, |
| `x = new_zero_array <T> (num);' can be replaced with |
| `x = new T[num] {};'. */ |
| |
| template<typename T> |
| inline T *new_zero_array (unsigned num) |
| { |
| T *result = new T[num]; |
| memset (result, 0, sizeof (T) * num); |
| return result; |
| } |
| |
| /* Helper function for constructors to initialize a part of class members. */ |
| |
| void |
| dom_info::dom_init (void) |
| { |
| unsigned num = m_n_basic_blocks; |
| |
| m_dfs_parent = new_zero_array <TBB> (num); |
| m_dom = new_zero_array <TBB> (num); |
| |
| m_path_min = new TBB[num]; |
| m_key = new TBB[num]; |
| m_set_size = new unsigned int[num]; |
| for (unsigned i = 0; i < num; i++) |
| { |
| m_path_min[i] = m_key[i] = i; |
| m_set_size[i] = 1; |
| } |
| |
| m_bucket = new_zero_array <TBB> (num); |
| m_next_bucket = new_zero_array <TBB> (num); |
| |
| m_set_chain = new_zero_array <TBB> (num); |
| m_set_child = new_zero_array <TBB> (num); |
| |
| m_dfs_to_bb = new_zero_array <basic_block> (num); |
| |
| m_dfsnum = 1; |
| m_nodes = 0; |
| } |
| |
| /* Allocate all needed memory in a pessimistic fashion (so we round up). */ |
| |
| dom_info::dom_info (function *fn, cdi_direction dir) |
| { |
| m_n_basic_blocks = n_basic_blocks_for_fn (fn); |
| |
| dom_init (); |
| |
| unsigned last_bb_index = last_basic_block_for_fn (fn); |
| m_dfs_order = new_zero_array <TBB> (last_bb_index + 1); |
| m_dfs_last = &m_dfs_order[last_bb_index]; |
| |
| switch (dir) |
| { |
| case CDI_DOMINATORS: |
| m_reverse = false; |
| m_fake_exit_edge = NULL; |
| m_start_block = ENTRY_BLOCK_PTR_FOR_FN (fn); |
| m_end_block = EXIT_BLOCK_PTR_FOR_FN (fn); |
| break; |
| case CDI_POST_DOMINATORS: |
| m_reverse = true; |
| m_fake_exit_edge = BITMAP_ALLOC (NULL); |
| m_start_block = EXIT_BLOCK_PTR_FOR_FN (fn); |
| m_end_block = ENTRY_BLOCK_PTR_FOR_FN (fn); |
| break; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Constructor for reducible region REGION. */ |
| |
| dom_info::dom_info (vec<basic_block> region, cdi_direction dir) |
| { |
| m_n_basic_blocks = region.length (); |
| unsigned nm1 = m_n_basic_blocks - 1; |
| |
| dom_init (); |
| |
| /* Determine max basic block index in region. */ |
| int max_index = region[0]->index; |
| for (unsigned i = 1; i <= nm1; i++) |
| if (region[i]->index > max_index) |
| max_index = region[i]->index; |
| max_index += 1; /* set index on the first bb out of region. */ |
| |
| m_dfs_order = new_zero_array <TBB> (max_index + 1); |
| m_dfs_last = &m_dfs_order[max_index]; |
| |
| m_fake_exit_edge = NULL; /* Assume that region is reducible. */ |
| |
| switch (dir) |
| { |
| case CDI_DOMINATORS: |
| m_reverse = false; |
| m_start_block = region[0]; |
| m_end_block = region[nm1]; |
| break; |
| case CDI_POST_DOMINATORS: |
| m_reverse = true; |
| m_start_block = region[nm1]; |
| m_end_block = region[0]; |
| break; |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| inline basic_block |
| dom_info::get_idom (basic_block bb) |
| { |
| TBB d = m_dom[m_dfs_order[bb->index]]; |
| return m_dfs_to_bb[d]; |
| } |
| |
| /* Map dominance calculation type to array index used for various |
| dominance information arrays. This version is simple -- it will need |
| to be modified, obviously, if additional values are added to |
| cdi_direction. */ |
| |
| static inline unsigned int |
| dom_convert_dir_to_idx (cdi_direction dir) |
| { |
| gcc_checking_assert (dir == CDI_DOMINATORS || dir == CDI_POST_DOMINATORS); |
| return dir - 1; |
| } |
| |
| /* Free all allocated memory in dom_info. */ |
| |
| dom_info::~dom_info () |
| { |
| delete[] m_dfs_parent; |
| delete[] m_path_min; |
| delete[] m_key; |
| delete[] m_dom; |
| delete[] m_bucket; |
| delete[] m_next_bucket; |
| delete[] m_set_chain; |
| delete[] m_set_size; |
| delete[] m_set_child; |
| delete[] m_dfs_order; |
| delete[] m_dfs_to_bb; |
| BITMAP_FREE (m_fake_exit_edge); |
| } |
| |
| /* The nonrecursive variant of creating a DFS tree. BB is the starting basic |
| block for this tree and m_reverse is true, if predecessors should be visited |
| instead of successors of a node. After this is done all nodes reachable |
| from BB were visited, have assigned their dfs number and are linked together |
| to form a tree. */ |
| |
| void |
| dom_info::calc_dfs_tree_nonrec (basic_block bb) |
| { |
| edge_iterator *stack = new edge_iterator[m_n_basic_blocks + 1]; |
| int sp = 0; |
| unsigned d_i = dom_convert_dir_to_idx (m_reverse ? CDI_POST_DOMINATORS |
| : CDI_DOMINATORS); |
| |
| /* Initialize the first edge. */ |
| edge_iterator ei = m_reverse ? ei_start (bb->preds) |
| : ei_start (bb->succs); |
| |
| /* When the stack is empty we break out of this loop. */ |
| while (1) |
| { |
| basic_block bn; |
| edge_iterator einext; |
| |
| /* This loop traverses edges e in depth first manner, and fills the |
| stack. */ |
| while (!ei_end_p (ei)) |
| { |
| edge e = ei_edge (ei); |
| |
| /* Deduce from E the current and the next block (BB and BN), and the |
| next edge. */ |
| if (m_reverse) |
| { |
| bn = e->src; |
| |
| /* If the next node BN is either already visited or a border |
| block or out of region the current edge is useless, and simply |
| overwritten with the next edge out of the current node. */ |
| if (bn == m_end_block || bn->dom[d_i] == NULL |
| || m_dfs_order[bn->index]) |
| { |
| ei_next (&ei); |
| continue; |
| } |
| bb = e->dest; |
| einext = ei_start (bn->preds); |
| } |
| else |
| { |
| bn = e->dest; |
| if (bn == m_end_block || bn->dom[d_i] == NULL |
| || m_dfs_order[bn->index]) |
| { |
| ei_next (&ei); |
| continue; |
| } |
| bb = e->src; |
| einext = ei_start (bn->succs); |
| } |
| |
| gcc_assert (bn != m_start_block); |
| |
| /* Fill the DFS tree info calculatable _before_ recursing. */ |
| TBB my_i; |
| if (bb != m_start_block) |
| my_i = m_dfs_order[bb->index]; |
| else |
| my_i = *m_dfs_last; |
| TBB child_i = m_dfs_order[bn->index] = m_dfsnum++; |
| m_dfs_to_bb[child_i] = bn; |
| m_dfs_parent[child_i] = my_i; |
| |
| /* Save the current point in the CFG on the stack, and recurse. */ |
| stack[sp++] = ei; |
| ei = einext; |
| } |
| |
| if (!sp) |
| break; |
| ei = stack[--sp]; |
| |
| /* OK. The edge-list was exhausted, meaning normally we would |
| end the recursion. After returning from the recursive call, |
| there were (may be) other statements which were run after a |
| child node was completely considered by DFS. Here is the |
| point to do it in the non-recursive variant. |
| E.g. The block just completed is in e->dest for forward DFS, |
| the block not yet completed (the parent of the one above) |
| in e->src. This could be used e.g. for computing the number of |
| descendants or the tree depth. */ |
| ei_next (&ei); |
| } |
| delete[] stack; |
| } |
| |
| /* The main entry for calculating the DFS tree or forest. m_reverse is true, |
| if we are interested in the reverse flow graph. In that case the result is |
| not necessarily a tree but a forest, because there may be nodes from which |
| the EXIT_BLOCK is unreachable. */ |
| |
| void |
| dom_info::calc_dfs_tree () |
| { |
| *m_dfs_last = m_dfsnum; |
| m_dfs_to_bb[m_dfsnum] = m_start_block; |
| m_dfsnum++; |
| |
| calc_dfs_tree_nonrec (m_start_block); |
| |
| if (m_fake_exit_edge) |
| { |
| /* In the post-dom case we may have nodes without a path to EXIT_BLOCK. |
| They are reverse-unreachable. In the dom-case we disallow such |
| nodes, but in post-dom we have to deal with them. |
| |
| There are two situations in which this occurs. First, noreturn |
| functions. Second, infinite loops. In the first case we need to |
| pretend that there is an edge to the exit block. In the second |
| case, we wind up with a forest. We need to process all noreturn |
| blocks before we know if we've got any infinite loops. */ |
| |
| basic_block b; |
| bool saw_unconnected = false; |
| |
| FOR_BB_BETWEEN (b, m_start_block->prev_bb, m_end_block, prev_bb) |
| { |
| if (EDGE_COUNT (b->succs) > 0) |
| { |
| if (m_dfs_order[b->index] == 0) |
| saw_unconnected = true; |
| continue; |
| } |
| bitmap_set_bit (m_fake_exit_edge, b->index); |
| m_dfs_order[b->index] = m_dfsnum; |
| m_dfs_to_bb[m_dfsnum] = b; |
| m_dfs_parent[m_dfsnum] = *m_dfs_last; |
| m_dfsnum++; |
| calc_dfs_tree_nonrec (b); |
| } |
| |
| if (saw_unconnected) |
| { |
| FOR_BB_BETWEEN (b, m_start_block->prev_bb, m_end_block, prev_bb) |
| { |
| if (m_dfs_order[b->index]) |
| continue; |
| basic_block b2 = dfs_find_deadend (b); |
| gcc_checking_assert (m_dfs_order[b2->index] == 0); |
| bitmap_set_bit (m_fake_exit_edge, b2->index); |
| m_dfs_order[b2->index] = m_dfsnum; |
| m_dfs_to_bb[m_dfsnum] = b2; |
| m_dfs_parent[m_dfsnum] = *m_dfs_last; |
| m_dfsnum++; |
| calc_dfs_tree_nonrec (b2); |
| gcc_checking_assert (m_dfs_order[b->index]); |
| } |
| } |
| } |
| |
| m_nodes = m_dfsnum - 1; |
| |
| /* This aborts e.g. when there is _no_ path from ENTRY to EXIT at all. */ |
| gcc_assert (m_nodes == (unsigned int) m_n_basic_blocks - 1); |
| } |
| |
| /* Compress the path from V to the root of its set and update path_min at the |
| same time. After compress(di, V) set_chain[V] is the root of the set V is |
| in and path_min[V] is the node with the smallest key[] value on the path |
| from V to that root. */ |
| |
| void |
| dom_info::compress (TBB v) |
| { |
| /* Btw. It's not worth to unrecurse compress() as the depth is usually not |
| greater than 5 even for huge graphs (I've not seen call depth > 4). |
| Also performance wise compress() ranges _far_ behind eval(). */ |
| TBB parent = m_set_chain[v]; |
| if (m_set_chain[parent]) |
| { |
| compress (parent); |
| if (m_key[m_path_min[parent]] < m_key[m_path_min[v]]) |
| m_path_min[v] = m_path_min[parent]; |
| m_set_chain[v] = m_set_chain[parent]; |
| } |
| } |
| |
| /* Compress the path from V to the set root of V if needed (when the root has |
| changed since the last call). Returns the node with the smallest key[] |
| value on the path from V to the root. */ |
| |
| inline TBB |
| dom_info::eval (TBB v) |
| { |
| /* The representative of the set V is in, also called root (as the set |
| representation is a tree). */ |
| TBB rep = m_set_chain[v]; |
| |
| /* V itself is the root. */ |
| if (!rep) |
| return m_path_min[v]; |
| |
| /* Compress only if necessary. */ |
| if (m_set_chain[rep]) |
| { |
| compress (v); |
| rep = m_set_chain[v]; |
| } |
| |
| if (m_key[m_path_min[rep]] >= m_key[m_path_min[v]]) |
| return m_path_min[v]; |
| else |
| return m_path_min[rep]; |
| } |
| |
| /* This essentially merges the two sets of V and W, giving a single set with |
| the new root V. The internal representation of these disjoint sets is a |
| balanced tree. Currently link(V,W) is only used with V being the parent |
| of W. */ |
| |
| void |
| dom_info::link_roots (TBB v, TBB w) |
| { |
| TBB s = w; |
| |
| /* Rebalance the tree. */ |
| while (m_key[m_path_min[w]] < m_key[m_path_min[m_set_child[s]]]) |
| { |
| if (m_set_size[s] + m_set_size[m_set_child[m_set_child[s]]] |
| >= 2 * m_set_size[m_set_child[s]]) |
| { |
| m_set_chain[m_set_child[s]] = s; |
| m_set_child[s] = m_set_child[m_set_child[s]]; |
| } |
| else |
| { |
| m_set_size[m_set_child[s]] = m_set_size[s]; |
| s = m_set_chain[s] = m_set_child[s]; |
| } |
| } |
| |
| m_path_min[s] = m_path_min[w]; |
| m_set_size[v] += m_set_size[w]; |
| if (m_set_size[v] < 2 * m_set_size[w]) |
| std::swap (m_set_child[v], s); |
| |
| /* Merge all subtrees. */ |
| while (s) |
| { |
| m_set_chain[s] = v; |
| s = m_set_child[s]; |
| } |
| } |
| |
| /* This calculates the immediate dominators (or post-dominators). THIS is our |
| working structure and should hold the DFS forest. |
| On return the immediate dominator to node V is in m_dom[V]. */ |
| |
| void |
| dom_info::calc_idoms () |
| { |
| /* Go backwards in DFS order, to first look at the leafs. */ |
| for (TBB v = m_nodes; v > 1; v--) |
| { |
| basic_block bb = m_dfs_to_bb[v]; |
| edge e; |
| |
| TBB par = m_dfs_parent[v]; |
| TBB k = v; |
| |
| edge_iterator ei = m_reverse ? ei_start (bb->succs) |
| : ei_start (bb->preds); |
| edge_iterator einext; |
| |
| if (m_fake_exit_edge) |
| { |
| /* If this block has a fake edge to exit, process that first. */ |
| if (bitmap_bit_p (m_fake_exit_edge, bb->index)) |
| { |
| einext = ei; |
| einext.index = 0; |
| goto do_fake_exit_edge; |
| } |
| } |
| |
| /* Search all direct predecessors for the smallest node with a path |
| to them. That way we have the smallest node with also a path to |
| us only over nodes behind us. In effect we search for our |
| semidominator. */ |
| while (!ei_end_p (ei)) |
| { |
| basic_block b; |
| TBB k1; |
| |
| e = ei_edge (ei); |
| b = m_reverse ? e->dest : e->src; |
| einext = ei; |
| ei_next (&einext); |
| |
| if (b == m_start_block) |
| { |
| do_fake_exit_edge: |
| k1 = *m_dfs_last; |
| } |
| else |
| k1 = m_dfs_order[b->index]; |
| |
| /* Call eval() only if really needed. If k1 is above V in DFS tree, |
| then we know, that eval(k1) == k1 and key[k1] == k1. */ |
| if (k1 > v) |
| k1 = m_key[eval (k1)]; |
| if (k1 < k) |
| k = k1; |
| |
| ei = einext; |
| } |
| |
| m_key[v] = k; |
| link_roots (par, v); |
| m_next_bucket[v] = m_bucket[k]; |
| m_bucket[k] = v; |
| |
| /* Transform semidominators into dominators. */ |
| for (TBB w = m_bucket[par]; w; w = m_next_bucket[w]) |
| { |
| k = eval (w); |
| if (m_key[k] < m_key[w]) |
| m_dom[w] = k; |
| else |
| m_dom[w] = par; |
| } |
| /* We don't need to cleanup next_bucket[]. */ |
| m_bucket[par] = 0; |
| } |
| |
| /* Explicitly define the dominators. */ |
| m_dom[1] = 0; |
| for (TBB v = 2; v <= m_nodes; v++) |
| if (m_dom[v] != m_key[v]) |
| m_dom[v] = m_dom[m_dom[v]]; |
| } |
| |
| /* Assign dfs numbers starting from NUM to NODE and its sons. */ |
| |
| static void |
| assign_dfs_numbers (struct et_node *node, int *num) |
| { |
| struct et_node *son; |
| |
| node->dfs_num_in = (*num)++; |
| |
| if (node->son) |
| { |
| assign_dfs_numbers (node->son, num); |
| for (son = node->son->right; son != node->son; son = son->right) |
| assign_dfs_numbers (son, num); |
| } |
| |
| node->dfs_num_out = (*num)++; |
| } |
| |
| /* Compute the data necessary for fast resolving of dominator queries in a |
| static dominator tree. */ |
| |
| static void |
| compute_dom_fast_query (enum cdi_direction dir) |
| { |
| int num = 0; |
| basic_block bb; |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| gcc_checking_assert (dom_info_available_p (dir)); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| return; |
| |
| FOR_ALL_BB_FN (bb, cfun) |
| { |
| if (!bb->dom[dir_index]->father) |
| assign_dfs_numbers (bb->dom[dir_index], &num); |
| } |
| |
| dom_computed[dir_index] = DOM_OK; |
| } |
| |
| /* Analogous to the previous function but compute the data for reducible |
| region REGION. */ |
| |
| static void |
| compute_dom_fast_query_in_region (enum cdi_direction dir, |
| vec<basic_block> region) |
| { |
| int num = 0; |
| basic_block bb; |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| gcc_checking_assert (dom_info_available_p (dir)); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| return; |
| |
| /* Assign dfs numbers for region nodes except for entry and exit nodes. */ |
| for (unsigned int i = 1; i < region.length () - 1; i++) |
| { |
| bb = region[i]; |
| if (!bb->dom[dir_index]->father) |
| assign_dfs_numbers (bb->dom[dir_index], &num); |
| } |
| |
| dom_computed[dir_index] = DOM_OK; |
| } |
| |
| /* The main entry point into this module. DIR is set depending on whether |
| we want to compute dominators or postdominators. */ |
| |
| void |
| calculate_dominance_info (cdi_direction dir) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| { |
| checking_verify_dominators (dir); |
| return; |
| } |
| |
| timevar_push (TV_DOMINANCE); |
| if (!dom_info_available_p (dir)) |
| { |
| gcc_assert (!n_bbs_in_dom_tree[dir_index]); |
| |
| basic_block b; |
| FOR_ALL_BB_FN (b, cfun) |
| { |
| b->dom[dir_index] = et_new_tree (b); |
| } |
| n_bbs_in_dom_tree[dir_index] = n_basic_blocks_for_fn (cfun); |
| |
| dom_info di (cfun, dir); |
| di.calc_dfs_tree (); |
| di.calc_idoms (); |
| |
| FOR_EACH_BB_FN (b, cfun) |
| { |
| if (basic_block d = di.get_idom (b)) |
| et_set_father (b->dom[dir_index], d->dom[dir_index]); |
| } |
| |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| } |
| else |
| checking_verify_dominators (dir); |
| |
| compute_dom_fast_query (dir); |
| |
| timevar_pop (TV_DOMINANCE); |
| } |
| |
| /* Analogous to the previous function but compute dominance info for regions |
| which are single entry, multiple exit regions for CDI_DOMINATORs and |
| multiple entry, single exit regions for CDI_POST_DOMINATORs. */ |
| |
| void |
| calculate_dominance_info_for_region (cdi_direction dir, |
| vec<basic_block> region) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| basic_block bb; |
| unsigned int i; |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| return; |
| |
| timevar_push (TV_DOMINANCE); |
| /* Assume that dom info is not partially computed. */ |
| gcc_assert (!dom_info_available_p (dir)); |
| |
| FOR_EACH_VEC_ELT (region, i, bb) |
| { |
| bb->dom[dir_index] = et_new_tree (bb); |
| } |
| dom_info di (region, dir); |
| di.calc_dfs_tree (); |
| di.calc_idoms (); |
| |
| FOR_EACH_VEC_ELT (region, i, bb) |
| if (basic_block d = di.get_idom (bb)) |
| et_set_father (bb->dom[dir_index], d->dom[dir_index]); |
| |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| compute_dom_fast_query_in_region (dir, region); |
| |
| timevar_pop (TV_DOMINANCE); |
| } |
| |
| /* Free dominance information for direction DIR. */ |
| void |
| free_dominance_info (function *fn, enum cdi_direction dir) |
| { |
| basic_block bb; |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| if (!dom_info_available_p (fn, dir)) |
| return; |
| |
| FOR_ALL_BB_FN (bb, fn) |
| { |
| et_free_tree_force (bb->dom[dir_index]); |
| bb->dom[dir_index] = NULL; |
| } |
| et_free_pools (); |
| |
| fn->cfg->x_n_bbs_in_dom_tree[dir_index] = 0; |
| |
| fn->cfg->x_dom_computed[dir_index] = DOM_NONE; |
| } |
| |
| void |
| free_dominance_info (enum cdi_direction dir) |
| { |
| free_dominance_info (cfun, dir); |
| } |
| |
| /* Free dominance information for direction DIR in region REGION. */ |
| |
| void |
| free_dominance_info_for_region (function *fn, |
| enum cdi_direction dir, |
| vec<basic_block> region) |
| { |
| basic_block bb; |
| unsigned int i; |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| if (!dom_info_available_p (dir)) |
| return; |
| |
| FOR_EACH_VEC_ELT (region, i, bb) |
| { |
| et_free_tree_force (bb->dom[dir_index]); |
| bb->dom[dir_index] = NULL; |
| } |
| et_free_pools (); |
| |
| fn->cfg->x_dom_computed[dir_index] = DOM_NONE; |
| |
| fn->cfg->x_n_bbs_in_dom_tree[dir_index] = 0; |
| } |
| |
| /* Return the immediate dominator of basic block BB. */ |
| basic_block |
| get_immediate_dominator (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *node = bb->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (!node->father) |
| return NULL; |
| |
| return (basic_block) node->father->data; |
| } |
| |
| /* Set the immediate dominator of the block possibly removing |
| existing edge. NULL can be used to remove any edge. */ |
| void |
| set_immediate_dominator (enum cdi_direction dir, basic_block bb, |
| basic_block dominated_by) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *node = bb->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (node->father) |
| { |
| if (node->father->data == dominated_by) |
| return; |
| et_split (node); |
| } |
| |
| if (dominated_by) |
| et_set_father (node, dominated_by->dom[dir_index]); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| } |
| |
| /* Returns the list of basic blocks immediately dominated by BB, in the |
| direction DIR. */ |
| vec<basic_block> |
| get_dominated_by (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *node = bb->dom[dir_index], *son = node->son, *ason; |
| vec<basic_block> bbs = vNULL; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (!son) |
| return vNULL; |
| |
| bbs.safe_push ((basic_block) son->data); |
| for (ason = son->right; ason != son; ason = ason->right) |
| bbs.safe_push ((basic_block) ason->data); |
| |
| return bbs; |
| } |
| |
| /* Returns the list of basic blocks that are immediately dominated (in |
| direction DIR) by some block between N_REGION ones stored in REGION, |
| except for blocks in the REGION itself. */ |
| |
| vec<basic_block> |
| get_dominated_by_region (enum cdi_direction dir, basic_block *region, |
| unsigned n_region) |
| { |
| unsigned i; |
| basic_block dom; |
| vec<basic_block> doms = vNULL; |
| |
| for (i = 0; i < n_region; i++) |
| region[i]->flags |= BB_DUPLICATED; |
| for (i = 0; i < n_region; i++) |
| for (dom = first_dom_son (dir, region[i]); |
| dom; |
| dom = next_dom_son (dir, dom)) |
| if (!(dom->flags & BB_DUPLICATED)) |
| doms.safe_push (dom); |
| for (i = 0; i < n_region; i++) |
| region[i]->flags &= ~BB_DUPLICATED; |
| |
| return doms; |
| } |
| |
| /* Returns the list of basic blocks including BB dominated by BB, in the |
| direction DIR up to DEPTH in the dominator tree. The DEPTH of zero will |
| produce a vector containing all dominated blocks. The vector will be sorted |
| in preorder. */ |
| |
| vec<basic_block> |
| get_dominated_to_depth (enum cdi_direction dir, basic_block bb, int depth) |
| { |
| vec<basic_block> bbs = vNULL; |
| unsigned i; |
| unsigned next_level_start; |
| |
| i = 0; |
| bbs.safe_push (bb); |
| next_level_start = 1; /* = bbs.length (); */ |
| |
| do |
| { |
| basic_block son; |
| |
| bb = bbs[i++]; |
| for (son = first_dom_son (dir, bb); |
| son; |
| son = next_dom_son (dir, son)) |
| bbs.safe_push (son); |
| |
| if (i == next_level_start && --depth) |
| next_level_start = bbs.length (); |
| } |
| while (i < next_level_start); |
| |
| return bbs; |
| } |
| |
| /* Returns the list of basic blocks including BB dominated by BB, in the |
| direction DIR. The vector will be sorted in preorder. */ |
| |
| vec<basic_block> |
| get_all_dominated_blocks (enum cdi_direction dir, basic_block bb) |
| { |
| return get_dominated_to_depth (dir, bb, 0); |
| } |
| |
| /* Redirect all edges pointing to BB to TO. */ |
| void |
| redirect_immediate_dominators (enum cdi_direction dir, basic_block bb, |
| basic_block to) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *bb_node, *to_node, *son; |
| |
| bb_node = bb->dom[dir_index]; |
| to_node = to->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (!bb_node->son) |
| return; |
| |
| while (bb_node->son) |
| { |
| son = bb_node->son; |
| |
| et_split (son); |
| et_set_father (son, to_node); |
| } |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| } |
| |
| /* Find first basic block in the tree dominating both BB1 and BB2. */ |
| basic_block |
| nearest_common_dominator (enum cdi_direction dir, basic_block bb1, basic_block bb2) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (!bb1) |
| return bb2; |
| if (!bb2) |
| return bb1; |
| |
| return (basic_block) et_nca (bb1->dom[dir_index], bb2->dom[dir_index])->data; |
| } |
| |
| |
| /* Find the nearest common dominator for the basic blocks in BLOCKS, |
| using dominance direction DIR. */ |
| |
| basic_block |
| nearest_common_dominator_for_set (enum cdi_direction dir, bitmap blocks) |
| { |
| unsigned i, first; |
| bitmap_iterator bi; |
| basic_block dom; |
| |
| first = bitmap_first_set_bit (blocks); |
| dom = BASIC_BLOCK_FOR_FN (cfun, first); |
| EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi) |
| if (dom != BASIC_BLOCK_FOR_FN (cfun, i)) |
| dom = nearest_common_dominator (dir, dom, BASIC_BLOCK_FOR_FN (cfun, i)); |
| |
| return dom; |
| } |
| |
| /* Given a dominator tree, we can determine whether one thing |
| dominates another in constant time by using two DFS numbers: |
| |
| 1. The number for when we visit a node on the way down the tree |
| 2. The number for when we visit a node on the way back up the tree |
| |
| You can view these as bounds for the range of dfs numbers the |
| nodes in the subtree of the dominator tree rooted at that node |
| will contain. |
| |
| The dominator tree is always a simple acyclic tree, so there are |
| only three possible relations two nodes in the dominator tree have |
| to each other: |
| |
| 1. Node A is above Node B (and thus, Node A dominates node B) |
| |
| A |
| | |
| C |
| / \ |
| B D |
| |
| |
| In the above case, DFS_Number_In of A will be <= DFS_Number_In of |
| B, and DFS_Number_Out of A will be >= DFS_Number_Out of B. This is |
| because we must hit A in the dominator tree *before* B on the walk |
| down, and we will hit A *after* B on the walk back up |
| |
| 2. Node A is below node B (and thus, node B dominates node A) |
| |
| |
| B |
| | |
| A |
| / \ |
| C D |
| |
| In the above case, DFS_Number_In of A will be >= DFS_Number_In of |
| B, and DFS_Number_Out of A will be <= DFS_Number_Out of B. |
| |
| This is because we must hit A in the dominator tree *after* B on |
| the walk down, and we will hit A *before* B on the walk back up |
| |
| 3. Node A and B are siblings (and thus, neither dominates the other) |
| |
| C |
| | |
| D |
| / \ |
| A B |
| |
| In the above case, DFS_Number_In of A will *always* be <= |
| DFS_Number_In of B, and DFS_Number_Out of A will *always* be <= |
| DFS_Number_Out of B. This is because we will always finish the dfs |
| walk of one of the subtrees before the other, and thus, the dfs |
| numbers for one subtree can't intersect with the range of dfs |
| numbers for the other subtree. If you swap A and B's position in |
| the dominator tree, the comparison changes direction, but the point |
| is that both comparisons will always go the same way if there is no |
| dominance relationship. |
| |
| Thus, it is sufficient to write |
| |
| A_Dominates_B (node A, node B) |
| { |
| return DFS_Number_In(A) <= DFS_Number_In(B) |
| && DFS_Number_Out (A) >= DFS_Number_Out(B); |
| } |
| |
| A_Dominated_by_B (node A, node B) |
| { |
| return DFS_Number_In(A) >= DFS_Number_In(B) |
| && DFS_Number_Out (A) <= DFS_Number_Out(B); |
| } */ |
| |
| /* Return TRUE in case BB1 is dominated by BB2. */ |
| bool |
| dominated_by_p (enum cdi_direction dir, const_basic_block bb1, const_basic_block bb2) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *n1 = bb1->dom[dir_index], *n2 = bb2->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| return (n1->dfs_num_in >= n2->dfs_num_in |
| && n1->dfs_num_out <= n2->dfs_num_out); |
| |
| return et_below (n1, n2); |
| } |
| |
| /* Returns the entry dfs number for basic block BB, in the direction DIR. */ |
| |
| unsigned |
| bb_dom_dfs_in (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *n = bb->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index] == DOM_OK); |
| return n->dfs_num_in; |
| } |
| |
| /* Returns the exit dfs number for basic block BB, in the direction DIR. */ |
| |
| unsigned |
| bb_dom_dfs_out (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *n = bb->dom[dir_index]; |
| |
| gcc_checking_assert (dom_computed[dir_index] == DOM_OK); |
| return n->dfs_num_out; |
| } |
| |
| /* Verify invariants of dominator structure. */ |
| DEBUG_FUNCTION void |
| verify_dominators (cdi_direction dir) |
| { |
| gcc_assert (dom_info_available_p (dir)); |
| |
| dom_info di (cfun, dir); |
| di.calc_dfs_tree (); |
| di.calc_idoms (); |
| |
| bool err = false; |
| basic_block bb; |
| FOR_EACH_BB_FN (bb, cfun) |
| { |
| basic_block imm_bb = get_immediate_dominator (dir, bb); |
| if (!imm_bb) |
| { |
| error ("dominator of %d status unknown", bb->index); |
| err = true; |
| continue; |
| } |
| |
| basic_block imm_bb_correct = di.get_idom (bb); |
| if (imm_bb != imm_bb_correct) |
| { |
| error ("dominator of %d should be %d, not %d", |
| bb->index, imm_bb_correct->index, imm_bb->index); |
| err = true; |
| } |
| } |
| |
| gcc_assert (!err); |
| } |
| |
| /* Determine immediate dominator (or postdominator, according to DIR) of BB, |
| assuming that dominators of other blocks are correct. We also use it to |
| recompute the dominators in a restricted area, by iterating it until it |
| reaches a fixed point. */ |
| |
| basic_block |
| recompute_dominator (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| basic_block dom_bb = NULL; |
| edge e; |
| edge_iterator ei; |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| if (dir == CDI_DOMINATORS) |
| { |
| FOR_EACH_EDGE (e, ei, bb->preds) |
| { |
| if (!dominated_by_p (dir, e->src, bb)) |
| dom_bb = nearest_common_dominator (dir, dom_bb, e->src); |
| } |
| } |
| else |
| { |
| FOR_EACH_EDGE (e, ei, bb->succs) |
| { |
| if (!dominated_by_p (dir, e->dest, bb)) |
| dom_bb = nearest_common_dominator (dir, dom_bb, e->dest); |
| } |
| } |
| |
| return dom_bb; |
| } |
| |
| /* Use simple heuristics (see iterate_fix_dominators) to determine dominators |
| of BBS. We assume that all the immediate dominators except for those of the |
| blocks in BBS are correct. If CONSERVATIVE is true, we also assume that the |
| currently recorded immediate dominators of blocks in BBS really dominate the |
| blocks. The basic blocks for that we determine the dominator are removed |
| from BBS. */ |
| |
| static void |
| prune_bbs_to_update_dominators (vec<basic_block> bbs, |
| bool conservative) |
| { |
| unsigned i; |
| bool single; |
| basic_block bb, dom = NULL; |
| edge_iterator ei; |
| edge e; |
| |
| for (i = 0; bbs.iterate (i, &bb);) |
| { |
| if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) |
| goto succeed; |
| |
| if (single_pred_p (bb)) |
| { |
| set_immediate_dominator (CDI_DOMINATORS, bb, single_pred (bb)); |
| goto succeed; |
| } |
| |
| if (!conservative) |
| goto fail; |
| |
| single = true; |
| dom = NULL; |
| FOR_EACH_EDGE (e, ei, bb->preds) |
| { |
| if (dominated_by_p (CDI_DOMINATORS, e->src, bb)) |
| continue; |
| |
| if (!dom) |
| dom = e->src; |
| else |
| { |
| single = false; |
| dom = nearest_common_dominator (CDI_DOMINATORS, dom, e->src); |
| } |
| } |
| |
| gcc_assert (dom != NULL); |
| if (single |
| || find_edge (dom, bb)) |
| { |
| set_immediate_dominator (CDI_DOMINATORS, bb, dom); |
| goto succeed; |
| } |
| |
| fail: |
| i++; |
| continue; |
| |
| succeed: |
| bbs.unordered_remove (i); |
| } |
| } |
| |
| /* Returns root of the dominance tree in the direction DIR that contains |
| BB. */ |
| |
| static basic_block |
| root_of_dom_tree (enum cdi_direction dir, basic_block bb) |
| { |
| return (basic_block) et_root (bb->dom[dom_convert_dir_to_idx (dir)])->data; |
| } |
| |
| /* See the comment in iterate_fix_dominators. Finds the immediate dominators |
| for the sons of Y, found using the SON and BROTHER arrays representing |
| the dominance tree of graph G. BBS maps the vertices of G to the basic |
| blocks. */ |
| |
| static void |
| determine_dominators_for_sons (struct graph *g, vec<basic_block> bbs, |
| int y, int *son, int *brother) |
| { |
| bitmap gprime; |
| int i, a, nc; |
| vec<int> *sccs; |
| basic_block bb, dom, ybb; |
| unsigned si; |
| edge e; |
| edge_iterator ei; |
| |
| if (son[y] == -1) |
| return; |
| if (y == (int) bbs.length ()) |
| ybb = ENTRY_BLOCK_PTR_FOR_FN (cfun); |
| else |
| ybb = bbs[y]; |
| |
| if (brother[son[y]] == -1) |
| { |
| /* Handle the common case Y has just one son specially. */ |
| bb = bbs[son[y]]; |
| set_immediate_dominator (CDI_DOMINATORS, bb, |
| recompute_dominator (CDI_DOMINATORS, bb)); |
| identify_vertices (g, y, son[y]); |
| return; |
| } |
| |
| gprime = BITMAP_ALLOC (NULL); |
| for (a = son[y]; a != -1; a = brother[a]) |
| bitmap_set_bit (gprime, a); |
| |
| nc = graphds_scc (g, gprime); |
| BITMAP_FREE (gprime); |
| |
| /* ??? Needed to work around the pre-processor confusion with |
| using a multi-argument template type as macro argument. */ |
| typedef vec<int> vec_int_heap; |
| sccs = XCNEWVEC (vec_int_heap, nc); |
| for (a = son[y]; a != -1; a = brother[a]) |
| sccs[g->vertices[a].component].safe_push (a); |
| |
| for (i = nc - 1; i >= 0; i--) |
| { |
| dom = NULL; |
| FOR_EACH_VEC_ELT (sccs[i], si, a) |
| { |
| bb = bbs[a]; |
| FOR_EACH_EDGE (e, ei, bb->preds) |
| { |
| if (root_of_dom_tree (CDI_DOMINATORS, e->src) != ybb) |
| continue; |
| |
| dom = nearest_common_dominator (CDI_DOMINATORS, dom, e->src); |
| } |
| } |
| |
| gcc_assert (dom != NULL); |
| FOR_EACH_VEC_ELT (sccs[i], si, a) |
| { |
| bb = bbs[a]; |
| set_immediate_dominator (CDI_DOMINATORS, bb, dom); |
| } |
| } |
| |
| for (i = 0; i < nc; i++) |
| sccs[i].release (); |
| free (sccs); |
| |
| for (a = son[y]; a != -1; a = brother[a]) |
| identify_vertices (g, y, a); |
| } |
| |
| /* Recompute dominance information for basic blocks in the set BBS. The |
| function assumes that the immediate dominators of all the other blocks |
| in CFG are correct, and that there are no unreachable blocks. |
| |
| If CONSERVATIVE is true, we additionally assume that all the ancestors of |
| a block of BBS in the current dominance tree dominate it. */ |
| |
| void |
| iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs, |
| bool conservative) |
| { |
| unsigned i; |
| basic_block bb, dom; |
| struct graph *g; |
| int n, y; |
| size_t dom_i; |
| edge e; |
| edge_iterator ei; |
| int *parent, *son, *brother; |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| /* We only support updating dominators. There are some problems with |
| updating postdominators (need to add fake edges from infinite loops |
| and noreturn functions), and since we do not currently use |
| iterate_fix_dominators for postdominators, any attempt to handle these |
| problems would be unused, untested, and almost surely buggy. We keep |
| the DIR argument for consistency with the rest of the dominator analysis |
| interface. */ |
| gcc_checking_assert (dir == CDI_DOMINATORS && dom_computed[dir_index]); |
| |
| /* The algorithm we use takes inspiration from the following papers, although |
| the details are quite different from any of them: |
| |
| [1] G. Ramalingam, T. Reps, An Incremental Algorithm for Maintaining the |
| Dominator Tree of a Reducible Flowgraph |
| [2] V. C. Sreedhar, G. R. Gao, Y.-F. Lee: Incremental computation of |
| dominator trees |
| [3] K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance |
| Algorithm |
| |
| First, we use the following heuristics to decrease the size of the BBS |
| set: |
| a) if BB has a single predecessor, then its immediate dominator is this |
| predecessor |
| additionally, if CONSERVATIVE is true: |
| b) if all the predecessors of BB except for one (X) are dominated by BB, |
| then X is the immediate dominator of BB |
| c) if the nearest common ancestor of the predecessors of BB is X and |
| X -> BB is an edge in CFG, then X is the immediate dominator of BB |
| |
| Then, we need to establish the dominance relation among the basic blocks |
| in BBS. We split the dominance tree by removing the immediate dominator |
| edges from BBS, creating a forest F. We form a graph G whose vertices |
| are BBS and ENTRY and X -> Y is an edge of G if there exists an edge |
| X' -> Y in CFG such that X' belongs to the tree of the dominance forest |
| whose root is X. We then determine dominance tree of G. Note that |
| for X, Y in BBS, X dominates Y in CFG if and only if X dominates Y in G. |
| In this step, we can use arbitrary algorithm to determine dominators. |
| We decided to prefer the algorithm [3] to the algorithm of |
| Lengauer and Tarjan, since the set BBS is usually small (rarely exceeding |
| 10 during gcc bootstrap), and [3] should perform better in this case. |
| |
| Finally, we need to determine the immediate dominators for the basic |
| blocks of BBS. If the immediate dominator of X in G is Y, then |
| the immediate dominator of X in CFG belongs to the tree of F rooted in |
| Y. We process the dominator tree T of G recursively, starting from leaves. |
| Suppose that X_1, X_2, ..., X_k are the sons of Y in T, and that the |
| subtrees of the dominance tree of CFG rooted in X_i are already correct. |
| Let G' be the subgraph of G induced by {X_1, X_2, ..., X_k}. We make |
| the following observations: |
| (i) the immediate dominator of all blocks in a strongly connected |
| component of G' is the same |
| (ii) if X has no predecessors in G', then the immediate dominator of X |
| is the nearest common ancestor of the predecessors of X in the |
| subtree of F rooted in Y |
| Therefore, it suffices to find the topological ordering of G', and |
| process the nodes X_i in this order using the rules (i) and (ii). |
| Then, we contract all the nodes X_i with Y in G, so that the further |
| steps work correctly. */ |
| |
| if (!conservative) |
| { |
| /* Split the tree now. If the idoms of blocks in BBS are not |
| conservatively correct, setting the dominators using the |
| heuristics in prune_bbs_to_update_dominators could |
| create cycles in the dominance "tree", and cause ICE. */ |
| FOR_EACH_VEC_ELT (bbs, i, bb) |
| set_immediate_dominator (CDI_DOMINATORS, bb, NULL); |
| } |
| |
| prune_bbs_to_update_dominators (bbs, conservative); |
| n = bbs.length (); |
| |
| if (n == 0) |
| return; |
| |
| if (n == 1) |
| { |
| bb = bbs[0]; |
| set_immediate_dominator (CDI_DOMINATORS, bb, |
| recompute_dominator (CDI_DOMINATORS, bb)); |
| return; |
| } |
| |
| /* Construct the graph G. */ |
| hash_map<basic_block, int> map (251); |
| FOR_EACH_VEC_ELT (bbs, i, bb) |
| { |
| /* If the dominance tree is conservatively correct, split it now. */ |
| if (conservative) |
| set_immediate_dominator (CDI_DOMINATORS, bb, NULL); |
| map.put (bb, i); |
| } |
| map.put (ENTRY_BLOCK_PTR_FOR_FN (cfun), n); |
| |
| g = new_graph (n + 1); |
| for (y = 0; y < g->n_vertices; y++) |
| g->vertices[y].data = BITMAP_ALLOC (NULL); |
| FOR_EACH_VEC_ELT (bbs, i, bb) |
| { |
| FOR_EACH_EDGE (e, ei, bb->preds) |
| { |
| dom = root_of_dom_tree (CDI_DOMINATORS, e->src); |
| if (dom == bb) |
| continue; |
| |
| dom_i = *map.get (dom); |
| |
| /* Do not include parallel edges to G. */ |
| if (!bitmap_set_bit ((bitmap) g->vertices[dom_i].data, i)) |
| continue; |
| |
| add_edge (g, dom_i, i); |
| } |
| } |
| for (y = 0; y < g->n_vertices; y++) |
| BITMAP_FREE (g->vertices[y].data); |
| |
| /* Find the dominator tree of G. */ |
| son = XNEWVEC (int, n + 1); |
| brother = XNEWVEC (int, n + 1); |
| parent = XNEWVEC (int, n + 1); |
| graphds_domtree (g, n, parent, son, brother); |
| |
| /* Finally, traverse the tree and find the immediate dominators. */ |
| for (y = n; son[y] != -1; y = son[y]) |
| continue; |
| while (y != -1) |
| { |
| determine_dominators_for_sons (g, bbs, y, son, brother); |
| |
| if (brother[y] != -1) |
| { |
| y = brother[y]; |
| while (son[y] != -1) |
| y = son[y]; |
| } |
| else |
| y = parent[y]; |
| } |
| |
| free (son); |
| free (brother); |
| free (parent); |
| |
| free_graph (g); |
| } |
| |
| void |
| add_to_dominance_info (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| gcc_checking_assert (dom_computed[dir_index] && !bb->dom[dir_index]); |
| |
| n_bbs_in_dom_tree[dir_index]++; |
| |
| bb->dom[dir_index] = et_new_tree (bb); |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| } |
| |
| void |
| delete_from_dominance_info (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| gcc_checking_assert (dom_computed[dir_index]); |
| |
| et_free_tree (bb->dom[dir_index]); |
| bb->dom[dir_index] = NULL; |
| n_bbs_in_dom_tree[dir_index]--; |
| |
| if (dom_computed[dir_index] == DOM_OK) |
| dom_computed[dir_index] = DOM_NO_FAST_QUERY; |
| } |
| |
| /* Returns the first son of BB in the dominator or postdominator tree |
| as determined by DIR. */ |
| |
| basic_block |
| first_dom_son (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *son = bb->dom[dir_index]->son; |
| |
| return (basic_block) (son ? son->data : NULL); |
| } |
| |
| /* Returns the next dominance son after BB in the dominator or postdominator |
| tree as determined by DIR, or NULL if it was the last one. */ |
| |
| basic_block |
| next_dom_son (enum cdi_direction dir, basic_block bb) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| struct et_node *next = bb->dom[dir_index]->right; |
| |
| return (basic_block) (next->father->son == next ? NULL : next->data); |
| } |
| |
| /* Return dominance availability for dominance info DIR. */ |
| |
| enum dom_state |
| dom_info_state (function *fn, enum cdi_direction dir) |
| { |
| if (!fn->cfg) |
| return DOM_NONE; |
| |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| return fn->cfg->x_dom_computed[dir_index]; |
| } |
| |
| enum dom_state |
| dom_info_state (enum cdi_direction dir) |
| { |
| return dom_info_state (cfun, dir); |
| } |
| |
| /* Set the dominance availability for dominance info DIR to NEW_STATE. */ |
| |
| void |
| set_dom_info_availability (enum cdi_direction dir, enum dom_state new_state) |
| { |
| unsigned int dir_index = dom_convert_dir_to_idx (dir); |
| |
| dom_computed[dir_index] = new_state; |
| } |
| |
| /* Returns true if dominance information for direction DIR is available. */ |
| |
| bool |
| dom_info_available_p (function *fn, enum cdi_direction dir) |
| { |
| return dom_info_state (fn, dir) != DOM_NONE; |
| } |
| |
| bool |
| dom_info_available_p (enum cdi_direction dir) |
| { |
| return dom_info_available_p (cfun, dir); |
| } |
| |
| DEBUG_FUNCTION void |
| debug_dominance_info (enum cdi_direction dir) |
| { |
| basic_block bb, bb2; |
| FOR_EACH_BB_FN (bb, cfun) |
| if ((bb2 = get_immediate_dominator (dir, bb))) |
| fprintf (stderr, "%i %i\n", bb->index, bb2->index); |
| } |
| |
| /* Prints to stderr representation of the dominance tree (for direction DIR) |
| rooted in ROOT, indented by INDENT tabulators. If INDENT_FIRST is false, |
| the first line of the output is not indented. */ |
| |
| static void |
| debug_dominance_tree_1 (enum cdi_direction dir, basic_block root, |
| unsigned indent, bool indent_first) |
| { |
| basic_block son; |
| unsigned i; |
| bool first = true; |
| |
| if (indent_first) |
| for (i = 0; i < indent; i++) |
| fprintf (stderr, "\t"); |
| fprintf (stderr, "%d\t", root->index); |
| |
| for (son = first_dom_son (dir, root); |
| son; |
| son = next_dom_son (dir, son)) |
| { |
| debug_dominance_tree_1 (dir, son, indent + 1, !first); |
| first = false; |
| } |
| |
| if (first) |
| fprintf (stderr, "\n"); |
| } |
| |
| /* Prints to stderr representation of the dominance tree (for direction DIR) |
| rooted in ROOT. */ |
| |
| DEBUG_FUNCTION void |
| debug_dominance_tree (enum cdi_direction dir, basic_block root) |
| { |
| debug_dominance_tree_1 (dir, root, 0, false); |
| } |