Commit 3646e58f authored by Michael Beck's avatar Michael Beck
Browse files

- implemented a pass manager, so optimizations could be added in advance to "a...

- implemented a pass manager, so optimizations could be added in advance to "a pass" and run an once as a pipeline
- two managers yet: graph manager runs passes on all graphs of an irp, prog manager runs passes on all irp's (currently only one)

[r26344]
parent 95d5fa3e
......@@ -124,6 +124,10 @@ typedef enum {
k_ir_extblk, /**< An extended basic block. */
k_ir_prog, /**< A program representation (irp). */
k_ir_region, /**< A region. */
k_ir_graph_pass, /**< An ir_graph pass. */
k_ir_prog_pass, /**< An ir_prog pass. */
k_ir_graph_pass_mgr, /**< An ir_graph pass manager. */
k_ir_prog_pass_mgr, /**< An ir_prog pass manager. */
k_ir_max /**< maximum value -- illegal for firm nodes. */
} firm_kind;
......
......@@ -40,6 +40,7 @@ typedef struct tarval tarval, *ir_tarval_ptr;
typedef struct ir_enum_const ir_enum_const, *ir_enum_const_ptr;
typedef struct ir_type ir_type, *ir_type_ptr;
typedef struct ir_graph ir_graph, *ir_graph_ptr;
typedef struct ir_prog ir_prog, *ir_prog_ptr;
typedef struct ir_loop ir_loop, *ir_loop_ptr;
typedef struct ir_region ir_region, *ir_region_ptr;
typedef struct ir_reg_tree ir_reg_tree, *ir_reg_tree_ptr;
......@@ -53,6 +54,11 @@ typedef struct sn_entry *seqno_t;
typedef struct arch_irn_ops_t arch_irn_ops_t;
typedef struct ident_if_t ident_if_t;
typedef struct type_identify_if_t type_identify_if_t;
typedef struct ir_graph_pass_t ir_graph_pass_t;
typedef struct ir_prog_pass_t ir_prog_pass_t;
typedef struct ir_graph_pass_manager_t ir_graph_pass_manager_t;
typedef struct ir_prog_pass_manager_t ir_prog_pass_manager_t;
typedef union ir_initializer_t ir_initializer_t, *ir_initializer_ptr;
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* 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.
*/
/**
* @file
* @brief Manager for transformation passes.
* @author Michael Beck
* @version $Id: $
*/
#ifndef FIRM_IR_PASS_H
#define FIRM_IR_PASS_H
#include "firm_types.h"
/**
* Creates a new ir_graph pass manager.
*
* @param name the name of the manager
* @param verify_all if non-zero, all passes of this manager will be verified
* @param dump_all if non-zero, all passes results will be dumped
*
* @return the newly created manager
*/
ir_graph_pass_manager_t *new_graph_pass_mgr(
const char *name, int verify_all, int dump_all);
/**
* Add an ir_graph pass to a graph pass manager.
*
* @param mgr the ir_graph pass manager
* @param pass the pass to add
*/
void ir_graph_pass_mgr_add(ir_graph_pass_manager_t *mgr, ir_graph_pass_t *pass);
/**
* Run all passes of an ir_graph pass manager.
*
* @param mgr the manager
*
* @return 0 if all passes return 0, else 1
*/
int ir_graph_pass_mgr_run(ir_graph_pass_manager_t *mgr);
/**
* Terminate an ir_graph pass manager and all owned passes.
*
* @param mgr the manager
*/
void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr);
/**
* Creates a new ir_prog pass manager.
*
* @param name the name of the manager
* @param verify_all if non-zero, all passes of this manager will be verified
* @param dump_all if non-zero, all passes results will be dumped
*
* @return the newly created manager
*/
ir_prog_pass_manager_t *new_prog_pass_mgr(
const char *name, int verify_all, int dump_all);
/**
* Add an ir_prog pass to an ir_prog pass manager.
*
* @param mgr the ir_prog pass manager
* @param pass the pass to add
*/
void ir_prog_pass_mgr_add(ir_prog_pass_manager_t *mgr, ir_prog_pass_t *pass);
/**
* Add an ir_graph_pass_manager as a pass to an ir_prog pass manager.
*
* @param mgr the ir_prog pass manager
* @param graph_mgr the ir_graph pass manager to be added
*/
void ir_prog_pass_mgr_add_graph_mgr(
ir_prog_pass_manager_t *mgr, ir_graph_pass_manager_t *graph_mgr);
/**
* Run all passes of an ir_prog pass manager.
*
* @param mgr the manager
*
* @return 0 if all passes return 0, else 1
*/
int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr);
/**
* Terminate an ir_prog pass manager and all owned passes.
*
* @param mgr the manager
*/
void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr);
#endif
/*
* Copyright (C) 1995-2009 University of Karlsruhe. All right reserved.
*
* 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.
*/
/**
* @file
* @brief Manager for optimization passes.
* @author Michael Beck
* @version $Id: $
*/
#include "config.h"
#include <string.h>
#include "adt/list.h"
#include "irpass_t.h"
#include "irgraph_t.h"
#include "irprog_t.h"
#include "irdump.h"
#include "irvrfy.h"
#include "xmalloc.h"
/*Add a graph pass to a graph pass manager. */
void ir_graph_pass_mgr_add(ir_graph_pass_manager_t *mgr, ir_graph_pass_t *pass)
{
list_add(&pass->list, &mgr->passes);
++mgr->n_passes;
if (pass->add_to_mgr)
pass->add_to_mgr(pass->context);
}
/* Add an irprog pass to an irprog pass manager. */
void ir_prog_pass_mgr_add(ir_prog_pass_manager_t *mgr, ir_prog_pass_t *pass)
{
list_add(&pass->list, &mgr->passes);
++mgr->n_passes;
if (pass->add_to_mgr)
pass->add_to_mgr(pass->context);
}
/**
* wrapper for running a graph pass manager as a pass on an irprog
* pass manager.
*/
static int run_wrapper(ir_prog *prog, void *ctx)
{
ir_graph_pass_manager_t *mgr = ctx;
(void)prog;
return ir_graph_pass_mgr_run(mgr);
}
/**
* Ensure that no verifier is run from the wrapper.
*/
static int no_verify(ir_prog *prog, void *ctx)
{
(void)prog;
(void)ctx;
return 0;
}
/**
* Ensure that no dumper is run from the wrapper.
*/
static void no_dump(ir_prog *prog, void *ctx, unsigned idx)
{
(void)prog;
(void)ctx;
(void)idx;
}
/* Add an ir_graph_pass_manager as a pass to an irprog pass manager. */
void ir_prog_pass_mgr_add_graph_mgr(
ir_prog_pass_manager_t *mgr, ir_graph_pass_manager_t *graph_mgr)
{
ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
pass->run_on_irprog = run_wrapper;
pass->context = graph_mgr;
pass->name = graph_mgr->name;
/* do not verify nor dump: this is handled by the graph manager */
pass->verify_irprog = no_verify;
pass->dump_irprog = no_dump;
pass->dump = 0;
pass->verify = 0;
pass->add_to_mgr = NULL;
pass->rem_from_mgr = NULL;
if (mgr->dump_all)
graph_mgr->dump_all = 1;
if (mgr->verify_all)
graph_mgr->verify_all = 1;
graph_mgr->run_idx = mgr->n_passes;
ir_prog_pass_mgr_add(mgr, pass);
}
/**
* Create a suffix for dumping.
*/
void create_suffix(char *suffix, size_t n, const char *pass_name, unsigned index)
{
snprintf(suffix, n, "-%02u_%s", index, pass_name);
}
/* Run all passes of an ir_graph pass manager. */
int ir_graph_pass_mgr_run(ir_graph_pass_manager_t *mgr)
{
ir_graph_pass_t *pass;
int i, res = 0;
ir_graph *rem = current_ir_graph;
/* on all graphs: beware: number of irgs might be changed */
for (i = 0; i < get_irp_n_irgs(); ++i) {
ir_graph *irg = current_ir_graph = get_irp_irg(i);
unsigned idx = mgr->run_idx;
/* run every pass on every graph */
list_for_each_entry(ir_graph_pass_t, pass, &mgr->passes, list) {
int pass_res = pass->run_on_irg(irg, pass->context);
if (pass_res != 0)
res = 1;
/* verify is necessary */
if (mgr->verify_all || pass->verify) {
if (pass->verify_irg) {
pass->verify_irg(irg, pass->context);
} else {
irg_verify(irg, 0);
}
}
/* dump */
if (mgr->dump_all || pass->dump) {
if (pass->dump_irg) {
pass->dump_irg(irg, pass->context, idx);
} else {
char suffix[1024];
create_suffix(suffix, sizeof(suffix), pass->name, idx);
dump_ir_block_graph(irg, suffix);
}
}
++idx;
}
}
current_ir_graph = rem;
return res;
}
/**
* Verify all graphs on the given ir_prog.
*/
static int irp_verify_irgs(ir_prog *irp, int flags) {
int i, res = 1;
for (i = get_irp_n_irgs() - 1; i >= 0; --i)
res &= irg_verify(get_irp_irg(i), flags);
return res;
}
/* Run all passes of an irprog pass manager. */
int ir_prog_pass_mgr_run(ir_prog_pass_manager_t *mgr)
{
ir_prog_pass_t *pass;
int res = 0;
/* run every pass on every graph */
unsigned idx = mgr->run_idx;
list_for_each_entry(ir_prog_pass_t, pass, &mgr->passes, list) {
int pass_res = pass->run_on_irprog(irp, pass->context);
if (pass_res != 0)
res = 1;
/* verify is necessary */
if (mgr->verify_all || pass->verify) {
if (pass->verify_irprog) {
pass->verify_irprog(irp, pass->context);
} else {
irp_verify_irgs(irp, 0);
}
}
/* dump */
if (mgr->dump_all || pass->dump) {
if (pass->dump_irprog) {
pass->dump_irprog(irp, pass->context, idx);
} else {
char suffix[1024];
create_suffix(suffix, sizeof(suffix), pass->name, idx);
dump_all_ir_graphs(dump_ir_block_graph, suffix);
}
}
++idx;
}
return res;
}
/* Creates a new ir_graph pass manager. */
ir_graph_pass_manager_t *new_graph_pass_mgr(
const char *name, int verify_all, int dump_all)
{
ir_graph_pass_manager_t *res = xmalloc(sizeof(res));
INIT_LIST_HEAD(&res->passes);
res->name = name;
res->run_idx = 0;
res->verify_all = verify_all != 0;
res->dump_all = dump_all != 0;
return res;
}
/* Creates a new ir_prog pass manager. */
ir_prog_pass_manager_t *new_prog_pass_mgr(
const char *name, int verify_all, int dump_all)
{
ir_prog_pass_manager_t *res = xmalloc(sizeof(res));
INIT_LIST_HEAD(&res->passes);
res->name = name;
res->run_idx = 0;
res->verify_all = verify_all != 0;
res->dump_all = dump_all != 0;
return res;
}
/* Terminate a graph pass manager and all owned passes. */
void term_graph_pass_mgr(ir_graph_pass_manager_t *mgr)
{
ir_graph_pass_t *pass, *next;
list_for_each_entry_safe(ir_graph_pass_t, pass, next, &mgr->passes, list) {
if (pass->rem_from_mgr)
pass->rem_from_mgr(pass->context);
pass->kind = k_BAD;
xfree(pass);
}
mgr->kind = k_BAD;
xfree(mgr);
}
/* Terminate an ir_prog pass manager and all owned passes. */
void term_prog_pass_mgr(ir_prog_pass_manager_t *mgr)
{
ir_prog_pass_t *pass, *next;
list_for_each_entry_safe(ir_prog_pass_t, pass, next, &mgr->passes, list) {
if (pass->rem_from_mgr)
pass->rem_from_mgr(pass->context);
pass->kind = k_BAD;
xfree(pass);
}
mgr->kind = k_BAD;
xfree(mgr);
}
/**
* Set the run index for an irgraph pass manager.
*
* @param mgr the manager
* @param run_idx the index for the first pass of this manager
*/
void ir_graph_pass_manager_set_run_idx(
ir_graph_pass_manager_t *mgr, unsigned run_idx)
{
mgr->run_idx = run_idx;
}
/**
* Set the run index for an irprog pass manager.
*
* @param mgr the manager
* @param run_idx the index for the first pass of this manager
*/
void ir_prog_pass_manager_set_run_idx(
ir_prog_pass_manager_t *mgr, unsigned run_idx)
{
mgr->run_idx = run_idx;
}
/*
* Copyright (C) 1995-2009 University of Karlsruhe. All right reserved.
*
* 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.
*/
#ifndef FIRM_IR_PASS_T_H
#define FIRM_IR_PASS_T_H
/**
* @file
* @brief Manager for optimization passes. Private Header
* @author Michael Beck
* @version $Id: $
*/
#include "firm_types.h"
#include "firm_common.h"
#include "adt/list.h"
#include "irpass.h"
/**
* Pass function on an ir_graph.
*/
typedef int (*RUN_ON_IRG_FUNC)(ir_graph *irg, void *ctx);
/**
* Dump function on an ir_graph.
*/
typedef void (*DUMP_ON_IRG_FUNC)(ir_graph *irg, void *ctx, unsigned idx);
/**
* Pass function on an ir_prog.
*/
typedef int (*RUN_ON_IRPROG_FUNC)(ir_prog *prog, void *ctx);
/**
* Dump function on an ir_prog.
*/
typedef void (*DUMP_ON_IRPROG_FUNC)(ir_prog *irg, void *ctx, unsigned idx);
/**
* Init/Term function on an pass.
*/
typedef void (*INIT_TERM_FUNC)(void *ctx);
/**
* A graph pass.
*/
struct ir_graph_pass_t {
/** The firm kind. */
firm_kind kind;
/** This function is run on every graph on an ir_prog. */
RUN_ON_IRG_FUNC run_on_irg;
RUN_ON_IRG_FUNC verify_irg;
DUMP_ON_IRG_FUNC dump_irg;
/** This function is called if this pass is added. */
INIT_TERM_FUNC add_to_mgr;
/** This function is called if this pass is removed. */
INIT_TERM_FUNC rem_from_mgr;
/** context parameter for this pass */
void *context;
/** The name of the pass. */
const char *name;
/** Links all passes. */
list_head list;
unsigned verify:1; /**< Set if this pass should be verified. */
unsigned dump:1; /**< Set if this pass should be dumped. */
};
/**
* A irprog pass.
*/
struct ir_prog_pass_t {
/** The firm kind. */
firm_kind kind;
/** This function is on an ir_prog. */
RUN_ON_IRPROG_FUNC run_on_irprog;
RUN_ON_IRPROG_FUNC verify_irprog;
DUMP_ON_IRPROG_FUNC dump_irprog;
/** This function is called if this pass is added. */
INIT_TERM_FUNC add_to_mgr;
/** This function is called if this pass is removed. */
INIT_TERM_FUNC rem_from_mgr;
/** context parameter for this pass */
void *context;
/** The name of the pass. */
const char *name;
/** Links all passes */
list_head list;
unsigned verify:1; /**< Set if this pass should be verified. */
unsigned dump:1; /**< Set if this pass should be dumped. */
};
/**
* A graph pass manager.
*/
struct ir_graph_pass_manager_t {
firm_kind kind; /**< The firm kind. */
list_head passes; /**< The list of passes. */
unsigned n_passes; /**< Number of added passes. */
const char *name; /**< the name of the manager. */
unsigned run_idx; /**< The run number for the first pass of this manager. */
unsigned verify_all:1; /**< Set if every pass should be verified. */
unsigned dump_all:1; /**< Set if every pass should be dumped. */
};
/**
* A irprog pass manager.
*/
struct ir_prog_pass_manager_t {
firm_kind kind; /**< The firm kind. */
list_head passes; /**< The list of passes. */
unsigned n_passes; /**< Number of added passes. */
const char *name; /**< the name of the manager. */
unsigned run_idx; /**< The run number for the first pass of this manager. */
unsigned verify_all:1; /**< Set if every pass should be verified. */
unsigned dump_all:1; /**< Set if every pass should be dumped. */
};
#endif
......@@ -518,7 +518,21 @@ struct ir_graph {
#endif
};
/** ir_prog */
/**
* Data structure that holds central information about a program
* or a module.
* One irp is created by libFirm on construction, so irp should never be NULL.
*
* - main_irg: The ir graph that is the entry point to the program.
* (Anything not reachable from here may be optimized away
* if this irp represents a whole program.
* - irg: List of all ir graphs in the program or module.
* - type: A list containing all types known to the translated program.
* Some types can have several entries in this list (as a result of
* using exchange_types()).
* - glob_type: The unique global type that is owner of all global entities
* of this module.
*/
struct ir_prog {
firm_kind kind; /**< must be k_ir_prog */
ident *name; /**< A file name or the like. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment