irgopt.c 6.05 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
24
25
/**
 * @file
 * @brief    Optimizations for a whole ir graph, i.e., a procedure.
 * @author   Christian Schaefer, Goetz Lindenmaier, Sebastian Felis,
 *           Michael Beck
 * @version  $Id$
Götz Lindenmaier's avatar
Götz Lindenmaier committed
26
 */
Boris Boesler's avatar
added    
Boris Boesler committed
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
Boris Boesler's avatar
added    
Boris Boesler committed
29
30
#endif

31
32
33
34
35
#include <assert.h>

#include "irnode_t.h"
#include "irgraph_t.h"

36
#include "iroptimize.h"
37
38
39
40
41
#include "iropt_t.h"
#include "irgopt.h"
#include "irgmod.h"
#include "irgwalk.h"

Michael Beck's avatar
Michael Beck committed
42
#include "adt/pdeq.h"
43

44
#include "irflag_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
45
#include "iredges_t.h"
46
#include "irtools.h"
47

Michael Beck's avatar
Michael Beck committed
48
/*------------------------------------------------------------------*/
Götz Lindenmaier's avatar
Götz Lindenmaier committed
49
/* apply optimizations of iropt to all nodes.                       */
Michael Beck's avatar
Michael Beck committed
50
/*------------------------------------------------------------------*/
Götz Lindenmaier's avatar
Götz Lindenmaier committed
51

52
53
54
55
/**
 * A wrapper around optimize_inplace_2() to be called from a walker.
 */
static void optimize_in_place_wrapper (ir_node *n, void *env) {
Michael Beck's avatar
Michael Beck committed
56
	ir_node *optimized = optimize_in_place_2(n);
57
58
59
	(void) env;

	if (optimized != n) {
60
		exchange(n, optimized);
61
	}
62
63
}

Michael Beck's avatar
Michael Beck committed
64
65
66
67
68
69
70
71
/**
 * Do local optimizations for a node.
 *
 * @param n  the IR-node where to start. Typically the End node
 *           of a graph
 *
 * @note current_ir_graph must be set
 */
72
static INLINE void do_local_optimize(ir_node *n) {
Michael Beck's avatar
Michael Beck committed
73
74
	/* Handle graph state */
	assert(get_irg_phase_state(current_ir_graph) != phase_building);
75

Michael Beck's avatar
Michael Beck committed
76
	if (get_opt_global_cse())
77
		set_irg_pinned(current_ir_graph, op_pin_state_floats);
Michael Beck's avatar
Michael Beck committed
78
79
80
	set_irg_outs_inconsistent(current_ir_graph);
	set_irg_doms_inconsistent(current_ir_graph);
	set_irg_loopinfo_inconsistent(current_ir_graph);
81

Michael Beck's avatar
Michael Beck committed
82
83
84
	/* Clean the value_table in irg for the CSE. */
	del_identities(current_ir_graph->value_table);
	current_ir_graph->value_table = new_identities();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
85

Michael Beck's avatar
Michael Beck committed
86
87
	/* walk over the graph */
	irg_walk(n, firm_clear_link, optimize_in_place_wrapper, NULL);
88
89
}

Michael Beck's avatar
Michael Beck committed
90
/* Applies local optimizations (see iropt.h) to all nodes reachable from node n */
91
void local_optimize_node(ir_node *n) {
Michael Beck's avatar
Michael Beck committed
92
93
	ir_graph *rem = current_ir_graph;
	current_ir_graph = get_irn_irg(n);
94

Michael Beck's avatar
Michael Beck committed
95
	do_local_optimize(n);
96

Michael Beck's avatar
Michael Beck committed
97
	current_ir_graph = rem;
98
99
}

100
101
102
/**
 * Block-Walker: uses dominance depth to mark dead blocks.
 */
Michael Beck's avatar
Michael Beck committed
103
static void kill_dead_blocks(ir_node *block, void *env) {
104
105
	(void) env;

Michael Beck's avatar
Michael Beck committed
106
107
108
109
110
111
112
	if (get_Block_dom_depth(block) < 0) {
		/*
		 * Note that the new dominance code correctly handles
		 * the End block, i.e. it is always reachable from Start
		 */
		set_Block_dead(block);
	}
113
114
}

Michael Beck's avatar
Michael Beck committed
115
116
/* Applies local optimizations (see iropt.h) to all nodes reachable from node n. */
void local_optimize_graph(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
117
118
	ir_graph *rem = current_ir_graph;
	current_ir_graph = irg;
119

Michael Beck's avatar
Michael Beck committed
120
121
	if (get_irg_dom_state(irg) == dom_consistent)
		irg_block_walk_graph(irg, NULL, kill_dead_blocks, NULL);
122

Michael Beck's avatar
Michael Beck committed
123
	do_local_optimize(get_irg_end(irg));
Christian Schäfer's avatar
Christian Schäfer committed
124

Michael Beck's avatar
Michael Beck committed
125
	current_ir_graph = rem;
Christian Schäfer's avatar
Christian Schäfer committed
126
127
}

Michael Beck's avatar
Michael Beck committed
128
129
130
131
132
/**
 * Enqueue all users of a node to a wait queue.
 * Handles mode_T nodes.
 */
static void enqueue_users(ir_node *n, pdeq *waitq) {
Michael Beck's avatar
Michael Beck committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	const ir_edge_t *edge;

	foreach_out_edge(n, edge) {
		ir_node *succ = get_edge_src_irn(edge);

		if (get_irn_link(succ) != waitq) {
			pdeq_putr(waitq, succ);
			set_irn_link(succ, waitq);
		}
		if (get_irn_mode(succ) == mode_T) {
		/* A mode_T node has Proj's. Because most optimizations
			run on the Proj's we have to enqueue them also. */
			enqueue_users(succ, waitq);
		}
	}
Michael Beck's avatar
Michael Beck committed
148
149
}

150
151
/**
 * Data flow optimization walker.
Michael Beck's avatar
Michael Beck committed
152
153
 * Optimizes all nodes and enqueue it's users
 * if done.
154
155
 */
static void opt_walker(ir_node *n, void *env) {
Michael Beck's avatar
Michael Beck committed
156
157
	pdeq *waitq = env;
	ir_node *optimized;
158

159
160
161
162
163
164
	optimized = optimize_in_place_2(n);
	set_irn_link(optimized, NULL);

	if (optimized != n) {
		enqueue_users(n, waitq);
		exchange(n, optimized);
Michael Beck's avatar
Michael Beck committed
165
	}
166
167
}

Michael Beck's avatar
Michael Beck committed
168
/* Applies local optimizations to all nodes in the graph until fixpoint. */
169
void optimize_graph_df(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
170
171
	pdeq     *waitq = new_pdeq();
	ir_graph *rem = current_ir_graph;
172
	ir_node  *end;
173
	int      i, state, n_ka;
Michael Beck's avatar
Michael Beck committed
174

Michael Beck's avatar
Michael Beck committed
175
	current_ir_graph = irg;
176

177
	state = edges_assure(irg);
178

Michael Beck's avatar
Michael Beck committed
179
180
	if (get_opt_global_cse())
		set_irg_pinned(current_ir_graph, op_pin_state_floats);
181

Michael Beck's avatar
Michael Beck committed
182
183
184
	/* Clean the value_table in irg for the CSE. */
	del_identities(irg->value_table);
	irg->value_table = new_identities();
185

Michael Beck's avatar
Michael Beck committed
186
187
	if (get_irg_dom_state(irg) == dom_consistent)
		irg_block_walk_graph(irg, NULL, kill_dead_blocks, NULL);
188

Michael Beck's avatar
Michael Beck committed
189
190
191
192
	/* invalidate info */
	set_irg_outs_inconsistent(irg);
	set_irg_doms_inconsistent(irg);
	set_irg_loopinfo_inconsistent(irg);
193

Michael Beck's avatar
Michael Beck committed
194
	set_using_irn_link(irg);
195

196
197
198
	end  = get_irg_end(irg);
	n_ka = get_End_n_keepalives(end);

199
200
201
	/* walk over the graph, but don't touch keep-alives */
	irg_walk(get_irg_end_block(irg), NULL, opt_walker, waitq);

202
203
204
205
206
207
208
209
210
211
	/*
	 * Optimize keep-alives by removing superfluous ones.
	 * Beware: the last transformation might add new keep-alives
	 * that keep blocks that are where visited! So, check only the
	 * "old" keep-alives, not the new ones!
	 *
	 * FIXME: it might be better to completely remove this
	 * optimization here ...
	 */
	for (i = n_ka - 1; i >= 0; --i) {
212
213
214
215
216
217
218
219
220
221
		ir_node *ka = get_End_keepalive(end, i);

		if (irn_visited(ka) && !is_irn_keep(ka)) {
			/* this node can be regularly visited, no need to keep it */
			set_End_keepalive(end, i, get_irg_bad(irg));
		}
	}
	/* now walk again and visit all not yet visited nodes */
	set_irg_visited(current_ir_graph, get_irg_visited(irg) - 1);
	irg_walk(get_irg_end(irg), NULL, opt_walker, waitq);
222

Michael Beck's avatar
Michael Beck committed
223
224
225
226
227
228
	/* finish the wait queue */
	while (! pdeq_empty(waitq)) {
		ir_node *n = pdeq_getl(waitq);
		if (! is_Bad(n))
			opt_walker(n, waitq);
	}
229

Michael Beck's avatar
Michael Beck committed
230
	del_pdeq(waitq);
231

Michael Beck's avatar
Michael Beck committed
232
	clear_using_irn_link(irg);
233

Michael Beck's avatar
Michael Beck committed
234
235
	if (! state)
		edges_deactivate(irg);
Michael Beck's avatar
Michael Beck committed
236

Michael Beck's avatar
Michael Beck committed
237
	current_ir_graph = rem;
238
}