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