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 static void create_suffix(char *suffix, size_t n, const char *pass_name)
161 snprintf(suffix, n, "%s.svg", pass_name);
164 int ir_graph_pass_mgr_run(ir_graph_pass_manager_t *mgr)
166 ir_graph_pass_t *pass;
169 ir_graph *rem = current_ir_graph;
171 /* on all graphs: beware: number of irgs might be changed */
172 for (i = 0; i < get_irp_n_irgs(); ++i) {
173 ir_graph *irg = current_ir_graph = get_irp_irg(i);
174 unsigned idx = mgr->run_idx;
175 /* run every pass on every graph */
176 list_for_each_entry(ir_graph_pass_t, pass, &mgr->passes, list) {
177 int pass_res = pass->run_on_irg(irg, pass->context);
180 /* verify is necessary */
181 if (mgr->verify_all) {
182 if (pass->verify_irg) {
183 pass->verify_irg(irg, pass->context);
190 if (pass->dump_irg) {
191 pass->dump_irg(irg, pass->context, idx);
194 create_suffix(buf, sizeof(buf), pass->name);
195 dump_ir_graph(irg, buf);
201 current_ir_graph = rem;
206 * Verify all graphs on the given ir_prog.
208 static int irp_verify_irgs(void)
212 size_t n_irgs = get_irp_n_irgs();
214 for (i = 0; i < n_irgs; ++i)
215 res &= irg_verify(get_irp_irg(i), 0);
219 int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr)
221 ir_prog_pass_t *pass;
224 /* run every pass on every graph */
225 unsigned idx = mgr->run_idx;
226 list_for_each_entry(ir_prog_pass_t, pass, &mgr->passes, list) {
227 int pass_res = pass->run_on_irprog(irp, pass->context);
230 /* verify is necessary */
231 if (mgr->verify_all) {
232 if (pass->verify_irprog) {
233 pass->verify_irprog(irp, pass->context);
240 if (pass->dump_irprog) {
241 pass->dump_irprog(irp, pass->context, idx);
244 create_suffix(buf, sizeof(buf), pass->name);
245 dump_all_ir_graphs(buf);
248 if (pass->is_wrapper) {
249 ir_graph_pass_manager_t *graph_mgr = (ir_graph_pass_manager_t*)pass->context;
250 idx += graph_mgr->n_passes;
257 ir_graph_pass_manager_t *new_graph_pass_mgr(
258 const char *name, int verify_all, int dump_all)
260 ir_graph_pass_manager_t *res = XMALLOCZ(ir_graph_pass_manager_t);
262 INIT_LIST_HEAD(&res->passes);
263 res->kind = k_ir_graph_pass_mgr;
266 res->verify_all = verify_all != 0;
267 res->dump_all = dump_all != 0;
272 ir_prog_pass_manager_t *new_prog_pass_mgr(
273 const char *name, int verify_all, int dump_all)
275 ir_prog_pass_manager_t *res = XMALLOCZ(ir_prog_pass_manager_t);
277 INIT_LIST_HEAD(&res->passes);
278 res->kind = k_ir_prog_pass_mgr;
281 res->verify_all = verify_all != 0;
282 res->dump_all = dump_all != 0;
287 void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr)
289 ir_graph_pass_t *pass, *next;
291 list_for_each_entry_safe(ir_graph_pass_t, pass, next, &mgr->passes, list) {
292 if (pass->rem_from_mgr)
293 pass->rem_from_mgr(pass->context);
301 void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr)
303 ir_prog_pass_t *pass, *next;
305 list_for_each_entry_safe(ir_prog_pass_t, pass, next, &mgr->passes, list) {
306 if (pass->rem_from_mgr)
307 pass->rem_from_mgr(pass->context);
315 void ir_graph_pass_mgr_set_run_idx(
316 ir_graph_pass_manager_t *mgr, unsigned run_idx)
318 mgr->run_idx = run_idx;
321 void ir_prog_pass_mgr_set_run_idx(
322 ir_prog_pass_manager_t *mgr, unsigned run_idx)
324 mgr->run_idx = run_idx;
328 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
330 static int void_graph_wrapper(ir_graph *irg, void *context)
332 void_pass_func_irg function = (void_pass_func_irg)context;
337 ir_graph_pass_t *def_graph_pass(
338 const char *name, void (*function)(ir_graph *irg))
340 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
342 pass->kind = k_ir_graph_pass;
343 pass->run_on_irg = void_graph_wrapper;
344 pass->context = (void*)function;
347 INIT_LIST_HEAD(&pass->list);
353 * Wrapper for running int function(ir_graph *irg) as an ir_graph pass.
355 static int int_graph_wrapper(ir_graph *irg, void *context)
357 int_pass_func_irg function = (int_pass_func_irg)context;
358 return function(irg);
361 ir_graph_pass_t *def_graph_pass_ret(
362 const char *name, int (*function)(ir_graph *irg))
364 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
366 pass->kind = k_ir_graph_pass;
367 pass->run_on_irg = int_graph_wrapper;
368 pass->context = (void*)function;
371 INIT_LIST_HEAD(&pass->list);
376 ir_graph_pass_t *def_graph_pass_constructor(
377 ir_graph_pass_t *pass,
378 const char *name, int (*function)(ir_graph *irg, void *context)) {
380 pass = XMALLOCZ(ir_graph_pass_t);
382 memset(pass, 0, sizeof(ir_graph_pass_t));
383 pass->kind = k_ir_graph_pass;
384 pass->run_on_irg = function;
385 pass->context = pass;
388 INIT_LIST_HEAD(&pass->list);
393 void ir_graph_pass_set_parallel(ir_graph_pass_t *pass, int flag)
395 pass->run_parallel = flag != 0;
399 * Wrapper for running void function(void) as an ir_prog pass.
401 static int void_prog_wrapper(ir_prog *irp, void *context)
403 void_pass_func function = (void_pass_func)context;
410 ir_prog_pass_t *def_prog_pass(
412 void (*function)(void))
414 struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
416 pass->kind = k_ir_prog_pass;
417 pass->run_on_irprog = void_prog_wrapper;
418 pass->context = (void*)function;
421 INIT_LIST_HEAD(&pass->list);
426 ir_prog_pass_t *def_prog_pass_constructor(
427 ir_prog_pass_t *pass,
429 int (*function)(ir_prog *irp, void *context))
432 pass = XMALLOCZ(ir_prog_pass_t);
434 memset(pass, 0, sizeof(ir_prog_pass_t));
436 pass->kind = k_ir_prog_pass;
437 pass->run_on_irprog = function;
438 pass->context = pass;
441 INIT_LIST_HEAD(&pass->list);
446 typedef struct pass_t {
449 void (*function)(void *context);
453 * Wrapper for the call_function pass.
455 static int call_function_wrapper(ir_prog *irp, void *context)
457 pass_t *pass = (pass_t*)context;
460 pass->function(pass->context);
464 ir_prog_pass_t *call_function_pass(
465 const char *name, void (*function)(void *context), void *context) {
466 struct pass_t *pass = XMALLOCZ(struct pass_t);
468 def_prog_pass_constructor(
469 &pass->pass, name ? name : "set_function", call_function_wrapper);
471 pass->pass.verify_irprog = ir_prog_no_verify;
472 pass->pass.dump_irprog = ir_prog_no_dump;
473 pass->pass.context = pass;
475 pass->function = function;
476 pass->context = context;