2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Manager for optimization passes.
16 #include "irgraph_t.h"
23 typedef void (*void_pass_func_irg)(ir_graph *irg);
24 typedef int (*int_pass_func_irg)(ir_graph *irg);
25 typedef void (*void_pass_func)(void);
27 void ir_graph_pass_mgr_add(ir_graph_pass_manager_t *mgr, ir_graph_pass_t *pass)
29 list_add_tail(&pass->list, &mgr->passes);
32 pass->add_to_mgr(pass->context);
35 void ir_prog_pass_mgr_add(ir_prog_pass_manager_t *mgr, ir_prog_pass_t *pass)
37 list_add_tail(&pass->list, &mgr->passes);
40 pass->add_to_mgr(pass->context);
44 * wrapper for running a graph pass manager as a pass on an irprog
47 static int run_wrapper(ir_prog *prog, void *ctx)
49 ir_graph_pass_manager_t *mgr = (ir_graph_pass_manager_t*)ctx;
52 return ir_graph_pass_mgr_run(mgr);
55 int ir_prog_no_verify(ir_prog *prog, void *ctx)
62 void ir_prog_no_dump(ir_prog *prog, void *ctx, unsigned idx)
70 * Term wrapper for a wrapped ir_graph pass manager.
72 static void term_wrapper(void *context)
74 ir_graph_pass_manager_t *mgr = (ir_graph_pass_manager_t*)context;
75 term_graph_pass_mgr(mgr);
79 * Create a wrapper ir_prog pass for an ir_graph manager.
81 static ir_prog_pass_t *create_wrapper_pass(ir_graph_pass_manager_t *graph_mgr)
83 /* create a wrapper pass */
84 ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
86 pass->kind = k_ir_prog_pass;
87 pass->run_on_irprog = run_wrapper;
88 pass->context = graph_mgr;
89 pass->name = graph_mgr->name;
91 /* do not verify nor dump: this is handled by the graph manager */
92 pass->verify_irprog = ir_prog_no_verify;
93 pass->dump_irprog = ir_prog_no_dump;
96 pass->add_to_mgr = NULL;
97 pass->rem_from_mgr = term_wrapper;
102 void ir_prog_pass_mgr_add_graph_pass(
103 ir_prog_pass_manager_t *mgr, ir_graph_pass_t *pass)
105 ir_graph_pass_manager_t *graph_mgr;
106 ir_prog_pass_t *wrapper;
108 /* check if the last pass is a graph_pass wrapper */
109 if (! list_empty(&mgr->passes)) {
110 wrapper = list_entry(mgr->passes.prev, ir_prog_pass_t, list);
111 if (wrapper->is_wrapper) {
112 graph_mgr = (ir_graph_pass_manager_t*)wrapper->context;
114 ir_graph_pass_mgr_add(graph_mgr, pass);
120 /* not found, create a new wrapper */
121 graph_mgr = new_graph_pass_mgr(
122 "graph_pass_wrapper", mgr->verify_all, mgr->dump_all);
123 graph_mgr->run_idx = mgr->run_idx + mgr->n_passes;
125 ir_graph_pass_mgr_add(graph_mgr, pass);
127 wrapper = create_wrapper_pass(graph_mgr);
128 ir_prog_pass_mgr_add(mgr, wrapper);
131 void ir_prog_pass_mgr_add_graph_mgr(
132 ir_prog_pass_manager_t *mgr, ir_graph_pass_manager_t *graph_mgr)
134 ir_prog_pass_t *pass = create_wrapper_pass(graph_mgr);
137 graph_mgr->dump_all = 1;
139 graph_mgr->verify_all = 1;
140 graph_mgr->run_idx = mgr->n_passes;
142 ir_prog_pass_mgr_add(mgr, pass);
145 int ir_graph_pass_mgr_run(ir_graph_pass_manager_t *mgr)
149 ir_graph *rem = current_ir_graph;
151 /* on all graphs: beware: number of irgs might be changed */
152 for (i = 0; i < get_irp_n_irgs(); ++i) {
153 ir_graph *irg = current_ir_graph = get_irp_irg(i);
154 unsigned idx = mgr->run_idx;
155 /* run every pass on every graph */
156 list_for_each_entry(ir_graph_pass_t, pass, &mgr->passes, list) {
157 int pass_res = pass->run_on_irg(irg, pass->context);
160 /* verify is necessary */
161 if (mgr->verify_all) {
162 if (pass->verify_irg) {
163 pass->verify_irg(irg, pass->context);
170 if (pass->dump_irg) {
171 pass->dump_irg(irg, pass->context, idx);
173 dump_ir_graph(irg, pass->name);
179 current_ir_graph = rem;
184 * Verify all graphs on the given ir_prog.
186 static int irp_verify_irgs(void)
190 size_t n_irgs = get_irp_n_irgs();
192 for (i = 0; i < n_irgs; ++i)
193 res &= irg_verify(get_irp_irg(i), 0);
197 int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr)
201 /* run every pass on every graph */
202 unsigned idx = mgr->run_idx;
203 list_for_each_entry(ir_prog_pass_t, pass, &mgr->passes, list) {
204 int pass_res = pass->run_on_irprog(irp, pass->context);
207 /* verify is necessary */
208 if (mgr->verify_all) {
209 if (pass->verify_irprog) {
210 pass->verify_irprog(irp, pass->context);
217 if (pass->dump_irprog) {
218 pass->dump_irprog(irp, pass->context, idx);
220 dump_all_ir_graphs(pass->name);
223 if (pass->is_wrapper) {
224 ir_graph_pass_manager_t *graph_mgr = (ir_graph_pass_manager_t*)pass->context;
225 idx += graph_mgr->n_passes;
232 ir_graph_pass_manager_t *new_graph_pass_mgr(
233 const char *name, int verify_all, int dump_all)
235 ir_graph_pass_manager_t *res = XMALLOCZ(ir_graph_pass_manager_t);
237 INIT_LIST_HEAD(&res->passes);
238 res->kind = k_ir_graph_pass_mgr;
241 res->verify_all = verify_all != 0;
242 res->dump_all = dump_all != 0;
247 ir_prog_pass_manager_t *new_prog_pass_mgr(
248 const char *name, int verify_all, int dump_all)
250 ir_prog_pass_manager_t *res = XMALLOCZ(ir_prog_pass_manager_t);
252 INIT_LIST_HEAD(&res->passes);
253 res->kind = k_ir_prog_pass_mgr;
256 res->verify_all = verify_all != 0;
257 res->dump_all = dump_all != 0;
262 void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr)
264 list_for_each_entry_safe(ir_graph_pass_t, pass, next, &mgr->passes, list) {
265 if (pass->rem_from_mgr)
266 pass->rem_from_mgr(pass->context);
274 void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr)
276 list_for_each_entry_safe(ir_prog_pass_t, pass, next, &mgr->passes, list) {
277 if (pass->rem_from_mgr)
278 pass->rem_from_mgr(pass->context);
286 void ir_graph_pass_mgr_set_run_idx(
287 ir_graph_pass_manager_t *mgr, unsigned run_idx)
289 mgr->run_idx = run_idx;
292 void ir_prog_pass_mgr_set_run_idx(
293 ir_prog_pass_manager_t *mgr, unsigned run_idx)
295 mgr->run_idx = run_idx;
299 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
301 static int void_graph_wrapper(ir_graph *irg, void *context)
303 void_pass_func_irg function = (void_pass_func_irg)context;
308 ir_graph_pass_t *def_graph_pass(
309 const char *name, void (*function)(ir_graph *irg))
311 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
313 pass->kind = k_ir_graph_pass;
314 pass->run_on_irg = void_graph_wrapper;
315 pass->context = (void*)function;
318 INIT_LIST_HEAD(&pass->list);
324 * Wrapper for running int function(ir_graph *irg) as an ir_graph pass.
326 static int int_graph_wrapper(ir_graph *irg, void *context)
328 int_pass_func_irg function = (int_pass_func_irg)context;
329 return function(irg);
332 ir_graph_pass_t *def_graph_pass_ret(
333 const char *name, int (*function)(ir_graph *irg))
335 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
337 pass->kind = k_ir_graph_pass;
338 pass->run_on_irg = int_graph_wrapper;
339 pass->context = (void*)function;
342 INIT_LIST_HEAD(&pass->list);
347 ir_graph_pass_t *def_graph_pass_constructor(
348 ir_graph_pass_t *pass,
349 const char *name, int (*function)(ir_graph *irg, void *context)) {
351 pass = XMALLOCZ(ir_graph_pass_t);
353 memset(pass, 0, sizeof(ir_graph_pass_t));
354 pass->kind = k_ir_graph_pass;
355 pass->run_on_irg = function;
356 pass->context = pass;
359 INIT_LIST_HEAD(&pass->list);
364 void ir_graph_pass_set_parallel(ir_graph_pass_t *pass, int flag)
366 pass->run_parallel = flag != 0;
370 * Wrapper for running void function(void) as an ir_prog pass.
372 static int void_prog_wrapper(ir_prog *irp, void *context)
374 void_pass_func function = (void_pass_func)context;
381 ir_prog_pass_t *def_prog_pass(
383 void (*function)(void))
385 struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
387 pass->kind = k_ir_prog_pass;
388 pass->run_on_irprog = void_prog_wrapper;
389 pass->context = (void*)function;
392 INIT_LIST_HEAD(&pass->list);
397 ir_prog_pass_t *def_prog_pass_constructor(
398 ir_prog_pass_t *pass,
400 int (*function)(ir_prog *irp, void *context))
403 pass = XMALLOCZ(ir_prog_pass_t);
405 memset(pass, 0, sizeof(ir_prog_pass_t));
407 pass->kind = k_ir_prog_pass;
408 pass->run_on_irprog = function;
409 pass->context = pass;
412 INIT_LIST_HEAD(&pass->list);
417 typedef struct pass_t {
420 void (*function)(void *context);
424 * Wrapper for the call_function pass.
426 static int call_function_wrapper(ir_prog *irp, void *context)
428 pass_t *pass = (pass_t*)context;
431 pass->function(pass->context);
435 ir_prog_pass_t *call_function_pass(
436 const char *name, void (*function)(void *context), void *context) {
437 struct pass_t *pass = XMALLOCZ(struct pass_t);
439 def_prog_pass_constructor(
440 &pass->pass, name ? name : "set_function", call_function_wrapper);
442 pass->pass.verify_irprog = ir_prog_no_verify;
443 pass->pass.dump_irprog = ir_prog_no_dump;
444 pass->pass.context = pass;
446 pass->function = function;
447 pass->context = context;