becopyilp: Do not advertise the switch to dump the solution, because this is not...
[libfirm] / ir / ana / domfront.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Algorithms for computing dominance frontiers.
9  * @author      Sebastian Hack, Daniel Grund
10  * @date        04.05.2005
11  */
12 #include "config.h"
13
14 #include "obst.h"
15 #include "pmap.h"
16 #include "pdeq.h"
17 #include "irdom.h"
18 #include "array.h"
19 #include "irgraph.h"
20 #include "iredges_t.h"
21 #include "irnodeset.h"
22
23 /**
24  * A wrapper for get_Block_idom.
25  * This function returns the block itself, if the block is the start
26  * block. Returning NULL would make any != comparison true which
27  * suggests, that the start block is dominated by some other node.
28  * @param bl The block.
29  * @return The immediate dominator of the block.
30  */
31 static inline ir_node *get_idom(ir_node *bl)
32 {
33         ir_node *idom = get_Block_idom(bl);
34         return idom == NULL ? bl : idom;
35 }
36
37 /**
38  * Compute the dominance frontier for a given block.
39  *
40  * @param blk   the block where the calculation starts
41  *
42  * @return the list of all blocks in the dominance frontier of blk
43  */
44 static ir_node **compute_df(ir_node *blk, ir_dom_front_info_t *info)
45 {
46         ir_node *c;
47         ir_node **df_list = NEW_ARR_F(ir_node *, 0);
48
49         /* Add local dominance frontiers */
50         foreach_block_succ(blk, edge) {
51                 ir_node *y = get_edge_src_irn(edge);
52
53                 if (get_idom(y) != blk) {
54                         ARR_APP1(ir_node *, df_list, y);
55                 }
56         }
57
58         /*
59          * Go recursively down the dominance tree and add all blocks
60          * into the dominance frontiers of the children, which are not
61          * dominated by the given block.
62          */
63         for (c = get_Block_dominated_first(blk); c; c = get_Block_dominated_next(c)) {
64                 size_t i;
65                 ir_node **df_c_list = compute_df(c, info);
66
67                 for (i = ARR_LEN(df_c_list); i > 0;) {
68                         ir_node *w = df_c_list[--i];
69                         if (get_idom(w) != blk)
70                                 ARR_APP1(ir_node *, df_list, w);
71                 }
72         }
73
74         /* now copy the flexible array to the obstack */
75         ir_node **const df = DUP_ARR_D(ir_node*, &info->obst, df_list);
76         DEL_ARR_F(df_list);
77
78         pmap_insert(info->df_map, blk, df);
79         return df;
80 }
81
82 void ir_compute_dominance_frontiers(ir_graph *irg)
83 {
84         ir_dom_front_info_t *info = &irg->domfront;
85
86         assure_edges(irg);
87         obstack_init(&info->obst);
88         info->df_map = pmap_create();
89         assure_doms(irg);
90         compute_df(get_irg_start_block(irg), info);
91
92         add_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE_FRONTIERS);
93 }
94
95 void ir_free_dominance_frontiers(ir_graph *irg)
96 {
97         clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE_FRONTIERS);
98
99         ir_dom_front_info_t *info = &irg->domfront;
100         if (info->df_map == NULL)
101                 return;
102
103         obstack_free(&info->obst, NULL);
104         pmap_destroy(info->df_map);
105         info->df_map = NULL;
106 }
107
108 /* Get the dominance frontier of a block. */
109 ir_node **ir_get_dominance_frontier(const ir_node *block)
110 {
111         ir_graph            *irg  = get_irn_irg(block);
112         ir_dom_front_info_t *info = &irg->domfront;
113         return pmap_get(ir_node*, info->df_map, block);
114 }