Commit 4c66ebcc authored by Sebastian Hack's avatar Sebastian Hack
Browse files

Made everything really kaputt

parent 6de7c7d7
......@@ -22,8 +22,8 @@ SOURCES = $(INSTALL_HEADERS)
SOURCES += Makefile.in besched.h belistsched.h belistsched.c \
beutil.h bemain.c besched.c bemain.c belive.c belive.h benumb.h \
benumb_t.h benumb.c bechordal.c bera.c beutil.c \
bera.h bechordalspill.c beasm_dump_globals.c beasm_asm_gnu.c \
becopyoptmain.c becopyopt.c becopyheur.c \
bera.h bechordalspill.c bechordal_main.c \
becopyoptmain.c becopyopt.c becopyheur.c beifg.c \
becopyilp.c becopystat.c bearch.c bechordal_draw.c \
bechordal_draw.h beirgmod.c beirgmod.h benode.c benode_t.h \
bessadestr.c beifg_std.c bespill.c bespillbelady.c bespillilp.c beuses.c
......
......@@ -5,4 +5,7 @@
void be_init(void);
void be_main(int argc, const char *argv[]);
typedef struct _be_main_env_t be_main_env_t;
typedef struct _be_options_t be_options_t;
#endif
......@@ -11,19 +11,31 @@
#include "debug.h"
#include "irgraph.h"
#include "be.h"
#include "beirgmod.h"
typedef struct _be_main_env_t {
struct _be_options_t {
char ilp_server[128];
char ilp_solver[128];
};
struct _be_main_env_t {
struct obstack obst;
struct _be_node_factory_t *node_factory;
struct _arch_env_t *arch_env;
struct _be_options_t *options;
firm_dbg_module_t *dbg;
} be_main_env_t;
};
typedef struct _be_main_session_env_t {
const be_main_env_t *main_env;
#if 0
struct _be_main_session_env_t {
const struct _be_main_env_t *main_env;
ir_graph *irg;
struct _dom_front_info_t *dom_front;
} be_main_session_env_t;
};
#endif
#endif
......@@ -26,10 +26,10 @@
#include "pset.h"
#include "entity.h"
arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa)
arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa_if)
{
memset(env, 0, sizeof(*env));
env->isa = isa;
env->isa = isa_if->init();
return env;
}
......@@ -105,19 +105,13 @@ int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
return 0;
}
int arch_get_n_operands(const arch_env_t *env, const ir_node *irn, int in_out)
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
return ops->get_n_operands(ops, irn, in_out);
}
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(ops, &local_req, irn, pos);
return req != NULL;
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(ops, &local_req, irn, pos);
return req != NULL;
}
int arch_reg_is_allocatable(const arch_env_t *env, const ir_node *irn,
......@@ -154,19 +148,17 @@ arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos)
}
extern const arch_register_t *
arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx)
arch_get_irn_register(const arch_env_t *env, const ir_node *irn)
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
assert(idx >= 0);
return ops->get_irn_reg(ops, irn, idx);
return ops->get_irn_reg(ops, irn);
}
extern void arch_set_irn_register(const arch_env_t *env,
ir_node *irn, int idx, const arch_register_t *reg)
ir_node *irn, const arch_register_t *reg)
{
const arch_irn_ops_t *ops = get_irn_ops(env, irn);
assert(idx >= 0);
ops->set_irn_reg(ops, irn, idx, reg);
ops->set_irn_reg(ops, irn, reg);
}
extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn)
......
......@@ -3,6 +3,10 @@
#include "firm_config.h"
#ifdef WITH_LIBCORE
#include <libcore/lc_opts.h>
#endif
#include "irnode.h"
#include "irmode.h"
......@@ -13,14 +17,19 @@
#include "list.h"
#include "ident.h"
typedef struct _arch_register_class_t arch_register_class_t;
typedef struct _arch_register_t arch_register_t;
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;
#include "belistsched.h"
typedef struct _arch_register_class_t arch_register_class_t;
typedef struct _arch_register_t arch_register_t;
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_isa_t arch_isa_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 struct _arch_code_generator_t arch_code_generator_t;
typedef struct _arch_code_generator_if_t arch_code_generator_if_t;
struct _be_node_factory_t;
......@@ -203,106 +212,39 @@ typedef enum _arch_irn_flags_t {
arch_irn_flags_rematerializable = 2
} arch_irn_flags_t;
/*
* Some words about positions and indices:
*
* Firm has the policy "One node per value", that's why there are
* Proj nodes. This view has its advantages, but in a backend
* setting where we talk about instructions (which can also have
* multiple results and not a single Tuple value) this is sometimes
* hard.
*
* Each node representing an instruction must provide information
* about the kind of its operands (where operands mean both input
* and output operands). Such an operand is addressed with a position
* which is infact a tuple {in, out} x N. The fact that a position
* is an input/output operand is encoded in the sign, so input operands
* go from 0..n-1 and output operands from -1..-m if the
* 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) _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) _BEARCH_TRANSFORM_INDEX(>=, index)
/**
* Check, if a position denotes an input operand.
* @param pos The position.
* @return 1, if the position denotes an input operand 0 if not.
*/
#define arch_pos_is_in(pos) ((pos) >= 0)
/**
* Check, if a position denotes an output operand.
* @param pos The position.
* @return 1, if the position denotes an output operand 0 if not.
*/
#define arch_pos_is_out(pos) (!arch_pos_is_in(pos))
/**
* Get the index of a position.
* @param pos The position.
* @return The index of the position.
*/
#define arch_pos_get_index(pos) _BEARCH_TRANSFORM_INDEX(<, pos)
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.
* @param pos The operand's position
* (-1 for the result of the node, 0..n for the input
* operands).
* @return The register requirements for the selected operand.
* The pointer returned is never NULL.
*/
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.
* @param irn The node.
* @param in_out Denotes wither input (a number >= 0) or
* output (a number < 0).
* @return The number of operands for either in, or output.
*/
int (*get_n_operands)(const arch_irn_ops_t *self, const ir_node *irn, int in_out);
arch_register_req_t *req, const ir_node *irn, int pos);
/**
* Set the register for an output operand.
* @param irn The node.
* @param pos The position of the output operand.
* @param reg The register allocated to that operand.
* @note If the operand is not a register operand,
* the call is ignored.
*/
void (*set_irn_reg)(const arch_irn_ops_t *self, ir_node *irn,
int idx, const arch_register_t *reg);
void (*set_irn_reg)(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg);
/**
* Get the register allocated for an output operand.
* @param irn The node.
* @param pos The index of the output operand.
* @return The register allocated at that operand. NULL, if
* the operand was no register operand or
* @c arch_register_invalid, if no register has yet been
* allocated for this node.
*/
const arch_register_t *(*get_irn_reg)(const arch_irn_ops_t *self,
const ir_node *irn, int idx);
const arch_register_t *(*get_irn_reg)(const arch_irn_ops_t *self, const ir_node *irn);
/**
* Classify the node.
......@@ -321,9 +263,6 @@ struct _arch_irn_ops_t {
};
extern int
arch_get_n_operands(const arch_env_t *env, const ir_node *irm, int in_out);
/**
* Get the register requirements for a node.
* @param env The architecture environment.
......@@ -392,11 +331,10 @@ arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos);
* Get the register allocated at a certain output operand of a node.
* @param env The arch nvironment.
* @param irn The node.
* @param idx The index of the output operand.
* @return The register allocated for this operand
*/
extern const arch_register_t *
arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx);
arch_get_irn_register(const arch_env_t *env, const ir_node *irn);
/**
* Set the register for a certain output operand.
......@@ -405,8 +343,8 @@ arch_get_irn_register(const arch_env_t *env, const ir_node *irn, int idx);
* @param idx The index of the output operand.
* @param reg The register.
*/
extern void arch_set_irn_register(const arch_env_t *env,
ir_node *irn, int idx, const arch_register_t *reg);
extern void arch_set_irn_register(const arch_env_t *env, ir_node *irn,
const arch_register_t *reg);
/**
* Classify a node.
......@@ -443,36 +381,90 @@ struct _arch_irn_handler_t {
};
/**
* The code generator.
*/
struct _arch_code_generator_if_t {
/**
* Called, when the graph is being normalized.
*/
void (*prepare_graph)(void *self);
/**
* Called before scheduling.
*/
void (*before_sched)(void *self);
/**
* Called before register allocation.
*/
void (*before_ra)(void *self);
/**
* Called after everything happened.
* The code generator must also be de-allocated here.
*/
void (*done)(void *self);
};
#define _arch_cg_call(cg, func) \
do { \
if((cg)->impl->func) \
(cg)->impl->func(cg); \
} while(0)
#define arch_code_generator_prepare_graph(cg) _arch_cg_call(cg, prepare_graph)
#define arch_code_generator_before_sched(cg) _arch_cg_call(cg, before_sched)
#define arch_code_generator_before_ra(cg) _arch_cg_call(cg, before_ra)
#define arch_code_generator_done(cg) _arch_cg_call(cg, done)
/**
* Code generator base class.
*/
struct _arch_code_generator_t {
const arch_code_generator_if_t *impl;
};
/**
* ISA base class.
*/
struct _arch_isa_t {
const arch_isa_if_t *impl;
};
/**
* Architecture interface.
*/
struct _arch_isa_if_t {
#ifdef WITH_LIBCORE
void (*register_options)(lc_opt_entry_t *grp);
#endif
/**
* Initialize the isa interface.
*/
void (*init)(void);
void *(*init)(void);
/**
* Free the isa instance.
*/
void (*done)(void *self);
/**
* Get the the number of register classes in the isa.
* @return The number of register classes.
*/
int (*get_n_reg_class)(void);
int (*get_n_reg_class)(const void *self);
/**
* Get the i-th register class.
* @param i The number of the register class.
* @return The register class.
*/
const arch_register_class_t *(*get_reg_class)(int i);
/**
* Prepare a graph.
* This function is called each time, the back end starts running over
* a graph.
* @param irg The graph.
*/
void (*prepare_graph)(ir_graph *irg);
const arch_register_class_t *(*get_reg_class)(const void *self, int i);
/**
* The irn handler for this architecture.
......@@ -480,16 +472,29 @@ struct _arch_isa_if_t {
* when the architecture is initialized.
* (May be NULL).
*/
const arch_irn_handler_t *irn_handler;
const arch_irn_handler_t *(*get_irn_handler)(const void *self);
/**
* The code generation function for this architecture.
* (May be NULL)
* @param out The output file
* Produce a new code generator.
* @param self The this pointer.
* @param irg The graph for which code shall be generated.
* @return A code generator.
*/
void (*codegen)(FILE *out);
arch_code_generator_t *(*make_code_generator)(void *self, ir_graph *irg);
/**
* Get the list scheduler to use.
* @param self The isa object.
* @return The list scheduler selector.
*/
const list_sched_selector_t *(*get_list_sched_selector)(const void *self);
};
#define arch_isa_get_n_reg_class(isa) ((isa)->impl->get_n_reg_class(isa))
#define arch_isa_get_reg_class(isa,i) ((isa)->impl->get_reg_class(isa, i))
#define arch_isa_get_irn_handler(isa) ((isa)->impl->get_irn_handler(isa))
#define arch_isa_make_code_generator(isa,irg) ((isa)->impl->make_code_generator(isa, irg))
#define ARCH_MAX_HANDLERS 8
/**
......@@ -498,7 +503,7 @@ struct _arch_isa_if_t {
*/
struct _arch_env_t {
const struct _be_node_factory_t *node_factory; /**< The node factory for be nodes. */
const arch_isa_if_t *isa; /**< The isa about which everything is. */
arch_isa_t *isa; /**< The isa about which everything is. */
arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /**< The handlers are organized as
a stack. */
......
......@@ -34,6 +34,7 @@
#include "besched_t.h"
#include "belive_t.h"
#include "bearch.h"
#include "beifg.h"
#include "bechordal_t.h"
#include "bechordal_draw.h"
......@@ -44,139 +45,21 @@
#define NO_COLOR (-1)
#undef DUMP_INTERVALS
#undef DUMP_PRESSURE
#undef DUMP_IFG
#if defined(DUMP_IFG) && !defined(BUILD_GRAPH)
#error Must define BUILD_GRAPH to be able to dump it.
#endif
typedef struct _be_chordal_alloc_env_t {
be_chordal_env_t *chordal_env;
bitset_t *live; /**< A liveness bitset. */
bitset_t *colors; /**< The color mask. */
bitset_t *in_colors; /**< Colors used by live in values. */
int colors_n; /**< The number of colors. */
} be_chordal_alloc_env_t;
#include "fourcc.h"
/* Make a fourcc for border checking. */
#define BORDER_FOURCC FOURCC('B', 'O', 'R', 'D')
static firm_dbg_module_t *dbg;
#ifdef BUILD_GRAPH
#define IF_EDGE_HASH(e) ((e)->src ^ (e)->tgt)
#define IF_NODE_HASH(n) ((n)->nnr)
static int if_edge_cmp(const void *p1, const void *p2, size_t size)
{
const if_edge_t *e1 = p1;
const if_edge_t *e2 = p2;
return !(e1->src == e2->src && e1->tgt == e2->tgt);
}
static int if_node_cmp(const void *p1, const void *p2, size_t size)
{
const if_node_t *n1 = p1;
const if_node_t *n2 = p2;
return n1->nnr != n2->nnr;
}
static INLINE if_edge_t *edge_init(if_edge_t *edge, int src, int tgt)
{
/* Bring the smaller entry to src. */
if(src > tgt) {
edge->src = tgt;
edge->tgt = src;
} else {
edge->src = src;
edge->tgt = tgt;
}
return edge;
}
static INLINE void add_if(const be_chordal_env_t *env, int src, int tgt)
{
if_edge_t edge;
if_node_t node, *src_node, *tgt_node;
/* insert edge */
edge_init(&edge, src, tgt);
set_insert(env->edges, &edge, sizeof(edge), IF_EDGE_HASH(&edge));
/* insert nodes */
node.nnr = src;
node.neighb = pset_new_ptr(8);
src_node = set_insert(env->nodes, &node, sizeof(node), IF_NODE_HASH(&node));
node.nnr = tgt;
node.neighb = pset_new_ptr(8);
tgt_node = set_insert(env->nodes, &node, sizeof(node), IF_NODE_HASH(&node));
/* insert neighbors into nodes */
pset_insert_ptr(src_node->neighb, tgt_node);
pset_insert_ptr(tgt_node->neighb, src_node);
}
static INLINE int are_connected(const be_chordal_env_t *env, int src, int tgt)
{
if_edge_t edge;
edge_init(&edge, src, tgt);
return set_find(env->edges, &edge, sizeof(edge), IF_EDGE_HASH(&edge)) != NULL;
}
int ifg_has_edge(const be_chordal_env_t *env, const if_node_t *n1, const if_node_t* n2) {
return are_connected(env, n1->nnr, n2->nnr);
}
#ifdef DUMP_IFG
static void dump_ifg(const be_chordal_env_t *env)
{
FILE *f;
set *edges = env->edges;
ir_graph *irg = env->irg;
char filename[128];
ir_snprintf(filename, sizeof(filename), "ifg_%s_%F.dot", env->cls->name, irg);
if((f = fopen(filename, "wt")) != NULL) {
bitset_pos_t pos;
int n_edges = 0;
if_edge_t *edge;
bitset_t *bs = bitset_malloc(get_graph_node_count(irg));
ir_fprintf(f, "graph \"%F\" {\n", irg);
fprintf(f, "\tnode [shape=box,style=filled]\n");
for(edge = set_first(edges); edge; edge = set_next(edges)) {
bitset_set(bs, edge->src);
bitset_set(bs, edge->tgt);
n_edges++;
}
fprintf(f, "\tx [label=\"nodes: %u, edges: %d\"]\n", bitset_popcnt(bs), n_edges);
bitset_foreach(bs, pos) {
int nr = (int) pos;
ir_node *irn = get_irn_for_graph_nr(irg, nr);
ir_fprintf(f, "\tn%d [label=\"%+F\"]\n", nr, irn);
}
for(edge = set_first(edges); edge; edge = set_next(edges)) {
fprintf(f, "\tn%d -- n%d [len=5]\n", edge->src, edge->tgt);
}
fprintf(f, "}\n");
fclose(f);
bitset_free(bs);
}
}
#endif /* DUMP_IFG */
#endif /* BUILD_GRAPH */
static void check_border_list(struct list_head *head)
{
border_t *x;
......@@ -220,7 +103,7 @@ static INLINE border_t *border_add(be_chordal_env_t *env, struct list_head *head
/* also allocate the def and tie it to the use. */
def = obstack_alloc(&env->obst, sizeof(*def));
memset(def, 0, sizeof(*def));
memset(def, 0, sizeof(*def));
b->other_end = def;
def->other_end = b;
......@@ -252,17 +135,21 @@ static INLINE border_t *border_add(be_chordal_env_t *env, struct list_head *head
b->irn = irn;
b->step = step;
list_add_tail(&b->list, head);
DBG((dbg, LEVEL_5, "\t\t%s adding %+F, step: %d\n",
is_def ? "def" : "use", irn, step));
DBG((env->dbg, LEVEL_5, "\t\t%s adding %+F, step: %d\n", is_def ? "def" : "use", irn, step));
return b;
}
/**
* Check, if an irn is of the register class currently under processing.
* @param env The chordal environment.
* @param irn The node.
* @return 1, if the node is of that register class, 0 if not.
*/
static INLINE int has_reg_class(const be_chordal_env_t *env, const ir_node *irn)
{
return arch_irn_has_reg_class(env->session_env->main_env->arch_env,
irn, arch_pos_make_out(0), env->cls);
return arch_irn_has_reg_class(env->main_env->arch_env, irn, -1, env->cls);
}