fb80a796e857f509dff24e67bf5400a046bea4a0
[libfirm] / ir / ir / irgopt.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Author: Christian Schaefer
5 **
6 **  dead node elemination
7 **  walks one time through the whole graph and copies it into another graph,
8 **  so unreachable nodes will be lost.
9 */
10
11 # include "irgopt.h"
12 # include "irnode.h"
13 # include "iropt.h"
14 # include "irgwalk.h"
15 # include "irgraph.h"
16 # include "ircons.h"
17
18 /********************************************************************/
19 /* apply optimizations of iropt to all nodes.                       */
20 void
21 optimize_in_place_wrapper (ir_node *n, void *env) {
22   int i;
23   ir_node *optimized;
24
25   /* optimize all sons after recursion, i.e., the sons' sons are
26      optimized already. */
27   for (i = -1; i < get_irn_arity(n); i++) {
28     optimized = optimize_in_place(get_irn_n(n, i));
29     set_irn_n(n, i, optimized);
30   }
31 }
32
33
34 void
35 local_optimize_graph (ir_graph *irg) {
36   ir_graph *rem = current_ir_graph;
37   current_ir_graph = irg;
38
39   /* walk over the graph */
40   irg_walk(irg->end, NULL, optimize_in_place_wrapper, NULL);
41
42   current_ir_graph = rem;
43 }
44
45 /********************************************************************/
46 /* Routines for dead node elimination / copying garbage collection  */
47 /* of the obstack.                                                  */
48
49 /* Remeber the new node in the old node,
50    by using a field that all nodes have. */
51 void *
52 set_new_node (ir_node *old, ir_node *new)
53 {
54   old->in[0] = new;
55   return old;
56 }
57
58 /* Get this new node, before the old node is forgotton.*/
59 ir_node *
60 get_new_node (ir_node * n)
61 {
62   ir_node *new;
63   new = n->in[0];
64   assert(new);
65
66   return n->in[0];
67
68 }
69
70 /* Create this node on a new obstack. */
71 void
72 copy_node (ir_node *n, void *env) {
73   ir_node *res = NULL;
74   ir_node *a = NULL;
75   ir_node *b = NULL;
76   int i;
77
78   assert (n);
79
80   if (is_binop(n)) {
81     a = get_binop_left(n);
82     b = get_binop_right(n);
83   } else if (is_unop(n)) {
84     a = get_unop_op(n);
85   }
86
87   switch (get_irn_opcode(n)) {
88   case iro_Block:
89     {
90       ir_node **in = get_Block_cfgpred_arr(n);
91       for (i = 0; i < get_Block_n_cfgpreds(n); i++)
92         set_Block_cfgpred(n, i, get_new_node(get_Block_cfgpred(n, i)));
93       res = new_r_Block (current_ir_graph, get_Block_n_cfgpreds(n), in);
94     }
95     break;
96   case iro_Start:
97     res = new_r_Start (current_ir_graph, get_new_node(get_nodes_Block(n)));
98     break;
99   case iro_End:
100     res = new_r_End (current_ir_graph, get_new_node(n));
101     current_ir_graph -> end = res;
102     current_ir_graph -> end_block = get_new_node(get_nodes_Block(n));
103     break;
104   case iro_Jmp:
105     res = new_r_Jmp (current_ir_graph, get_new_node(n));
106     break;
107   case iro_Cond:
108     res = new_r_Cond (current_ir_graph, get_new_node(n),
109                       get_Cond_selector(n));
110     break;
111   case iro_Return:
112     {
113       ir_node **in ;
114       in = get_Return_res_arr(n);
115       for (i = 0; i < get_Return_n_res(n); i++)
116         set_Return_res(n, i, get_new_node(get_Return_res(n, i)));
117       res = new_r_Return (current_ir_graph, get_new_node(n),
118                           get_Return_mem (n), get_Return_n_res(n), in);
119     }
120     break;
121   case iro_Raise:
122     res = new_r_Raise (current_ir_graph, get_new_node(n),
123                        get_Raise_mem(n), get_Raise_exo_ptr(n));
124     break;
125   case iro_Const:
126     res = new_r_Const (current_ir_graph, get_new_node(n),
127                        get_irn_mode(n), get_Const_tarval(n));
128     break;
129   case iro_SymConst:
130     {
131       type_or_id *value = NULL;
132
133       if ((get_SymConst_kind(n)==type_tag) || (get_SymConst_kind(n)==size))
134         {
135
136            value = (type_or_id *) get_SymConst_type(n);
137         }
138       else
139         {
140           if (get_SymConst_kind(n)==linkage_ptr_info)
141           {
142             value = (type_or_id *) get_SymConst_ptrinfo(n);
143           }
144         }
145     res = new_r_SymConst (current_ir_graph, get_new_node(n), value,
146                           get_SymConst_kind (n));
147     }
148     break;
149   case iro_Sel:
150     {
151       ir_node **in = get_Sel_index_arr(n);
152       res = new_r_Sel (current_ir_graph, get_new_node(n),
153                        get_Sel_mem(n), get_Sel_ptr(n), get_Sel_n_index(n),
154                        in, get_Sel_entity(n));
155     }
156     break;
157   case  iro_Call:
158     {
159       ir_node **in = get_Call_param_arr(n);
160       res = new_r_Call (current_ir_graph, get_new_node(n), get_Call_mem(n),
161                         get_Call_ptr(n), get_Call_arity(n),
162                         in, get_Call_type (n));
163     }
164     break;
165   case iro_Add:
166     res = new_r_Add (current_ir_graph, get_new_node(n),
167                      get_new_node(a), get_new_node(b), get_irn_mode(n));
168     break;
169   case iro_Sub:
170     {
171       ir_node *temp_node;
172       temp_node = get_nodes_Block(n);
173       res = new_r_Sub (current_ir_graph, get_new_node(temp_node),
174                        get_new_node(a), get_new_node(b), get_irn_mode(n));
175     }
176     break;
177   case iro_Minus:
178     res = new_r_Minus (current_ir_graph, get_new_node(n), get_new_node(a),
179                        get_irn_mode(n));
180     break;
181   case iro_Mul:
182     res = new_r_Mul (current_ir_graph, get_new_node(n), get_new_node(a),
183                        get_new_node(b), get_irn_mode(n));
184     break;
185   case iro_Quot:
186     res = new_r_Quot (current_ir_graph, get_new_node(n), get_Quot_mem (n),
187                       get_new_node(a), get_new_node(b));
188     break;
189   case iro_DivMod:
190     res = new_r_DivMod (current_ir_graph, get_new_node(n), get_DivMod_mem(n),
191                         get_new_node(a), get_new_node(b));
192     break;
193   case iro_Div:
194     res = new_r_Div (current_ir_graph, get_new_node(n), get_Div_mem(n),
195                      get_new_node(a), get_new_node(b));
196     break;
197   case iro_Mod:
198     res = new_r_Mod (current_ir_graph, get_new_node(n), get_Mod_mem(n),
199                      get_new_node(a), get_new_node(b));
200     break;
201   case iro_Abs:
202     res = new_r_Abs (current_ir_graph, get_new_node(n), get_Abs_op(n),
203                      get_irn_mode(n));
204     break;
205   case iro_And:
206     res = new_r_And (current_ir_graph, get_new_node(n), get_new_node(a),
207                      get_new_node(b), get_irn_mode(n));
208     break;
209   case iro_Or:
210     res = new_r_Or (current_ir_graph, get_new_node(n), get_new_node(a),
211                     get_new_node(b), get_irn_mode(n));
212     break;
213   case iro_Eor:
214     res = new_r_Eor (current_ir_graph, get_new_node(n), get_new_node(a),
215                      get_new_node(b), get_irn_mode(n));
216     break;
217   case iro_Not:
218     res = new_r_Not (current_ir_graph, get_new_node(n), get_Not_op(n),
219                      get_irn_mode(n));
220     break;
221   case iro_Cmp:
222     res = new_r_Cmp (current_ir_graph, get_new_node(n), get_Cmp_left(n),
223                      get_Cmp_right(n));
224     break;
225   case iro_Shl:
226     res = new_r_Shl (current_ir_graph, get_new_node(n), get_Shl_left(n),
227                      get_Shl_right(n), get_irn_mode(n));
228     break;
229   case iro_Shr:
230     res = new_r_Shr (current_ir_graph, get_new_node(n), get_Shr_left(n),
231                      get_Shr_right(n), get_irn_mode(n));
232     break;
233   case iro_Shrs:
234     res = new_r_Shrs (current_ir_graph, get_new_node(n), get_Shrs_left(n),
235                       get_Shrs_right(n), get_irn_mode(n));
236     break;
237   case iro_Rot:
238     res = new_r_Rot (current_ir_graph, get_new_node(n), get_Rot_left(n),
239                      get_Rot_right(n), get_irn_mode(n));
240     break;
241   case iro_Conv:
242     res = new_r_Conv (current_ir_graph, get_new_node(n), get_Conv_op(n),
243                      get_irn_mode(n));
244     break;
245   case iro_Phi:
246     {
247       ir_node **in = get_Phi_preds_arr(n);
248       res = new_r_Phi (current_ir_graph, get_new_node(n),
249                        get_Phi_n_preds(n), in, get_irn_mode(n));
250     }
251     break;
252   case iro_Load:
253     res = new_r_Load (current_ir_graph, get_new_node(n), get_Load_mem(n),
254                       get_Load_ptr(n));
255     break;
256   case iro_Store:
257     res = new_r_Store (current_ir_graph, get_new_node(n), get_Store_mem(n),
258                        get_Store_ptr(n), get_Store_value(n));
259     break;
260   case iro_Alloc:
261     res = new_r_Alloc (current_ir_graph, get_new_node(n),
262                        get_Alloc_mem(n), get_Alloc_size(n),
263                        get_Alloc_type(n), get_Alloc_where(n));
264
265     break;
266   case iro_Free:
267     res = new_r_Free (current_ir_graph, get_new_node(n),
268                       get_Free_mem(n), get_Free_ptr(n),
269                       get_Free_size(n), get_Free_type(n));
270     break;
271   case iro_Sync:
272     {
273       ir_node **in = get_Sync_preds_arr(n);
274       res = new_r_Sync (current_ir_graph, get_new_node(n),
275                         get_Sync_n_preds(n), in);
276     }
277     break;
278   case iro_Proj:
279     res = new_r_Proj (current_ir_graph, get_new_node(get_nodes_Block(n)),
280                       get_new_node(get_Proj_pred(n)), get_irn_mode(n),
281                       get_Proj_proj(n));
282     break;
283   case iro_Tuple:
284     {
285       ir_node **in = get_Tuple_preds_arr(n);
286       res = new_r_Tuple (current_ir_graph, get_new_node(n),
287                          get_Tuple_n_preds(n), in);
288     }
289     break;
290   case iro_Id:
291     res = new_r_Id (current_ir_graph, get_new_node(n),
292                       get_Id_pred(n), get_irn_mode(n));
293     break;
294   case iro_Bad:
295     res = new_r_Bad (get_new_node(n));
296     break;
297   }
298   set_new_node(n, res);
299 }
300
301
302 void
303 dead_node_elimination(ir_graph *irg) {
304   struct obstack *graveyard_obst=NULL;
305   struct obstack *rebirth_obst;
306
307   ir_node *old_node, *new_node;
308   ir_graph *rem = current_ir_graph;
309   current_ir_graph = irg;
310
311   if (get_opt_dead_node_elimination()) {
312
313     /* A quiet place, where the old obstack can rest in peace,
314        until it will be cremated. */
315     graveyard_obst = irg->obst;
316
317     /* A new obstack, where the reachable nodes will be copied to. */
318     rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
319     current_ir_graph->obst = rebirth_obst;
320     obstack_init (current_ir_graph->obst);
321
322     /* Walks the graph once, and at the recursive way do the copy thing.
323        all reachable nodes will be copied to a new obstack. */
324
325     /*CS*/
326     printf("Before starting the DEAD NODE ELIMINATION !\n");
327
328     old_node = irg->start_block;
329     new_node = new_r_Block (current_ir_graph, 0, NULL);
330     irg->start_block = new_node;                       ;
331     set_new_node (old_node, new_node);
332     set_irn_visited (new_node, get_irg_visited(current_ir_graph)+1);
333     /*CS  Start node und alle Proj nodes muessen hier per hand eingetragen
334        werden! */
335
336     irg_walk(irg->end, NULL, copy_node, NULL);
337     /*CS*/
338     printf("After the DEAD NODE ELIMINATION !\n");
339
340     /* Free memory from old unoptimized obstack */
341     xfree (graveyard_obst);
342   }
343
344   /* Free memory from old unoptimized obstack */
345   xfree (graveyard_obst);
346
347   current_ir_graph = rem;
348 }