irgmod.c 4.55 KB
Newer Older
Götz Lindenmaier's avatar
Götz Lindenmaier committed
1
2
3
4
5
6
7
8
9
10
11
/*
 * Project:     libFIRM
 * File name:   ir/ir/irgmod.h
 * Purpose:     Support for ir graph modification.
 * Author:      Martin Trapp, Christian Schaefer
 * Modified by: Goetz Lindenmaier
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2003 Universitt Karlsruhe
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */
Boris Boesler's avatar
Boris Boesler committed
12

Boris Boesler's avatar
added    
Boris Boesler committed
13
14
15
16
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

17
# include "irvrfy.h"
18
# include "irflag_t.h"
19
# include "irgwalk.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
20
# include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
21
# include "irgraph_t.h"
Christian Schäfer's avatar
Christian Schäfer committed
22
# include "irgmod.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
23
# include "array.h"
24
# include "ircons.h"
Christian Schäfer's avatar
Christian Schäfer committed
25

Götz Lindenmaier's avatar
Götz Lindenmaier committed
26
27
28
29
/* Turns a node into a "useless" Tuple.  The Tuple just forms a tuple
   from several inputs.
   This is useful if a node returning a tuple is removed, but the Projs
   extracting values from the tuple are not available. */
Christian Schäfer's avatar
Christian Schäfer committed
30
31
32
33
34
35
36
37
void
turn_into_tuple (ir_node *node, int arity)
{
  assert(node);
  set_irn_op(node, op_Tuple);
  if (get_irn_arity(node) == arity) {
    /* keep old array */
  } else {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
38
39
    /* Allocate new array, don't free old in_array, it's on the obstack. */
    ir_node *block = get_nodes_Block(node);
Christian Schäfer's avatar
Christian Schäfer committed
40
    node->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, arity+1);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
41
    set_nodes_Block(node, block);
Christian Schäfer's avatar
Christian Schäfer committed
42
43
44
45
46
47
  }
}

/* Insert irnode `new' in place of irnode `old'
   Since `new' may be bigger than `old' replace `old'
   by an op_Id which is smaller than everything */
48
INLINE void
Götz Lindenmaier's avatar
Götz Lindenmaier committed
49
exchange (ir_node *old, ir_node *nw)
Christian Schäfer's avatar
Christian Schäfer committed
50
{
51
52
  ir_node *block;

53
  assert(get_irn_op(old)->opar != oparity_dynamic);
54
55

  block = old->in[0];
Christian Schäfer's avatar
Christian Schäfer committed
56
57
58
59

  old->op = op_Id;
  old->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 2);
  old->in[0] = block;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
60
  old->in[1] = nw;
Christian Schäfer's avatar
Christian Schäfer committed
61
}
62

63
64
65
/*--------------------------------------------------------------------*/
/*  Functionality for collect_phis                                    */
/*--------------------------------------------------------------------*/
66

67
static void
68
69
70
71
clear_link (ir_node *n, void *env) {
  set_irn_link(n, NULL);
}

72
static void
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
collect (ir_node *n, void *env) {
  ir_node *pred;
  if (get_irn_op(n) == op_Phi) {
    set_irn_link(n, get_irn_link(get_nodes_Block(n)));
    set_irn_link(get_nodes_Block(n), n);
  }
  if (get_irn_op(n) == op_Proj) {
    pred = n;
    while (get_irn_op(pred) == op_Proj)
      pred = get_Proj_pred(pred);
    set_irn_link(n, get_irn_link(pred));
    set_irn_link(pred, n);
  }
}

void collect_phiprojs(ir_graph *irg) {
  ir_graph *rem;

  /* Remember external state of current_ir_graph. */
  rem = current_ir_graph;
  current_ir_graph = irg;

  irg_walk(get_irg_end(current_ir_graph), clear_link, collect, NULL);

  current_ir_graph = rem;
}


101
102
103
/*--------------------------------------------------------------------*/
/*  Functionality for part_block                                      */
/*--------------------------------------------------------------------*/
104

Michael Beck's avatar
Michael Beck committed
105
106
107
108
/**
 * Moves node and all predecessors of node from from_bl to to_bl.
 * Does not move predecessors of Phi nodes (or block nodes).
 */
109
static void move (ir_node *node, ir_node *from_bl, ir_node *to_bl) {
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  int i;
  ir_node *proj, *pred;

  /* move this node */
  set_nodes_Block(node, to_bl);

  /* move its projs */
  if (get_irn_mode(node) == mode_T) {
    proj = get_irn_link(node);
    while (proj) {
      if (get_nodes_Block(proj) == from_bl)
	set_nodes_Block(proj, to_bl);
      proj = get_irn_link(proj);
    }
  }

  /* recursion ... */
  if (get_irn_op(node) == op_Phi) return;

  for (i = 0; i < get_irn_arity(node); i++) {
    pred = get_irn_n(node, i);
    if (get_nodes_Block(pred) == from_bl)
      move(pred, from_bl, to_bl);
  }
}

void part_block(ir_node *node) {
  ir_node *new_block;
  ir_node *old_block;
  ir_node *phi;

141
  /* Turn off optimizations so that blocks are not merged again. */
142
  int rem_opt = get_opt_optimize();
143
144
  set_optimize(0);

145
146
147
148
149
150
151
152
153
  /* Transform the control flow */
  old_block = get_nodes_Block(node);
  new_block = new_Block(get_Block_n_cfgpreds(old_block),
			get_Block_cfgpred_arr(old_block));
  set_irg_current_block(current_ir_graph, new_block);
  {
    ir_node *in[1];
    in[0] = new_Jmp();
    set_irn_in(old_block, 1, in);
154
    irn_vrfy_irg(old_block, current_ir_graph);
155
156
157
158
159
160
161
162
163
164
  }

  /* move node and its predecessors to new_block */
  move(node, old_block, new_block);

  /* move Phi nodes to new_block */
  phi = get_irn_link(old_block);
  set_irn_link(new_block, phi);
  set_irn_link(old_block, NULL);
  while (phi) {
165
166
167
168
    if(get_nodes_Block(phi) == old_block);   /* @@@ inlinening chokes on phis that don't
					       obey this condition.  How do they get into
					       the list??? Example: InterfaceIII */
      set_nodes_Block(phi, new_block);
169
170
    phi = get_irn_link(phi);
  }
171
172

  set_optimize(rem_opt);
173
}