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)
168 ir_graph *rem = current_ir_graph;
170 /* on all graphs: beware: number of irgs might be changed */
171 for (i = 0; i < get_irp_n_irgs(); ++i) {
172 ir_graph *irg = current_ir_graph = get_irp_irg(i);
173 unsigned idx = mgr->run_idx;
174 /* run every pass on every graph */
175 list_for_each_entry(ir_graph_pass_t, pass, &mgr->passes, list) {
176 int pass_res = pass->run_on_irg(irg, pass->context);
179 /* verify is necessary */
180 if (mgr->verify_all) {
181 if (pass->verify_irg) {
182 pass->verify_irg(irg, pass->context);
189 if (pass->dump_irg) {
190 pass->dump_irg(irg, pass->context, idx);
193 create_suffix(buf, sizeof(buf), pass->name);
194 dump_ir_graph(irg, buf);
200 current_ir_graph = rem;
205 * Verify all graphs on the given ir_prog.
207 static int irp_verify_irgs(void)
211 size_t n_irgs = get_irp_n_irgs();
213 for (i = 0; i < n_irgs; ++i)
214 res &= irg_verify(get_irp_irg(i), 0);
218 int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr)
222 /* run every pass on every graph */
223 unsigned idx = mgr->run_idx;
224 list_for_each_entry(ir_prog_pass_t, pass, &mgr->passes, list) {
225 int pass_res = pass->run_on_irprog(irp, pass->context);
228 /* verify is necessary */
229 if (mgr->verify_all) {
230 if (pass->verify_irprog) {
231 pass->verify_irprog(irp, pass->context);
238 if (pass->dump_irprog) {
239 pass->dump_irprog(irp, pass->context, idx);
242 create_suffix(buf, sizeof(buf), pass->name);
243 dump_all_ir_graphs(buf);
246 if (pass->is_wrapper) {
247 ir_graph_pass_manager_t *graph_mgr = (ir_graph_pass_manager_t*)pass->context;
248 idx += graph_mgr->n_passes;
255 ir_graph_pass_manager_t *new_graph_pass_mgr(
256 const char *name, int verify_all, int dump_all)
258 ir_graph_pass_manager_t *res = XMALLOCZ(ir_graph_pass_manager_t);
260 INIT_LIST_HEAD(&res->passes);
261 res->kind = k_ir_graph_pass_mgr;
264 res->verify_all = verify_all != 0;
265 res->dump_all = dump_all != 0;
270 ir_prog_pass_manager_t *new_prog_pass_mgr(
271 const char *name, int verify_all, int dump_all)
273 ir_prog_pass_manager_t *res = XMALLOCZ(ir_prog_pass_manager_t);
275 INIT_LIST_HEAD(&res->passes);
276 res->kind = k_ir_prog_pass_mgr;
279 res->verify_all = verify_all != 0;
280 res->dump_all = dump_all != 0;
285 void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr)
287 list_for_each_entry_safe(ir_graph_pass_t, pass, next, &mgr->passes, list) {
288 if (pass->rem_from_mgr)
289 pass->rem_from_mgr(pass->context);
297 void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr)
299 list_for_each_entry_safe(ir_prog_pass_t, pass, next, &mgr->passes, list) {
300 if (pass->rem_from_mgr)
301 pass->rem_from_mgr(pass->context);
309 void ir_graph_pass_mgr_set_run_idx(
310 ir_graph_pass_manager_t *mgr, unsigned run_idx)
312 mgr->run_idx = run_idx;
315 void ir_prog_pass_mgr_set_run_idx(
316 ir_prog_pass_manager_t *mgr, unsigned run_idx)
318 mgr->run_idx = run_idx;
322 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
324 static int void_graph_wrapper(ir_graph *irg, void *context)
326 void_pass_func_irg function = (void_pass_func_irg)context;
331 ir_graph_pass_t *def_graph_pass(
332 const char *name, void (*function)(ir_graph *irg))
334 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
336 pass->kind = k_ir_graph_pass;
337 pass->run_on_irg = void_graph_wrapper;
338 pass->context = (void*)function;
341 INIT_LIST_HEAD(&pass->list);
347 * Wrapper for running int function(ir_graph *irg) as an ir_graph pass.
349 static int int_graph_wrapper(ir_graph *irg, void *context)
351 int_pass_func_irg function = (int_pass_func_irg)context;
352 return function(irg);
355 ir_graph_pass_t *def_graph_pass_ret(
356 const char *name, int (*function)(ir_graph *irg))
358 struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);
360 pass->kind = k_ir_graph_pass;
361 pass->run_on_irg = int_graph_wrapper;
362 pass->context = (void*)function;
365 INIT_LIST_HEAD(&pass->list);
370 ir_graph_pass_t *def_graph_pass_constructor(
371 ir_graph_pass_t *pass,
372 const char *name, int (*function)(ir_graph *irg, void *context)) {
374 pass = XMALLOCZ(ir_graph_pass_t);
376 memset(pass, 0, sizeof(ir_graph_pass_t));
377 pass->kind = k_ir_graph_pass;
378 pass->run_on_irg = function;
379 pass->context = pass;
382 INIT_LIST_HEAD(&pass->list);
387 void ir_graph_pass_set_parallel(ir_graph_pass_t *pass, int flag)
389 pass->run_parallel = flag != 0;
393 * Wrapper for running void function(void) as an ir_prog pass.
395 static int void_prog_wrapper(ir_prog *irp, void *context)
397 void_pass_func function = (void_pass_func)context;
404 ir_prog_pass_t *def_prog_pass(
406 void (*function)(void))
408 struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
410 pass->kind = k_ir_prog_pass;
411 pass->run_on_irprog = void_prog_wrapper;
412 pass->context = (void*)function;
415 INIT_LIST_HEAD(&pass->list);
420 ir_prog_pass_t *def_prog_pass_constructor(
421 ir_prog_pass_t *pass,
423 int (*function)(ir_prog *irp, void *context))
426 pass = XMALLOCZ(ir_prog_pass_t);
428 memset(pass, 0, sizeof(ir_prog_pass_t));
430 pass->kind = k_ir_prog_pass;
431 pass->run_on_irprog = function;
432 pass->context = pass;
435 INIT_LIST_HEAD(&pass->list);
440 typedef struct pass_t {
443 void (*function)(void *context);
447 * Wrapper for the call_function pass.
449 static int call_function_wrapper(ir_prog *irp, void *context)
451 pass_t *pass = (pass_t*)context;
454 pass->function(pass->context);
458 ir_prog_pass_t *call_function_pass(
459 const char *name, void (*function)(void *context), void *context) {
460 struct pass_t *pass = XMALLOCZ(struct pass_t);
462 def_prog_pass_constructor(
463 &pass->pass, name ? name : "set_function", call_function_wrapper);
465 pass->pass.verify_irprog = ir_prog_no_verify;
466 pass->pass.dump_irprog = ir_prog_no_dump;
467 pass->pass.context = pass;
469 pass->function = function;
470 pass->context = context;