2 * Copyright (C) 1995-2010 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Manager for optimization passes.
23 * @author Michael Beck
30 #include "irgraph_t.h"
37 typedef void (*void_pass_func_irg)(ir_graph *irg);
38 typedef int (*int_pass_func_irg)(ir_graph *irg);
39 typedef void (*void_pass_func)(void);
41 void ir_graph_pass_mgr_add(ir_graph_pass_manager_t *mgr, ir_graph_pass_t *pass)
43 list_add_tail(&pass->list, &mgr->passes);
46 pass->add_to_mgr(pass->context);
49 void ir_prog_pass_mgr_add(ir_prog_pass_manager_t *mgr, ir_prog_pass_t *pass)
51 list_add_tail(&pass->list, &mgr->passes);
54 pass->add_to_mgr(pass->context);
58 * wrapper for running a graph pass manager as a pass on an irprog
61 static int run_wrapper(ir_prog *prog, void *ctx)
63 ir_graph_pass_manager_t *mgr = (ir_graph_pass_manager_t*)ctx;
66 return ir_graph_pass_mgr_run(mgr);
69 int ir_prog_no_verify(ir_prog *prog, void *ctx)
76 void ir_prog_no_dump(ir_prog *prog, void *ctx, unsigned idx)
84 * Term wrapper for a wrapped ir_graph pass manager.
86 static void term_wrapper(void *context)
88 ir_graph_pass_manager_t *mgr = (ir_graph_pass_manager_t*)context;
89 term_graph_pass_mgr(mgr);
93 * Create a wrapper ir_prog pass for an ir_graph manager.
95 static ir_prog_pass_t *create_wrapper_pass(ir_graph_pass_manager_t *graph_mgr)
97 /* create a wrapper pass */
98 ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
100 pass->kind = k_ir_prog_pass;
101 pass->run_on_irprog = run_wrapper;
102 pass->context = graph_mgr;
103 pass->name = graph_mgr->name;
105 /* do not verify nor dump: this is handled by the graph manager */
106 pass->verify_irprog = ir_prog_no_verify;
107 pass->dump_irprog = ir_prog_no_dump;
108 pass->is_wrapper = 1;
110 pass->add_to_mgr = NULL;
111 pass->rem_from_mgr = term_wrapper;
116 void ir_prog_pass_mgr_add_graph_pass(
117 ir_prog_pass_manager_t *mgr, ir_graph_pass_t *pass)
119 ir_graph_pass_manager_t *graph_mgr;
120 ir_prog_pass_t *wrapper;
122 /* check if the last pass is a graph_pass wrapper */
123 if (! list_empty(&mgr->passes)) {
124 wrapper = list_entry(mgr->passes.prev, ir_prog_pass_t, list);
125 if (wrapper->is_wrapper) {
126 graph_mgr = (ir_graph_pass_manager_t*)wrapper->context;
128 ir_graph_pass_mgr_add(graph_mgr, pass);
134 /* not found, create a new wrapper */
135 graph_mgr = new_graph_pass_mgr(
136 "graph_pass_wrapper", mgr->verify_all, mgr->dump_all);
137 graph_mgr->run_idx = mgr->run_idx + mgr->n_passes;
139 ir_graph_pass_mgr_add(graph_mgr, pass);
141 wrapper = create_wrapper_pass(graph_mgr);
142 ir_prog_pass_mgr_add(mgr, wrapper);
145 void ir_prog_pass_mgr_add_graph_mgr(
146 ir_prog_pass_manager_t *mgr, ir_graph_pass_manager_t *graph_mgr)
148 ir_prog_pass_t *pass = create_wrapper_pass(graph_mgr);
151 graph_mgr->dump_all = 1;
153 graph_mgr->verify_all = 1;
154 graph_mgr->run_idx = mgr->n_passes;
156 ir_prog_pass_mgr_add(mgr, pass);
159 int ir_graph_pass_mgr_run(ir_graph_pass_manager_t *mgr)
163 ir_graph *rem = current_ir_graph;
165 /* on all graphs: beware: number of irgs might be changed */
166 for (i = 0; i < get_irp_n_irgs(); ++i) {
167 ir_graph *irg = current_ir_graph = get_irp_irg(i);
168 unsigned idx = mgr->run_idx;
169 /* run every pass on every graph */
170 list_for_each_entry(ir_graph_pass_t, pass, &mgr->passes, list) {
171 int pass_res = pass->run_on_irg(irg, pass->context);
174 /* verify is necessary */
175 if (mgr->verify_all) {
176 if (pass->verify_irg) {
177 pass->verify_irg(irg, pass->context);
184 if (pass->dump_irg) {
185 pass->dump_irg(irg, pass->context, idx);
187 dump_ir_graph(irg, pass->name);
193 current_ir_graph = rem;
198 * Verify all graphs on the given ir_prog.
200 static int irp_verify_irgs(void)
204 size_t n_irgs = get_irp_n_irgs();
206 for (i = 0; i < n_irgs; ++i)
207 res &= irg_verify(get_irp_irg(i), 0);
211 int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr)
215 /* run every pass on every graph */
216 unsigned idx = mgr->run_idx;
217 list_for_each_entry(ir_prog_pass_t, pass, &mgr->passes, list) {
218 int pass_res = pass->run_on_irprog(irp, pass->context);
221 /* verify is necessary */
222 if (mgr->verify_all) {
223 if (pass->verify_irprog) {
224 pass->verify_irprog(irp, pass->context);
231 if (pass->dump_irprog) {
232 pass->dump_irprog(irp, pass->context, idx);
234 dump_all_ir_graphs(pass->name);
237 if (pass->is_wrapper) {
238 ir_graph_pass_manager_t *graph_mgr = (ir_graph_pass_manager_t*)pass->context;
239 idx += graph_mgr->n_passes;
246 ir_graph_pass_manager_t *new_graph_pass_mgr(
247 const char *name, int verify_all, int dump_all)
249 ir_graph_pass_manager_t *res = XMALLOCZ(ir_graph_pass_manager_t);
251 INIT_LIST_HEAD(&res->passes);
252 res->kind = k_ir_graph_pass_mgr;
255 res->verify_all = verify_all != 0;
256 res->dump_all = dump_all != 0;
261 ir_prog_pass_manager_t *new_prog_pass_mgr(
262 const char *name, int verify_all, int dump_all)
264 ir_prog_pass_manager_t *res = XMALLOCZ(ir_prog_pass_manager_t);
266 INIT_LIST_HEAD(&res->passes);
267 res->kind = k_ir_prog_pass_mgr;
270 res->verify_all = verify_all != 0;
271 res->dump_all = dump_all != 0;
276 void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr)
278 list_for_each_entry_safe(ir_graph_pass_t, pass, next, &mgr->passes, list) {
279 if (pass->rem_from_mgr)
280 pass->rem_from_mgr(pass->context);
288 void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr)
290 list_for_each_entry_safe(ir_prog_pass_t, pass, next, &mgr->passes, list) {
291 if (pass->rem_from_mgr)
292 pass->rem_from_mgr(pass->context);
300 void ir_graph_pass_mgr_set_run_idx(
301 ir_graph_pass_manager_t *mgr, unsigned run_idx)
303 mgr->run_idx = run_idx;
306 void ir_prog_pass_mgr_set_run_idx(
307 ir_prog_pass_manager_t *mgr, unsigned run_idx)
309 mgr->run_idx = run_idx;
313 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
315 static int void_graph_wrapper(ir_graph *irg, void *context)
317 void_pass_func_irg function = (void_pass_func_irg)context;
322 ir_graph_pass_t *def_graph_pass(
323 const char *name, void (*function)(ir_graph *irg))
325 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
327 pass->kind = k_ir_graph_pass;
328 pass->run_on_irg = void_graph_wrapper;
329 pass->context = (void*)function;
332 INIT_LIST_HEAD(&pass->list);
338 * Wrapper for running int function(ir_graph *irg) as an ir_graph pass.
340 static int int_graph_wrapper(ir_graph *irg, void *context)
342 int_pass_func_irg function = (int_pass_func_irg)context;
343 return function(irg);
346 ir_graph_pass_t *def_graph_pass_ret(
347 const char *name, int (*function)(ir_graph *irg))
349 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
351 pass->kind = k_ir_graph_pass;
352 pass->run_on_irg = int_graph_wrapper;
353 pass->context = (void*)function;
356 INIT_LIST_HEAD(&pass->list);
361 ir_graph_pass_t *def_graph_pass_constructor(
362 ir_graph_pass_t *pass,
363 const char *name, int (*function)(ir_graph *irg, void *context)) {
365 pass = XMALLOCZ(ir_graph_pass_t);
367 memset(pass, 0, sizeof(ir_graph_pass_t));
368 pass->kind = k_ir_graph_pass;
369 pass->run_on_irg = function;
370 pass->context = pass;
373 INIT_LIST_HEAD(&pass->list);
378 void ir_graph_pass_set_parallel(ir_graph_pass_t *pass, int flag)
380 pass->run_parallel = flag != 0;
384 * Wrapper for running void function(void) as an ir_prog pass.
386 static int void_prog_wrapper(ir_prog *irp, void *context)
388 void_pass_func function = (void_pass_func)context;
395 ir_prog_pass_t *def_prog_pass(
397 void (*function)(void))
399 struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
401 pass->kind = k_ir_prog_pass;
402 pass->run_on_irprog = void_prog_wrapper;
403 pass->context = (void*)function;
406 INIT_LIST_HEAD(&pass->list);
411 ir_prog_pass_t *def_prog_pass_constructor(
412 ir_prog_pass_t *pass,
414 int (*function)(ir_prog *irp, void *context))
417 pass = XMALLOCZ(ir_prog_pass_t);
419 memset(pass, 0, sizeof(ir_prog_pass_t));
421 pass->kind = k_ir_prog_pass;
422 pass->run_on_irprog = function;
423 pass->context = pass;
426 INIT_LIST_HEAD(&pass->list);
431 typedef struct pass_t {
434 void (*function)(void *context);
438 * Wrapper for the call_function pass.
440 static int call_function_wrapper(ir_prog *irp, void *context)
442 pass_t *pass = (pass_t*)context;
445 pass->function(pass->context);
449 ir_prog_pass_t *call_function_pass(
450 const char *name, void (*function)(void *context), void *context) {
451 struct pass_t *pass = XMALLOCZ(struct pass_t);
453 def_prog_pass_constructor(
454 &pass->pass, name ? name : "set_function", call_function_wrapper);
456 pass->pass.verify_irprog = ir_prog_no_verify;
457 pass->pass.dump_irprog = ir_prog_no_dump;
458 pass->pass.context = pass;
460 pass->function = function;
461 pass->context = context;