d04dea38be39d0d61032f2dff66da84480d2f290
[libfirm] / ir / ir / irgmod.c
1
2 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
3 ** All rights reserved.
4 **
5 ** Authors: Martin Trapp, Christian Schaefer
6 **
7 ** irgmod: ir graph modification
8 */
9
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13
14 # include "irnode_t.h"
15 # include "irgraph_t.h"
16 # include "irgmod.h"
17 # include "array.h"
18 # include "ircons.h"
19
20 /* Turns a node into a "useless" Tuple.  The Tuple just forms a tuple
21    from several inputs.
22    This is useful if a node returning a tuple is removed, but the Projs
23    extracting values from the tuple are not available. */
24 void
25 turn_into_tuple (ir_node *node, int arity)
26 {
27   assert(node);
28   set_irn_op(node, op_Tuple);
29   if (get_irn_arity(node) == arity) {
30     /* keep old array */
31   } else {
32     /* Allocate new array, don't free old in_array, it's on the obstack. */
33     ir_node *block = get_nodes_Block(node);
34     node->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, arity+1);
35     set_nodes_Block(node, block);
36   }
37 }
38
39 /* Insert irnode `new' in place of irnode `old'
40    Since `new' may be bigger than `old' replace `old'
41    by an op_Id which is smaller than everything */
42 inline void
43 exchange (ir_node *old, ir_node *new)
44 {
45   ir_node *block = old->in[0];
46
47   old->op = op_Id;
48   old->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 2);
49   old->in[0] = block;
50   old->in[1] = new;
51 }
52
53
54 /**********************************************************************/
55 /*  Funcionality for collect_phis                                     */
56 /**********************************************************************/
57
58 void
59 clear_link (ir_node *n, void *env) {
60   set_irn_link(n, NULL);
61 }
62
63 void
64 collect (ir_node *n, void *env) {
65   ir_node *pred;
66   if (get_irn_op(n) == op_Phi) {
67     set_irn_link(n, get_irn_link(get_nodes_Block(n)));
68     set_irn_link(get_nodes_Block(n), n);
69   }
70   if (get_irn_op(n) == op_Proj) {
71     pred = n;
72     while (get_irn_op(pred) == op_Proj)
73       pred = get_Proj_pred(pred);
74     set_irn_link(n, get_irn_link(pred));
75     set_irn_link(pred, n);
76   }
77 }
78
79 void collect_phiprojs(ir_graph *irg) {
80   ir_graph *rem;
81
82   /* Remember external state of current_ir_graph. */
83   rem = current_ir_graph;
84   current_ir_graph = irg;
85
86   irg_walk(get_irg_end(current_ir_graph), clear_link, collect, NULL);
87
88   current_ir_graph = rem;
89 }
90
91
92 /**********************************************************************/
93 /*  Funcionality for part_block                                       */
94 /**********************************************************************/
95
96 /* Moves node and all predecessors of node from from_bl to to_bl.
97    Does not move predecessors of Phi nodes (or block nodes). */
98
99 void move (ir_node *node, ir_node *from_bl, ir_node *to_bl) {
100   int i;
101   ir_node *proj, *pred;
102
103   /* move this node */
104   set_nodes_Block(node, to_bl);
105
106   /* move its projs */
107   if (get_irn_mode(node) == mode_T) {
108     proj = get_irn_link(node);
109     while (proj) {
110       if (get_nodes_Block(proj) == from_bl)
111         set_nodes_Block(proj, to_bl);
112       proj = get_irn_link(proj);
113     }
114   }
115
116   /* recursion ... */
117   if (get_irn_op(node) == op_Phi) return;
118
119   for (i = 0; i < get_irn_arity(node); i++) {
120     pred = get_irn_n(node, i);
121     if (get_nodes_Block(pred) == from_bl)
122       move(pred, from_bl, to_bl);
123   }
124 }
125
126 void part_block(ir_node *node) {
127   ir_node *new_block;
128   ir_node *old_block;
129   ir_node *phi;
130
131   /* Transform the control flow */
132   old_block = get_nodes_Block(node);
133   new_block = new_Block(get_Block_n_cfgpreds(old_block),
134                         get_Block_cfgpred_arr(old_block));
135   set_irg_current_block(current_ir_graph, new_block);
136   {
137     ir_node *in[1];
138     in[0] = new_Jmp();
139     set_irn_in(old_block, 1, in);
140     irn_vrfy(old_block);
141   }
142
143   /* move node and its predecessors to new_block */
144   move(node, old_block, new_block);
145
146   /* move Phi nodes to new_block */
147   phi = get_irn_link(old_block);
148   set_irn_link(new_block, phi);
149   set_irn_link(old_block, NULL);
150   while (phi) {
151     set_nodes_Block(phi, new_block);
152     phi = get_irn_link(phi);
153   }
154 }