respect dependency edges in dead code elimination
[libfirm] / ir / common / irtools.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     Some often needed tool-functions
23  * @author    Michael Beck
24  */
25 #include "config.h"
26
27 #include "pset.h"
28
29 #include <stdlib.h>
30 #include "irnode_t.h"
31 #include "irbackedge_t.h"
32 #include "irtools.h"
33 #include "irprintf.h"
34 #include "irpass_t.h"
35 #include "iropt_t.h"
36
37 void firm_clear_link(ir_node *n, void *env)
38 {
39         (void) env;
40         set_irn_link(n, NULL);
41 }
42
43 void firm_clear_node_and_phi_links(ir_node *n, void *env)
44 {
45         (void) env;
46         set_irn_link(n, NULL);
47         if (is_Block(n))
48                 set_Block_phis(n, NULL);
49         else if (is_Phi(n))
50                 set_Phi_next(n, NULL);
51 }
52
53 void firm_clear_block_phis(ir_node *node, void *env)
54 {
55         (void) env;
56         if (is_Block(node)) {
57                 set_Block_phis(node, NULL);
58         } else if (is_Phi(node)) {
59                 set_Phi_next(node, NULL);
60         }
61 }
62
63 void firm_collect_block_phis(ir_node *node, void *env)
64 {
65         (void) env;
66         if (is_Phi(node))
67                 add_Block_phi(get_nodes_block(node), node);
68 }
69
70 void copy_irn_to_irg(ir_node *n, ir_graph *irg)
71 {
72         ir_op *op = get_irn_op(n);
73         ir_graph *old_irg;
74         ir_node *nn = NULL;
75
76         /* do not copy standard nodes */
77         if (op == op_NoMem)
78                 n = get_irg_no_mem(irg);
79         else if (op == op_Block) {
80                 old_irg = get_irn_irg(n);
81
82                 if (n == get_irg_start_block(old_irg))
83                         nn = get_irg_start_block(irg);
84                 else if (n == get_irg_end_block(old_irg))
85                         nn = get_irg_end_block(irg);
86         }
87         else if (op == op_Start)
88                 nn = get_irg_start(irg);
89         else if (op == op_End)
90                 nn = get_irg_end(irg);
91         else if (op == op_Proj) {
92                 old_irg = get_irn_irg(n);
93
94                 if (n == get_irg_initial_exec(old_irg))
95                         nn = get_irg_initial_exec(irg);
96                 else if (n == get_irg_frame(old_irg))
97                         nn = get_irg_frame(irg);
98                 else if (n == get_irg_initial_mem(old_irg))
99                         nn = get_irg_initial_mem(irg);
100                 else if (n == get_irg_args(old_irg))
101                         nn = get_irg_args(irg);
102         }
103
104         if (nn) {
105                 set_irn_link(n, nn);
106                 return;
107         }
108
109         nn = new_ir_node(get_irn_dbg_info(n),
110                          irg,
111                          NULL,            /* no block yet, will be set later */
112                          op,
113                          get_irn_mode(n),
114                          get_irn_arity(n),
115                          get_irn_in(n) + 1);
116
117
118         /* Copy the attributes.  These might point to additional data.  If this
119            was allocated on the old obstack the pointers now are dangling.  This
120            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
121         copy_node_attr(irg, n, nn);
122         set_irn_link(n, nn);
123
124         /* fix the irg for nodes containing a reference to it */
125         if (ir_has_irg_ref(nn)) {
126                 nn->attr.block.irg.irg = irg;
127         }
128 }
129
130 ir_node *irn_copy_into_irg(const ir_node *node, ir_graph *irg)
131 {
132         ir_node  *block = NULL;
133         ir_op    *op    = get_irn_op(node);
134         int       arity = get_irn_arity(node);
135         dbg_info *dbgi  = get_irn_dbg_info(node);
136         ir_mode  *mode  = get_irn_mode(node);
137         ir_node  *res;
138         int       n_deps;
139         int       i;
140
141         if (op != op_Block)
142                 block = get_nodes_block(node);
143
144         if (op->opar == oparity_dynamic) {
145                 int i;
146                 res = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
147                 for (i = 0; i < arity; ++i) {
148                         ir_node *in = get_irn_n(node, i);
149                         add_irn_n(res, in);
150                 }
151         } else {
152                 ir_node **ins = get_irn_in(node)+1;
153                 res = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
154         }
155
156         /* copy the attributes */
157         copy_node_attr(irg, node, res);
158
159         /* duplicate dependency edges */
160         n_deps = get_irn_deps(node);
161         for (i = 0; i < n_deps; ++i) {
162                 ir_node *dep = get_irn_dep(node, i);
163                 add_irn_dep(res, dep);
164         }
165
166         return res;
167 }
168
169 ir_node *exact_copy(const ir_node *node)
170 {
171         return irn_copy_into_irg(node, get_irn_irg(node));
172 }
173
174 static ir_node *get_new_node(const ir_node *old_node)
175 {
176         return (ir_node*) get_irn_link(old_node);
177 }
178
179 void irn_rewire_inputs(ir_node *node)
180 {
181         ir_node *new_node;
182         int      arity;
183         int      n_deps;
184         int      i;
185
186         new_node = get_new_node(node);
187
188         if (!is_Block(node)) {
189                 ir_node *block     = get_nodes_block(node);
190                 ir_node *new_block = get_new_node(block);
191                 set_nodes_block(new_node, new_block);
192         }
193
194         arity = get_irn_arity(new_node);
195         for (i = 0; i < arity; ++i) {
196                 ir_node *in     = get_irn_n(node, i);
197                 ir_node *new_in = get_new_node(in);
198                 set_irn_n(new_node, i, new_in);
199         }
200
201         n_deps = get_irn_deps(new_node);
202         for (i = 0; i < n_deps; ++i) {
203                 ir_node *dep     = get_irn_dep(node, i);
204                 ir_node *new_dep = get_new_node(dep);
205                 set_irn_dep(new_node, i, new_dep);
206         }
207
208         /* Now the new node is complete. We can add it to the hash table for CSE. */
209         add_identities(new_node);
210 }
211
212 void firm_pset_dump(pset *set)
213 {
214         void *obj;
215
216         foreach_pset(set, void*, obj) {
217                 ir_fprintf(stderr, "%+F\n", obj);
218         }
219 }