Remove duplicate calls to register_node_cmp_func().
[libfirm] / ir / ir / unreachable.c
1 /*
2  * Copyright (C) 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  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE.
14  */
15
16 /**
17  * @brief    Remove unreachable code
18  * @author   Andreas Zwinkau
19  *
20  * This is done by elminiating all edges into the unreachable code. So that
21  * after that the unreachable code should be dead.
22  */
23 #include "config.h"
24
25 #include "irgopt.h"
26
27 #include <assert.h>
28 #include <stdbool.h>
29
30 #include "irnode_t.h"
31 #include "irgopt.h"
32 #include "irgmod.h"
33 #include "irgwalk.h"
34 #include "irtools.h"
35
36 static bool is_block_unreachable(ir_node *block)
37 {
38         return get_Block_dom_depth(block) < 0;
39 }
40
41 /**
42  * Eliminate block- and phi-inputs pointing to unreachable code
43  */
44 static void unreachable_to_bad(ir_node *node, void *env)
45 {
46         bool *changed = (bool *)env;
47
48         if (is_Block(node)) {
49                 ir_graph *irg;
50                 int       arity;
51                 int       i;
52                 /* optimisation: we do not have to do anything inside the unreachable
53                  * code */
54                 if (is_block_unreachable(node))
55                         return;
56
57                 arity = get_irn_arity(node);
58                 irg   = get_irn_irg(node);
59                 for (i = 0; i < arity; ++i) {
60                         ir_node *pred = get_Block_cfgpred(node, i);
61                         if (is_Bad(pred) || !is_block_unreachable(get_nodes_block(pred)))
62                                 continue;
63                         set_irn_n(node, i, new_r_Bad(irg, mode_X));
64                         *changed = true;
65                 }
66         } else if (is_Phi(node)) {
67                 ir_node  *block = get_nodes_block(node);
68                 int       arity;
69                 int       i;
70                 ir_graph *irg;
71                 /* optimisation: we do not have to do anything inside the unreachable
72                  * code */
73                 if (is_block_unreachable(block))
74                         return;
75
76                 irg   = get_irn_irg(node);
77                 arity = get_irn_arity(node);
78                 for (i = 0; i < arity; ++i) {
79                         ir_node *block_pred;
80                         ir_node *phi_pred = get_irn_n(node, i);
81                         if (is_Bad(phi_pred))
82                                 continue;
83                         block_pred = get_Block_cfgpred(block, i);
84                         if (!is_Bad(block_pred) && !is_block_unreachable(get_nodes_block(block_pred)))
85                                 continue;
86
87                         set_irn_n(node, i, new_r_Bad(irg, get_irn_mode(node)));
88                         *changed = true;
89                 }
90         }
91 }
92
93 /**
94  * remove kept nodes in unreachable blocks
95  */
96 static void remove_unreachable_keeps(ir_graph *irg)
97 {
98         ir_node  *end       = get_irg_end(irg);
99         int       arity     = get_irn_arity(end);
100         ir_node **new_in    = XMALLOCN(ir_node*, arity);
101         int       new_arity = 0;
102         int       i;
103
104         for (i = 0; i < arity; ++i) {
105                 ir_node *ka    = get_End_keepalive(end, i);
106                 ir_node *block = is_Block(ka) ? ka : get_nodes_block(ka);
107                 if (is_block_unreachable(block))
108                         continue;
109                 new_in[new_arity++] = ka;
110         }
111         if (new_arity != arity)
112                 set_End_keepalives(end, new_arity, new_in);
113         free(new_in);
114 }
115
116 void remove_unreachable_code(ir_graph *irg)
117 {
118         bool changed = false;
119
120         assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
121
122         irg_walk_graph(irg, unreachable_to_bad, NULL, &changed);
123         remove_unreachable_keeps(irg);
124
125         confirm_irg_properties(irg, changed
126                 ? IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
127                 | IR_GRAPH_PROPERTY_NO_TUPLES
128                 | IR_GRAPH_PROPERTY_ONE_RETURN
129                 | IR_GRAPH_PROPERTY_MANY_RETURNS
130                 : IR_GRAPH_PROPERTIES_ALL);
131         add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE);
132 }