Commit 03ffa62e authored by Sebastian Hack's avatar Sebastian Hack
Browse files

Added beirgmod and benode

fixed some minor flaws
parent cd68cfb3
......@@ -25,7 +25,7 @@ SOURCES += Makefile.in besched.h belistsched.h belistsched.c \
bera.h bechordalspill.c beasm_dump_globals.c beasm_asm_gnu.c \
sp_matrix.c becopyoptmain.c becopyopt.c becopyheur.c \
becopyilp.c becopystat.c bearch_firm.c bearch.c bechordal_draw.c \
bechordal_draw.h lpp_rzcpx.c
bechordal_draw.h beirgmod.c beirgmod.h benode.c benode.h lpp_rzcpx.c
include $(topdir)/MakeRules
......
......@@ -66,7 +66,9 @@ get_irn_ops(const arch_env_t *env, const ir_node *irn)
int i;
for(i = env->handlers_tos - 1; i >= 0; --i) {
const arch_irn_ops_t *ops = env->handlers[i]->get_irn_ops(irn);
const arch_irn_handler_t *handler = env->handlers[i];
const arch_irn_ops_t *ops = handler->get_irn_ops(handler, irn);
if(ops)
return ops;
}
......@@ -74,11 +76,19 @@ get_irn_ops(const arch_env_t *env, const ir_node *irn)
return fallback_irn_ops;
}
const arch_register_req_t *arch_get_register_req(const arch_env_t *env,
arch_register_req_t *req, const ir_node *irn, int pos)
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
return ops->get_irn_reg_req(ops, req, irn, pos);
}
int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
int pos, const arch_register_class_t *cls, bitset_t *bs)
{
arch_register_req_t local_req;
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
const arch_register_req_t *req = ops->get_irn_reg_req(irn, pos);
const arch_register_req_t *req = ops->get_irn_reg_req(ops, &local_req, irn, pos);
switch(req->type) {
case arch_register_req_type_normal:
......@@ -98,8 +108,9 @@ int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
int arch_is_register_operand(const arch_env_t *env,
const ir_node *irn, int pos)
{
arch_register_req_t local_req;
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
const arch_register_req_t *req = ops->get_irn_reg_req(irn, pos);
const arch_register_req_t *req = ops->get_irn_reg_req(ops, &local_req, irn, pos);
return req != NULL;
}
......@@ -117,8 +128,9 @@ int arch_reg_is_allocatable(const arch_env_t *env, const ir_node *irn,
const arch_register_class_t *
arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos)
{
arch_register_req_t local_req;
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
const arch_register_req_t *req = ops->get_irn_reg_req(irn, pos);
const arch_register_req_t *req = ops->get_irn_reg_req(ops, &local_req, irn, pos);
return req ? req->cls : NULL;
}
......@@ -127,7 +139,7 @@ arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx)
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
assert(idx >= 0);
return ops->get_irn_reg(irn, idx);
return ops->get_irn_reg(ops, irn, idx);
}
extern void arch_set_irn_register(const arch_env_t *env,
......@@ -135,5 +147,5 @@ extern void arch_set_irn_register(const arch_env_t *env,
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
assert(idx >= 0);
ops->set_irn_reg(irn, idx, reg);
ops->set_irn_reg(ops, irn, idx, reg);
}
......@@ -4,9 +4,8 @@
#include "firm_config.h"
#include "irop_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "irnode.h"
#include "irmode.h"
#include "hashptr.h"
#include "fourcc.h"
......@@ -14,8 +13,6 @@
#include "list.h"
#include "ident.h"
#include "bearch.h"
struct _bitset_t;
typedef struct _arch_register_class_t arch_register_class_t;
......@@ -24,6 +21,8 @@ typedef struct _arch_enum_t arch_enum_t;
typedef struct _arch_enum_member_t arch_enum_member_t;
typedef struct _arch_isa_if_t arch_isa_if_t;
typedef struct _arch_env_t arch_env_t;
typedef struct _arch_irn_ops_t arch_irn_ops_t;
typedef struct _arch_irn_handler_t arch_irn_handler_t;
typedef enum _arch_register_type_t {
arch_register_type_none = 0,
......@@ -140,22 +139,27 @@ typedef enum _arch_operand_type_t {
* Different types of register allocation requirements.
*/
typedef enum _arch_register_req_type_t {
arch_register_req_type_normal, /** All registers in the class
arch_register_req_type_none = 0, /** No register requirement. */
arch_register_req_type_normal = 1, /** All registers in the class
are allowed. */
arch_register_req_type_limited, /** Only a real subset of
arch_register_req_type_limited = 2, /** Only a real subset of
the class is allowed. */
arch_register_req_type_equal, /** The register must equal
arch_register_req_type_equal = 4, /** The register must equal
another one at the node. */
arch_register_req_type_unequal, /** The register must be unequal
arch_register_req_type_unequal = 8, /** The register must be unequal
to some other at the node. */
arch_register_req_type_pair /** The register is part of a
arch_register_req_type_pair = 16 /** The register is part of a
register pair. */
} arch_register_req_type_t;
#define arch_register_req_is_constr(x) \
((x)->type & (arch_register_req_type_pair + arch_register_req_type_limited - 1) != 0)
/**
* Expresses requirements to register allocation for an operand.
*/
......@@ -187,7 +191,8 @@ typedef enum _arch_irn_class_t {
arch_irn_class_normal,
arch_irn_class_spill,
arch_irn_class_reload,
arch_irn_class_copy
arch_irn_class_copy,
arch_irn_class_perm
} arch_irn_class_t;
/*
......@@ -208,19 +213,21 @@ typedef enum _arch_irn_class_t {
* instruction has n input and m output operands.
*/
#define _BEARCH_TRANSFORM_INDEX(cmp, index) ((index) cmp 0 ? -((index) + 1) : (index))
/**
* Make an in position from an index.
* @param index The index.
* @return The position representing the index as an in operand.
*/
#define arch_pos_make_in(index) (index)
#define arch_pos_make_in(index) _BEARCH_TRANSFORM_INDEX(<, index)
/**
* Make an out position from an index.
* @param index The index.
* @return The position representing the index as an out operand.
*/
#define arch_pos_make_out(index) (-((index) + 1))
#define arch_pos_make_out(index) _BEARCH_TRANSFORM_INDEX(>=, index)
/**
* Check, if a position denotes an input operand.
......@@ -241,18 +248,21 @@ typedef enum _arch_irn_class_t {
* @param pos The position.
* @return The index of the position.
*/
#define arch_pos_get_index(pos) ((pos) < 0 ? -(pos) - 1 : (pos))
#define arch_pos_get_index(pos) _BEARCH_TRANSFORM_INDEX(<, pos)
typedef struct _arch_irn_ops_t {
struct _arch_irn_ops_t {
/**
* Get the register requirements for a given operand.
* @param self The self pointer.
* @param irn The node.
* @param pos The operand's position.
* @return The register requirements for the selected operand,
* or NULL, if the operand is no register.
* @return The register requirements for the selected operand.
* The pointer returned is never NULL.
*/
const arch_register_req_t *(*get_irn_reg_req)(const ir_node *irn, int pos);
const arch_register_req_t *(*get_irn_reg_req)(const arch_irn_ops_t *self,
arch_register_req_t *req,
const ir_node *irn, int pos);
/**
* Get the number of operands of a node.
......@@ -261,7 +271,7 @@ typedef struct _arch_irn_ops_t {
* output (a number < 0).
* @return The number of operands for either in, or output.
*/
int (*get_n_operands)(const ir_node *irn, int in_out);
int (*get_n_operands)(const arch_irn_ops_t *self, const ir_node *irn, int in_out);
/**
* Set the register for an output operand.
......@@ -271,7 +281,8 @@ typedef struct _arch_irn_ops_t {
* @note If the operand is not a register operand,
* the call is ignored.
*/
void (*set_irn_reg)(ir_node *irn, int idx, const arch_register_t *reg);
void (*set_irn_reg)(const arch_irn_ops_t *self, ir_node *irn,
int idx, const arch_register_t *reg);
/**
* Get the register allocated for an output operand.
......@@ -282,16 +293,32 @@ typedef struct _arch_irn_ops_t {
* @c arch_register_invalid, if no register has yet been
* allocated for this node.
*/
const arch_register_t *(*get_irn_reg)(const ir_node *irn, int idx);
const arch_register_t *(*get_irn_reg)(const arch_irn_ops_t *self,
const ir_node *irn, int idx);
/**
* Classify the node.
* @param irn The node.
* @return A classification.
*/
arch_irn_class_t (*classify)(const ir_node *irn);
arch_irn_class_t (*classify)(const arch_irn_ops_t *self, const ir_node *irn);
};
} arch_irn_ops_t;
/**
* Get the register requirements for a node.
* @param env The architecture environment.
* @param req A pointer to a requirements structure, where the data can
* be put into.
* @param irn The node.
* @param pos The position of the operand you're interested in.
* @return A pointer to the register requirements which may <b>not</b>
* neccessarily be equal to @p req. If NULL is returned, the
* operand was no register operand.
*/
extern const arch_register_req_t *
arch_get_register_req(const arch_env_t *env, arch_register_req_t *req,
const ir_node *irn, int pos);
/**
* Check if an operand is a register operand.
......@@ -368,16 +395,18 @@ extern void arch_set_irn_register(const arch_env_t *env,
/**
* Somebody who can be asked about nodes.
*/
typedef struct _arch_irn_handler_t {
struct _arch_irn_handler_t {
/**
* Get the operations of an irn.
* @param self The handler from which the method is invoked.
* @param irn Some node.
* @return Operations for that irn.
*/
const arch_irn_ops_t *(*get_irn_ops)(const ir_node *irn);
const arch_irn_ops_t *(*get_irn_ops)(const arch_irn_handler_t *handler,
const ir_node *irn);
} arch_irn_handler_t;
};
/**
* Architecture interface.
......
......@@ -7,6 +7,8 @@
#endif
#include "bitset.h"
#include "obst.h"
#include "bearch.h"
#include "irreflect.h"
......@@ -83,12 +85,18 @@ static const rflct_arg_t *get_arg(const ir_node *irn, int pos)
}
static const arch_register_req_t *
firm_get_irn_reg_req(const ir_node *irn, int pos)
firm_get_irn_reg_req(const arch_irn_ops_t *self,
arch_register_req_t *req, const ir_node *irn, int pos)
{
return mode_is_datab(get_irn_mode(irn)) ? &firm_std_reg_req : NULL;
if(mode_is_datab(get_irn_mode(irn)))
memcpy(req, &firm_std_reg_req, sizeof(*req));
else
req = NULL;
return req;
}
static int firm_get_n_operands(const ir_node *irn, int in_out)
static int firm_get_n_operands(const arch_irn_ops_t *self, const ir_node *irn, int in_out)
{
int sig = rflct_get_signature(irn);
return rflct_get_args_count(get_irn_opcode(irn), sig, in_out >= 0);
......@@ -125,19 +133,21 @@ static struct irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, int pos)
return set_insert(reg_set, &templ, sizeof(templ), hash);
}
static void firm_set_irn_reg(ir_node *irn, int pos, const arch_register_t *reg)
static void firm_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn,
int pos, const arch_register_t *reg)
{
struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
assoc->reg = reg;
}
static const arch_register_t *firm_get_irn_reg(const ir_node *irn, int pos)
static const arch_register_t *firm_get_irn_reg(const arch_irn_ops_t *self,
const ir_node *irn, int pos)
{
struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
return assoc->reg;
}
static arch_irn_class_t firm_classify(const ir_node *irn)
static arch_irn_class_t firm_classify(const arch_irn_ops_t *self, const ir_node *irn)
{
return arch_irn_class_normal;
}
......@@ -156,7 +166,8 @@ const arch_isa_if_t firm_isa = {
firm_get_reg_class
};
static const arch_irn_ops_t *firm_get_irn_ops(const ir_node *irn)
static const arch_irn_ops_t *firm_get_irn_ops(const arch_irn_handler_t *self,
const ir_node *irn)
{
return &irn_ops;
}
......
......@@ -151,7 +151,7 @@ extern void plotter_free(plotter_t *self)
}
const draw_chordal_opts_t draw_chordal_def_opts = {
10, 10, 30, 8
10, 10, 30, 8, 10, 10
};
typedef struct _draw_chordal_env_t {
......@@ -225,7 +225,7 @@ static void layout(const draw_chordal_env_t *env, ir_node *bl, int x)
struct block_dims *dims = pmap_get(env->block_dims, bl);
ir_node *sub;
rect_t *rect = &dims->subtree_box;
int h_space = 0;
int h_space = 0, v_space = 0;
memset(rect, 0, sizeof(*rect));
rect->x = x;
......@@ -239,14 +239,15 @@ static void layout(const draw_chordal_env_t *env, ir_node *bl, int x)
rect->h = max(rect->h, bl_dim->subtree_box.h);
h_space = opts->h_gap;
v_space = opts->v_gap;
}
rect->w = max(rect->w, dims->box.w + opts->h_gap);
dims->box.x = x + doz(rect->w, dims->box.w) / 2;
dims->box.y = rect->h + opts->v_gap;
dims->box.y = rect->h + v_space;
rect->h += dims->box.h + opts->v_gap;
rect->h += dims->box.h + v_space;
}
static void set_y(const draw_chordal_env_t *env, ir_node *bl, int up)
......@@ -357,8 +358,10 @@ static void draw_block(ir_node *bl, void *data)
env->plotter->vtab->set_color(env->plotter, &color);
env->plotter->vtab->line(env->plotter,
dims->box.x + x, dims->box.y + dims->box.h,
dom_dims->box.x + x, dom_dims->box.y);
dims->box.x + x,
dims->box.y + dims->box.h,
dom_dims->box.x + x,
dom_dims->box.y);
}
}
}
......@@ -378,11 +381,16 @@ static void draw_block(ir_node *bl, void *data)
#endif
}
static void draw(draw_chordal_env_t *env, const rect_t *bbox)
static void draw(draw_chordal_env_t *env, const rect_t *start_box)
{
plotter_t *p = env->plotter;
rect_t bbox;
p->vtab->begin(p, bbox);
bbox.x = bbox.y = 0;
bbox.w = start_box->w + 2 * env->opts->x_margin;
bbox.h = start_box->h + 2 * env->opts->y_margin;
p->vtab->begin(p, &bbox);
irg_block_walk_graph(env->chordal_env->irg, draw_block, NULL, env);
p->vtab->finish(p);
}
......@@ -407,8 +415,8 @@ void draw_interval_tree(const draw_chordal_opts_t *opts,
obstack_init(&env.obst);
irg_block_walk_graph(chordal_env->irg, block_dims_walker, NULL, &env);
layout(&env, start_block, 0);
set_y(&env, start_block, 0);
layout(&env, start_block, opts->x_margin);
set_y(&env, start_block, opts->y_margin);
start_dims = pmap_get(env.block_dims, start_block);
draw(&env, &start_dims->subtree_box);
......
......@@ -56,6 +56,8 @@ struct _draw_chordal_opts_t {
int h_inter_gap;
int v_gap;
int v_inter_gap;
int x_margin;
int y_margin;
};
extern const draw_chordal_opts_t draw_chordal_def_opts;
......
......@@ -12,6 +12,7 @@
#include "bitset.h"
#include "list.h"
#include "obst.h"
#include "pset.h"
#include "pmap.h"
#include "set.h"
......
......@@ -15,6 +15,8 @@
#include <malloc.h>
#endif
#include "irprog.h"
#include "lpp.h"
#include "xmalloc.h"
#include "becopyopt.h"
......
......@@ -8,6 +8,8 @@
#include "config.h"
#endif
#include "irprog.h"
#include "xmalloc.h"
#include "bechordal_t.h"
#include "becopyopt.h"
......
#include <stdlib.h>
#include "hashptr.h"
#include "pdeq.h"
#include "pset.h"
#include "pmap.h"
#include "irflag_t.h"
#include "ircons_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "irdom_t.h"
#include "iredges_t.h"
#include "besched_t.h"
#include "beirgmod.h"
struct _dom_front_info_t {
pmap *df_map;
};
static void compute_df_local(ir_node *bl, void *data)
{
pmap *df_map = ((dom_front_info_t *) data)->df_map;
ir_node *idom = get_Block_idom(bl);
int i, n;
for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
/* The predecessor block */
ir_node *pred = get_nodes_block(get_irn_n(bl, i));
/* The dominance frontier set of the predecessor. */
pset *df = pmap_get(df_map, pred);
/*
* Create the dominance frontier set of the predecessor
* if it didn't exist.
*/
if(!df) {
df = pset_new_ptr(16);
pmap_insert(df_map, pred, df);
}
if(pred != idom && bl)
pset_insert_ptr(df, bl);
}
}
static void compute_df_up(ir_node *bl, void *data)
{
pmap *df_map = ((dom_front_info_t *) data)->df_map;
ir_node *y;
for(y = get_Block_dominated_first(bl); y; y = get_Block_dominated_next(y)) {
ir_node *w;
pset *df = pmap_get(df_map, y);
for(w = pset_first(df); df; w = pset_next(df))
if(!block_dominates(bl, w) || bl == w)
pset_insert_ptr(df, w);
}
}
dom_front_info_t *be_compute_dominance_frontiers(ir_graph *irg)
{
dom_front_info_t *info = malloc(sizeof(*info));
info->df_map = pmap_create();
/* Perhaps both can we interwined */
dom_tree_walk_irg(irg, compute_df_local, NULL, info);
dom_tree_walk_irg(irg, NULL, compute_df_up, info);
return info;
}
void be_free_dominance_frontiers(dom_front_info_t *info)
{
pmap_entry *ent;
for(ent = pmap_first(info->df_map); ent; ent = pmap_next(info->df_map))
del_pset(ent->value);
pmap_destroy(info->df_map);
free(info);
}
pset *be_get_dominance_frontier(dom_front_info_t *info, ir_node *block)
{
return pmap_get(info->df_map, block);
}
/**
* Algorithm to place the Phi-Functions.
* @see Appel, Modern Compiler Implementation in Java, 2nd ed., p. 399ff
*
* This function takes an original node and a set of already placed
* copies of that node called @p copies. It places phi nodes at the
* iterated dominance frontiers of these copies and puts these phi nodes
* in the @p copies set, since they are another form of copies of the
* original value.
*
* The rename phase (see below) is responsible for fixing up the usages
* of the original node.
*
* @param orig The original node.
* @param copies A set contianing nodes representing a copy of the
* original node. Each node must be inserted into the block's schedule.
* @param copy_blocks A set in which the blocks are recorded which
* contain a copy. This is just for efficiency in later phases (see
* rename).
*/
static void place_phi_functions(ir_node *orig, pset *copies,
pset *copy_blocks, dom_front_info_t *df_info)
{
int i;
ir_node *orig_block = get_nodes_block(orig);
ir_graph *irg = get_irn_irg(orig);
ir_mode *mode = get_irn_mode(orig);
pdeq *worklist = new_pdeq();
pset *phi_blocks = pset_new_ptr(8);
ir_node **ins = NULL;
void *it;
/*
* Allocate an array for all blocks where the copies and the original
* value were defined.
*/
int n_orig_blocks = pset_count(copy_blocks) + 1;
ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
/*
* Fill the array of definition blocks.
*/
orig_blocks[0] = get_nodes_block(orig);
/*
* Fill the worklist queue and the rest of the orig blocks array.
*/
for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
ir_node *copy_block = get_nodes_block(it);
assert(block_dominates(orig_block, copy_block)
&& "The block of the copy must be dominated by the block of the value");
pdeq_putr(worklist, it);
orig_blocks[i++] = copy_block;
}
while(!pdeq_empty(worklist)) {
ir_node *irn = pdeq_getl(worklist);
ir_node *bl = get_nodes_block(irn);
ir_node *y;
int n_preds = get_irn_arity(bl);
pset *df = be_get_dominance_frontier(df_info, bl);
for(y = pset_first(df); y; y = pset_next(df)) {
if(!pset_find_ptr(phi_blocks, y)) {
ir_node *phi;
int insert = 1;
/*
* Set the orig node as the only operand of the
* phi node.
*/
ins = realloc(ins, n_preds * sizeof(ins[0]));
for(i = 0; i < n_preds; ++i)
ins[0] = orig;
/* Insert phi node */