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