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