rework liveness dumper
[libfirm] / ir / ana / domfront.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Algorithms for computing dominance frontiers.
23  * @author      Sebastian Hack, Daniel Grund
24  * @date        04.05.2005
25  */
26 #include "config.h"
27
28 #include "obst.h"
29 #include "pmap.h"
30 #include "pdeq.h"
31 #include "irdom.h"
32 #include "array.h"
33 #include "irgraph.h"
34 #include "iredges_t.h"
35 #include "irnodeset.h"
36
37 /**
38  * A wrapper for get_Block_idom.
39  * This function returns the block itself, if the block is the start
40  * block. Returning NULL would make any != comparison true which
41  * suggests, that the start block is dominated by some other node.
42  * @param bl The block.
43  * @return The immediate dominator of the block.
44  */
45 static inline ir_node *get_idom(ir_node *bl)
46 {
47         ir_node *idom = get_Block_idom(bl);
48         return idom == NULL ? bl : idom;
49 }
50
51 /**
52  * Compute the dominance frontier for a given block.
53  *
54  * @param blk   the block where the calculation starts
55  *
56  * @return the list of all blocks in the dominance frontier of blk
57  */
58 static ir_node **compute_df(ir_node *blk, ir_dom_front_info_t *info)
59 {
60         ir_node *c;
61         ir_node **df_list = NEW_ARR_F(ir_node *, 0);
62         ir_node **df;
63         size_t len;
64
65         /* Add local dominance frontiers */
66         foreach_block_succ(blk, edge) {
67                 ir_node *y = get_edge_src_irn(edge);
68
69                 if (get_idom(y) != blk) {
70                         ARR_APP1(ir_node *, df_list, y);
71                 }
72         }
73
74         /*
75          * Go recursively down the dominance tree and add all blocks
76          * into the dominance frontiers of the children, which are not
77          * dominated by the given block.
78          */
79         for (c = get_Block_dominated_first(blk); c; c = get_Block_dominated_next(c)) {
80                 size_t i;
81                 ir_node **df_c_list = compute_df(c, info);
82
83                 for (i = ARR_LEN(df_c_list); i > 0;) {
84                         ir_node *w = df_c_list[--i];
85                         if (get_idom(w) != blk)
86                                 ARR_APP1(ir_node *, df_list, w);
87                 }
88         }
89
90         /* now copy the flexible array to the obstack */
91         len = ARR_LEN(df_list);
92         df = NEW_ARR_D(ir_node *, &info->obst, len);
93         memcpy(df, df_list, len * sizeof(df[0]));
94         DEL_ARR_F(df_list);
95
96         pmap_insert(info->df_map, blk, df);
97         return df;
98 }
99
100 void ir_compute_dominance_frontiers(ir_graph *irg)
101 {
102         ir_dom_front_info_t *info = &irg->domfront;
103
104         assure_edges(irg);
105         obstack_init(&info->obst);
106         info->df_map = pmap_create();
107         assure_doms(irg);
108         compute_df(get_irg_start_block(irg), info);
109
110         add_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE_FRONTIERS);
111 }
112
113 void ir_free_dominance_frontiers(ir_graph *irg)
114 {
115         clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE_FRONTIERS);
116
117         ir_dom_front_info_t *info = &irg->domfront;
118         if (info->df_map == NULL)
119                 return;
120
121         obstack_free(&info->obst, NULL);
122         pmap_destroy(info->df_map);
123         info->df_map = NULL;
124 }
125
126 /* Get the dominance frontier of a block. */
127 ir_node **ir_get_dominance_frontier(const ir_node *block)
128 {
129         ir_graph            *irg  = get_irn_irg(block);
130         ir_dom_front_info_t *info = &irg->domfront;
131         return pmap_get(ir_node*, info->df_map, block);
132 }