#include "bearch.h"
-#define ARCH_OBJ(name,x) typedef struct _arch_ ## name ## _t arch_ ## name ## _t;
-#include "bearch_obj.def"
-#undef ARCH_OBJ
-
struct _bitset_t;
+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 enum _arch_register_type_t {
arch_register_type_none = 0,
arch_register_type_write_invariant,
const arch_register_class_t *reg_class; /**< The class the register belongs to. */
int index; /**< The index of the register in the class. */
arch_register_type_t type; /**< The type of the register. */
+ void *data; /**< Custom data. */
};
static INLINE const arch_register_class_t *
#define arch_register_get_class(reg) _arch_register_get_class(reg)
#define arch_register_get_index(reg) _arch_register_get_index(reg)
-
-/**
- * A (sub-) set of registers.
- */
-struct _arch_register_set_t {
- const struct _arch_register_class_t *reg_class; /**< The register class for this set. */
- int *regs; /**< An array containing 0/1 at place i
- whether the register with index i is
- in the set or not. */
-};
-
-static INLINE int _arch_register_in_set(const arch_register_set_t *set,
- const arch_register_t *reg)
-{
- if(reg->reg_class != set->reg_class)
- return 0;
-
- return set->regs[reg->index];
-}
-
+#define arch_register_get_name(reg) ((reg)->name)
/**
* A class of registers.
* Like general purpose or floating point.
*/
struct _arch_register_class_t {
- const char *name; /**< The name of the register. */
- arch_register_set_t *set; /**< A register set containing all registers
- in this class. */
- int n_regs; /**< Number of registers in this class. */
- const arch_register_t *regs; /**< The array of registers. */
+ const char *name; /**< The name of the register. */
+ int n_regs; /**< Number of registers in this class. */
+ const arch_register_t *regs; /**< The array of registers. */
};
#define arch_register_class_n_regs(cls) ((cls)->n_regs)
+/**
+ * Put all registers in a class into a bitset.
+ * @param cls The class.
+ * @param bs The bitset. May be NULL.
+ * @return The number of registers in the class.
+ */
+extern int arch_register_class_put(const arch_register_class_t *cls,
+ struct _bitset_t *bs);
+
static INLINE const arch_register_t *
_arch_register_for_index(const arch_register_class_t *cls, int idx)
{
};
typedef enum _arch_operand_type_t {
-#define ARCH_OPERAND_TYPE(name,size_in_irn) arch_operand_type_ ## name,
-#include "bearch_operand_types.def"
-#undef ARCH_OPERAND_TYPE
+ arch_operand_type_invalid,
+ arch_operand_type_memory,
+ arch_operand_type_register,
+ arch_operand_type_immediate,
+ arch_operand_type_symconst,
arch_operand_type_last
} 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
+ are allowed. */
+
+ arch_register_req_type_limited, /** Only a real subset of
+ the class is allowed. */
+
+ arch_register_req_type_equal, /** The register must equal
+ another one at the node. */
+
+ arch_register_req_type_unequal, /** The register must be unequal
+ to some other at the node. */
+ arch_register_req_type_pair /** The register is part of a
+ register pair. */
+} arch_register_req_type_t;
/**
- * The data for the different flavours of operand types.
+ * Expresses requirements to register allocation for an operand.
+ */
+typedef struct _arch_register_req_t {
+ arch_register_req_type_t type; /** The type of the constraint. */
+ const arch_register_class_t *cls; /** The register class this
+ constraint belongs to. */
+ union {
+ int (*limited)(const ir_node *irn, int pos, struct _bitset_t *bs);
+ /** In case of the 'limited'
+ constraint, this function
+ must put all allowable
+ registers in the bitset and
+ return the number of registers
+ in the bitset. */
+
+ int pos; /** In case of the equal constraint,
+ this gives the position of the
+ operand to which the register of
+ this should be equal to. Same for
+ unequal. */
+ } data;
+} arch_register_req_t;
+
+/**
+ * Certain node classes which are relevent for the register allocator.
+ */
+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_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.
*/
-typedef union _arch_operand_data_t {
- const arch_register_set_t *set; /**< The set of valid registers is directly
- given. Note, that if an insn has no constraints,
- the set comprises all registers in the
- register class. */
- const arch_immediate_t *imm; /**< If the operand is an immediate
- operand, this describes the kind of
- immediate. */
+/**
+ * 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)
- const arch_enum_t *enm; /**< Some enumeration value. */
+/**
+ * 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))
- int same_as_pos; /**< 'Same as' position for equals. */
-} arch_operand_data_t;
+/**
+ * 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)
/**
- * An operand to an instruction.
+ * Check, if a position denotes an output operand.
+ * @param pos The position.
+ * @return 1, if the position denotes an output operand 0 if not.
*/
-struct _arch_operand_t {
- arch_operand_type_t type; /**< The type of the operand. */
- arch_operand_data_t data; /**< The payload. */
-};
+#define arch_pos_is_out(pos) (!arch_pos_is_in(pos))
/**
- * An instruction format.
+ * Get the index of a position.
+ * @param pos The position.
+ * @return The index of the position.
*/
-struct _arch_insn_format_t {
- int n_in; /**< Number of in operands. */
- int n_out; /**< Number of out operands. */
+#define arch_pos_get_index(pos) ((pos) < 0 ? -(pos) - 1 : (pos))
- arch_operand_t * const *in_operands; /**< In operands. */
- arch_operand_t * const *out_operands; /**< Out operands. */
-};
+typedef struct _arch_irn_ops_t {
+
+ /**
+ * Get the register requirements for a given operand.
+ * @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.
+ */
+ const arch_register_req_t *(*get_irn_reg_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 ir_node *irn, int in_out);
+
+ /**
+ * 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)(ir_node *irn, int idx, 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 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_ops_t;
/**
- * An instruction.
+ * Get the number of allocatable registers concerning
+ * a register class for an operand of a node.
+ * @param env The environment.
+ * @param irn The node.
+ * @param pos The postition of the node's operand.
+ * @param cls The register class.
+ * @param bs The bitset all allocatable registers shall be put into.
+ * Note, that you can also pass NULL here. If you don't,
+ * make sure, the bitset is as large as the register class
+ * has registers.
+ * @return The amount of registers allocatable for that operand.
*/
-struct _arch_insn_t {
- const arch_insn_format_t *format; /**< The format of the instruction. */
- ir_op *op; /**< The firm opcode for this insn. */
-};
+extern int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn,
+ int pos, const arch_register_class_t *cls, struct _bitset_t *bs);
-#define arch_insn_is_allocatable(insn,reg) \
- ((irn)->get_allocatable_regs(irn, cls, NULL) != 0)
+/**
+ * Check, if a register is assignable to an operand of a node.
+ * @param env The architecture environment.
+ * @param irn The node.
+ * @param pos The position of the operand.
+ * @param reg The register.
+ * @return 1, if the register might be allocated to the operand 0 if not.
+ */
+extern int arch_reg_is_allocatable(const arch_env_t *env,
+ const ir_node *irn, int pos, const arch_register_t *reg);
+
+/**
+ * Get the register class of an operand of a node.
+ * @param env The architecture environment.
+ * @param irn The node.
+ * @param idx The position of the operand.
+ * @return The register class of the operand or NULL, if
+ * operand is a non-register operand.
+ */
+extern const arch_register_class_t *
+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);
+
+/**
+ * Set the register for a certain output operand.
+ * @param env The architecture environment.
+ * @param irn The node.
+ * @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);
+
+#define arch_irn_has_reg_class(env, irn, pos, cls) \
+ ((cls) == arch_get_irn_reg_class(env, irn, pos))
+
+/**
+ * Somebody who can be asked about nodes.
+ */
+typedef struct _arch_irn_handler_t {
+
+ /**
+ * Get the operations of an irn.
+ * @param irn Some node.
+ * @return Operations for that irn.
+ */
+ const arch_irn_ops_t *(*get_irn_ops)(const ir_node *irn);
+
+} arch_irn_handler_t;
/**
* Architecture interface.
*/
const arch_register_class_t *(*get_reg_class)(int i);
- /**
- * Put all registers of a given class which are allocatable to a
- * certain node into a bitset.
- * The bitset contains the indices of the registers concerning
- * the register class @p cls.
- * @param irn The node.
- * @param cls The register class.
- * @param bs The bitset. Can be NULL.
- * @return The number of registers which are allocatable at this node.
- */
- int (*get_allocatable_regs)(const ir_node *irn,
- const arch_register_class_t *cls, struct _bitset_t *bs);
-
- int (*is_reg_allocatable)(const ir_node *irn, const arch_register_t *reg);
+};
- /**
- * Get the register class, the value of a node belongs to.
- * @param irn The node.
- * @return The register class of the registers which can hold the
- * value of irn. If the node does not return a value, or possesses no
- * suitable register class, NULL is returned.
- */
- const arch_register_class_t *(*get_irn_reg_class)(const ir_node *irn);
+#define ARCH_MAX_HANDLERS 8
+/**
+ * Environment for the architecture infrastructure.
+ * Keep this everywhere you're going.
+ */
+struct _arch_env_t {
+ const arch_isa_if_t *isa; /** The isa about which everything is. */
+ arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /** The handlers are organized as
+ a stack. */
- /**
- * Get an op for a name.
- * @note This method may not be implemented.
- * @param name The name of the op.
- * @return The op with that name.
- */
- ir_op *(*get_op_by_name)(const char *name);
+ int handlers_tos; /** The stack pointer of the handler
+ stack. */
};
/**
- * Check, if the value of a node can be stored in a
- * specific register class.
- * @param isa The isa.
- * @param irn The node.
- * @param cls The register class.
- * @return 1, if the value can be stored in the register class, 0 if
- * not.
+ * Get the isa of an arch environment.
+ * @param env The environment.
+ * @return The isa with which the env was initialized with.
*/
-#define arch_isa_irn_has_reg_class(isa, irn, cls) \
- ((isa)->get_irn_reg_class(irn) == (cls))
+#define arch_env_get_isa(env) ((env)->isa)
/**
- * Check, if a register is allocatable for an irn.
- * @param irn The node.
- * @param reg The register.
- * @return 1, if the register can be allocated to this node, 0 if not.
+ * Initialize the architecture environment struct.
+ * @param isa The isa which shall be put into the environment.
+ * @return The environment.
+ */
+extern arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa);
+
+/**
+ * Add a node handler to the environment.
+ * @param env The environment.
+ * @param handler A node handler.
+ * @return The environment itself.
*/
-#define arch_isa_reg_is_allocatable(irn, reg) \
- ((isa)->is_reg_allocatable(irn, reg))
+extern arch_env_t *arch_env_add_irn_handler(arch_env_t *env,
+ const arch_irn_handler_t *handler);
#endif /* _FIRM_BEARCH_H */
#include "bitset.h"
#include "bearch.h"
+#include "irreflect.h"
+
#define N_REGS 64
-static arch_register_t gp_regs[N_REGS];
-static arch_register_t fp_regs[N_REGS];
+static arch_register_t datab_regs[N_REGS];
static arch_register_class_t reg_classes[] = {
- { "gp", NULL, N_REGS, gp_regs },
- { "fp", NULL, N_REGS, fp_regs }
+ { "datab", N_REGS, datab_regs },
};
#define N_CLASSES \
(sizeof(reg_classes) / sizeof(reg_classes[0]))
-#define CLS_GP 0
-#define CLS_FP 1
+#define CLS_DATAB 0
static void firm_init(void)
{
return ®_classes[i];
}
-static const arch_register_class_t *firm_get_irn_reg_class(const ir_node *irn)
+static const arch_register_req_t firm_std_reg_req = {
+ arch_register_req_type_normal,
+ ®_classes[CLS_DATAB],
+ { NULL }
+};
+
+static const rflct_arg_t *get_arg(const ir_node *irn, int pos)
{
- ir_mode *mode = get_irn_mode(irn);
+ int sig = rflct_get_signature(irn);
+ const rflct_arg_t *args =
+ rflct_get_args(get_irn_opcode(irn), sig, arch_pos_is_in(pos));
+ return &args[arch_pos_get_index(pos)];
+}
- if(mode_is_float(mode))
- return ®_classes[CLS_FP];
- else if(mode_is_datab(mode))
- return ®_classes[CLS_GP];
+static const arch_register_req_t *
+firm_get_irn_reg_req(const ir_node *irn, int pos)
+{
+ return mode_is_datab(get_irn_mode(irn)) ? &firm_std_reg_req : NULL;
+}
- return NULL;
+static int firm_get_n_operands(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);
}
-static int firm_get_allocatable_regs(const ir_node *irn,
- const arch_register_class_t *cls, bitset_t *bs)
+struct irn_reg_assoc {
+ const ir_node *irn;
+ int pos;
+ const arch_register_t *reg;
+};
+
+static int cmp_irn_reg_assoc(const void *a, const void *b, size_t len)
{
- int res = 0;
+ const struct irn_reg_assoc *x = a;
+ const struct irn_reg_assoc *y = b;
- if(firm_get_irn_reg_class(irn) != cls) {
- if(bs)
- bitset_clear_all(bs);
- }
+ return !(x->irn == y->irn && x->pos == y->pos);
+}
- else {
- int i;
+static struct irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, int pos)
+{
+ static set *reg_set = NULL;
+ struct irn_reg_assoc templ;
+ unsigned int hash;
- res = cls->n_regs;
- if(bs) {
- for(i = 0; i < cls->n_regs; ++i)
- bitset_set(bs, i);
- }
- }
+ if(!reg_set)
+ reg_set = new_set(cmp_irn_reg_assoc, 1024);
+
+ templ.irn = irn;
+ templ.pos = pos;
+ templ.reg = NULL;
+ hash = HASH_PTR(irn) + 7 * pos;
- return res;
+ return set_insert(reg_set, &templ, sizeof(templ), hash);
}
-static int firm_is_reg_allocatable(const ir_node *irn, const arch_register_t *reg)
+static void firm_set_irn_reg(ir_node *irn, int pos, const arch_register_t *reg)
{
- const arch_register_class_t *cls = reg->reg_class;
- ir_mode *irm = get_irn_mode(irn);
+ struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
+ assoc->reg = reg;
+}
- if(mode_is_float(irm))
- return cls == ®_classes[CLS_FP];
- else if(mode_is_datab(irm))
- return cls == ®_classes[CLS_GP];
+static const arch_register_t *firm_get_irn_reg(const ir_node *irn, int pos)
+{
+ struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
+ return assoc->reg;
+}
- return 0;
+static arch_irn_class_t firm_classify(const ir_node *irn)
+{
+ return arch_irn_class_normal;
}
-const arch_isa_if_t arch_isa_if_firm = {
+static const arch_irn_ops_t irn_ops = {
+ firm_get_irn_reg_req,
+ firm_get_n_operands,
+ firm_set_irn_reg,
+ firm_get_irn_reg,
+ firm_classify
+};
+
+const arch_isa_if_t firm_isa = {
firm_init,
firm_get_n_reg_class,
- firm_get_reg_class,
- firm_get_allocatable_regs,
- firm_is_reg_allocatable,
- firm_get_irn_reg_class,
- NULL
+ firm_get_reg_class
+};
+
+static const arch_irn_ops_t *firm_get_irn_ops(const ir_node *irn)
+{
+ return &irn_ops;
+}
+
+const arch_irn_handler_t firm_irn_handler = {
+ firm_get_irn_ops,
};
* Chordal register allocation.
* @author Sebastian Hack
* @date 8.12.2004
+ *
+ * Copyright (C) Universitaet Karlsruhe
+ * Released under the GPL
*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
bitset_t *colors; /**< The color mask. */
bitset_t *in_colors; /**< Colors used by live in values. */
int colors_n; /**< The number of colors. */
- const arch_isa_if_t *isa; /**< The isa interface. */
+ const arch_env_t *arch_env; /**< The arch interface environment. */
const arch_register_class_t *cls; /**< The current register class. */
void *data; /**< Some pointer, to which different
phases can attach data to. */
#endif /* BUILD_GRAPH */
+
/**
* Add an interval border to the list of a block's list
* of interval border.
pset *live_in = get_live_in(block);
pset *live_end = get_live_end(block);
const arch_register_class_t *cls = env->cls;
- const arch_isa_if_t *isa = env->isa;
DBG((dbg, LEVEL_1, "Computing pressure in block %n\n", block));
bitset_clear_all(live);
for(irn = pset_first(live_end); irn; irn = pset_next(live_end)) {
DBG((dbg, LEVEL_3, "\tMaking live: %n/%d\n", irn, get_irn_graph_nr(irn)));
bitset_set(live, get_irn_graph_nr(irn));
- if(arch_isa_irn_has_reg_class(isa, irn, cls))
+ if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls))
border_use(irn, step, 0);
}
* If the node defines some value, which can put into a
* register of the current class, make a border for it.
*/
- if(arch_isa_irn_has_reg_class(isa, irn, cls)) {
+ if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
bitset_pos_t elm;
int nr = get_irn_graph_nr(irn);
for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
ir_node *op = get_irn_n(irn, i);
- if(arch_isa_irn_has_reg_class(isa, op, cls)) {
+ if(arch_irn_has_reg_class(env->arch_env, op, 0, cls)) {
int nr = get_irn_graph_nr(op);
DBG((dbg, LEVEL_4, "\t\tpos: %d, use: %n\n", i, op));
* Add initial defs for all values live in.
*/
for(irn = pset_first(live_in); irn; irn = pset_next(live_in)) {
- if(arch_isa_irn_has_reg_class(isa, irn, cls)) {
+ if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
/* Mark the value live in. */
bitset_set(live, get_irn_graph_nr(irn));
bitset_t *live = env->live;
bitset_t *colors = env->colors;
bitset_t *in_colors = env->in_colors;
- const arch_isa_if_t *isa = env->isa;
const arch_register_class_t *cls = env->cls;
- /* The used colors will remain on the obstack. */
- bitset_t *used_colors = bitset_obstack_alloc(obst, env->colors_n);
-
/* Mark the obstack level and allocate the temporary tmp_colors */
void *obstack_level = obstack_base(obst);
/*bitset_t *tmp_colors = bitset_obstack_alloc(obst, env->colors_n);*/
* allocated before), we have to mark their colors as used also.
*/
for(irn = pset_first(live_in); irn; irn = pset_next(live_in)) {
- if(arch_isa_irn_has_reg_class(isa, irn, cls)) {
- int col = get_irn_color(irn);
+ if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
+ const arch_register_t *reg = arch_get_irn_register(env->arch_env, irn, 0);
+ int col;
+
+ assert(reg && "Nodfe must have been assigned a register");
+ col = arch_register_get_index(reg);
/* Mark the color of the live in value as used. */
- assert(is_color(col) && "Node must have been assigned a color.");
bitset_set(colors, col);
bitset_set(in_colors, col);
- bitset_set(used_colors, col);
/* Mark the value live in. */
bitset_set(live, get_irn_graph_nr(irn));
* will work.
*/
list_for_each_entry_reverse(border_t, b, head, list) {
- const ir_node *irn = b->irn;
+ ir_node *irn = b->irn;
int nr = get_irn_graph_nr(irn);
/*
* color.
*/
if(b->is_def && !is_live_in(block, irn)) {
- ra_node_info_t *ri = get_ra_node_info(irn);
+ const arch_register_t *reg;
int col = NO_COLOR;
DBG((dbg, LEVEL_4, "\tcolors in use: %b\n", colors));
- /*
- * Try to assign live out values colors which are not used by live
- * in values.
- */
-#if 0
- if(is_live_out(block, irn)) {
- int next_clear;
-
- bitset_copy(tmp_colors, colors);
- bitset_or(tmp_colors, in_colors);
- next_clear = bitset_next_clear(tmp_colors, 0);
- col = next_clear != -1 ? next_clear : NO_COLOR;
+ col = bitset_next_clear(colors, 0);
+ reg = arch_register_for_index(env->cls, col);
- DBG((dbg, LEVEL_5, "next clear in only outs %b: %d\n", tmp_colors, col));
- }
-#endif
-
- /* If a color is not yet assigned, do it now. */
- if(!is_color(col))
- col = bitset_next_clear(colors, 0);
-
- assert(!is_color(get_irn_color(irn)) && "Color must not have assigned");
- assert(!bitset_is_set(live, nr) && "Value def must not have been encountered");
+ assert(arch_get_irn_register(env->arch_env, irn, 0) == NULL
+ && "This node must not have been assigned a register yet");
+ assert(!bitset_is_set(live, nr) && "Value's definition must not have been encountered");
bitset_set(colors, col);
- bitset_set(used_colors, col);
bitset_set(live, nr);
- ri->color = col;
-
- DBG((dbg, LEVEL_1, "\tassigning color %d to %n\n", col, irn));
+ arch_set_irn_register(env->arch_env, irn, 0, reg);
+ DBG((dbg, LEVEL_1, "\tassigning register %s(%d) to %n\n",
+ arch_register_get_name(reg), col, irn));
}
/* Clear the color upon a use. */
else if(!b->is_def) {
- int col = get_irn_color(irn);
+ const arch_register_t *reg = arch_get_irn_register(env->arch_env, irn, 0);
+ int col;
+
+ assert(reg && "Register must have been assigned");
+ col = arch_register_get_index(reg);
assert(bitset_is_set(live, nr) && "Cannot have a non live use");
- assert(is_color(col) && "A color must have been assigned");
bitset_clear(colors, col);
bitset_clear(live, nr);
}
}
-#ifdef DUMP_PRESSURE
- {
- char buf[128];
- FILE *f;
-
- ir_snprintf(buf, sizeof(buf), "pres_%s_bl_%N.txt",
- get_entity_name(get_irg_entity(irg)), block);
-
- if((f = fopen(buf, "wt")) != NULL) {
- sched_foreach_reverse(block, irn) {
- if(arch_isa_irn_has_reg_class(isa, irn, cls))
- ir_fprintf(f, "\"%n\" %d %d\n", irn, sched_get_time_step(irn),
- get_ra_node_info(irn)->pressure);
-
- }
- fclose(f);
- }
- }
-#endif
-
-
- /*
- * Allocate the used colors array in the blocks ra info structure and
- * fill it.
- */
- get_ra_block_info(block)->used_colors = used_colors;
-
/* Free the auxillary data on the obstack. */
obstack_free(obst, obstack_level);
}
}
void be_ra_chordal(ir_graph *irg,
- const arch_isa_if_t *isa,
+ const arch_env_t *arch_env,
const arch_register_class_t *cls)
{
int node_count = get_graph_node_count(irg);
env->in_colors = bitset_obstack_alloc(&env->obst, colors_n);
env->colors_n = colors_n;
env->cls = cls;
- env->isa = isa;
+ env->arch_env = arch_env;
env->irg = irg;
/* First, determine the pressure */
* @return Some internal data to be freed with be_ra_chordal_done().
*/
void be_ra_chordal(ir_graph *irg,
- const arch_isa_if_t *isa,
+ const arch_env_t *arch_env,
const arch_register_class_t *cls);
/**
#endif
struct list_head list; /**< list head for queuing. */
struct _border_t *other_end; /**< The other end of the border. */
- const ir_node *irn; /**< The node. */
+ ir_node *irn; /**< The node. */
unsigned step; /**< The number equal to the interval border. */
unsigned pressure; /**< The pressure at this interval border.
(The border itself is counting). */
#include "bearch.h"
#include "becopyoptmain.h"
#include "becopystat.h"
+#include "bearch_firm.h"
#include "beasm_dump_globals.h"
#include "beasm_asm_gnu.h"
#define N_PHASES 256
-typedef struct _be_graph_info_t {
- bitset_t *applied_phases;
-} be_graph_info_t;
-
-static size_t be_info_offset = 0;
-
-#define get_irg_be_info(irg) get_irg_data(irg, be_graph_info_t, be_info_offset)
-
-static int phase_ids = 1;
-static struct obstack obst;
-
-int phase_register(phase_t *phase)
-{
- phase->id = phase_ids;
- return phase_ids++;
-}
-
-void phase_applied(const ir_graph *irg, const phase_t *phase)
-{
- be_graph_info_t *info = get_irg_be_info(irg);
-
- if(!info->applied_phases)
- info->applied_phases = bitset_obstack_alloc(&obst, N_PHASES);
-
- bitset_set(info->applied_phases, phase->id);
-}
-
-int phase_depends_on(const ir_graph *irg, const phase_t *phase, int n, ...)
-{
- int errors = 0;
- int i;
- va_list args;
-
- if(n > 0) {
- const be_graph_info_t *info = get_irg_be_info(irg);
- const bitset_t *applied_phases = info->applied_phases;
-
- va_start(args, n);
-
- for(i = 0; i < n; ++i) {
- const phase_t *dep_phase = va_arg(args, const phase_t *);
-
- if(!applied_phases || !bitset_is_set(applied_phases, dep_phase->id)) {
- errors++;
- fprintf(stderr, "phase dependency unfulfilled: \"%s\" depends on \"%s\"\n",
- phase->name, dep_phase->name);
- }
- }
-
- va_end(args);
-
- assert(errors > 0 && "There were phase dependency errors");
- }
-
- return errors;
-}
void be_init(void)
{
- obstack_init(&obst);
- be_info_offset = register_additional_graph_data(sizeof(be_graph_info_t));
-
be_sched_init();
be_liveness_init();
be_numbering_init();
#endif
}
-/* The preliminary Firm backend isa. */
-extern arch_isa_if_t arch_isa_if_firm;
+static void be_init_arch_env(arch_env_t *env)
+{
+ arch_env_init(env, &firm_isa);
+ arch_env_add_irn_handler(env, &firm_irn_handler);
+
+ env->isa->init();
+}
static void be_main_loop(void)
{
int i, n;
- const arch_isa_if_t *isa = &arch_isa_if_firm;
+ arch_env_t env;
+ const arch_isa_if_t *isa;
+
+ be_init_arch_env(&env);
+
+ isa = arch_env_get_isa(&env);
for(i = 0, n = get_irp_n_irgs(); i < n; ++i) {
int j, m;
for(j = 0, m = isa->get_n_reg_class(); j < m; ++j) {
const arch_register_class_t *cls = isa->get_reg_class(j);
- be_ra_chordal(irg, isa, cls);
+ be_ra_chordal(irg, &env, cls);
#ifdef DUMP_ALLOCATED
- dump_allocated_irg(irg, "");
+ dump_allocated_irg(&env, irg, "");
#endif
#ifdef DO_STAT
stat_collect_irg(irg);
FIRM_IMPL1(get_graph_block_count, int, const ir_graph *)
FIRM_IMPL2(get_irn_for_graph_nr, ir_node *, const ir_graph *, int)
-static phase_t phase_numbering_info = {
- "Numbering", 0
-};
-
-const phase_t *phase_numbering = &phase_numbering_info;
-
-
static void numbering_walker(ir_node *irn, void *env)
{
irg_numbering_t *graph_nr = get_irg_numbering(get_irn_irg(irn));
void be_numbering_init(void)
{
- phase_register(&phase_numbering_info);
numbering_irn_data_offset = register_additional_node_data(sizeof(numbering_t));
numbering_irg_data_offset = register_additional_graph_data(sizeof(irg_numbering_t));
}
#include "beutil.h"
#include "besched_t.h"
#include "bera_t.h"
+#include "bearch.h"
-static void dump_allocated_block(ir_node *block, void *env)
+struct dump_env {
+ FILE *f;
+ arch_env_t *env;
+};
+
+static void dump_allocated_block(ir_node *block, void *data)
{
int i, n;
const ir_node *irn;
- FILE *f = env;
+ struct dump_env *dump_env = data;
+ FILE *f = dump_env->f;
+ arch_env_t *env = dump_env->env;
ir_fprintf(f, "node:{title:\"b%N\"\nlabel:\"%n\n", block, block);
sched_foreach(block, irn) {
const char *prefix = "";
+ const arch_register_t *reg = arch_get_irn_register(env, irn, 0);
ir_fprintf(f, "\n");
- if(is_color(get_irn_color(irn)))
- ir_fprintf(f, "r%d = ", get_irn_color(irn));
+ if(reg)
+ ir_fprintf(f, "%s = ", arch_register_get_name(reg));
ir_fprintf(f, "%n(", irn);
if(block != get_irg_start_block(get_irn_irg(block))) {
for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
ir_node *op = get_irn_n(irn, i);
if(is_allocatable_irn(op)) {
- ir_fprintf(f, "%sr%d", prefix, get_irn_color(op));
+ ir_fprintf(f, "%s%s", prefix,
+ arch_register_get_name(arch_get_irn_register(env, op, 0)));
prefix = ", ";
}
}
}
}
-void dump_allocated_irg(ir_graph *irg, char *suffix)
+void dump_allocated_irg(arch_env_t *arch_env, ir_graph *irg, char *suffix)
{
char buf[1024];
- FILE *f;
+ struct dump_env env;
+
+ env.env = arch_env;
- snprintf(buf, sizeof(buf), "%s-alloc%s.vcg", get_entity_name(get_irg_entity(irg)), suffix);
+ ir_snprintf(buf, sizeof(buf), "%F-alloc%s.vcg", irg, suffix);
- if((f = fopen(buf, "wt")) != NULL) {
- fprintf(f, "graph:{title:\"prg\"\n");
- irg_block_walk_graph(irg, dump_allocated_block, NULL, f);
- fprintf(f, "}\n");
- fclose(f);
+ if((env.f = fopen(buf, "wt")) != NULL) {
+ fprintf(env.f, "graph:{title:\"prg\"\n");
+ irg_block_walk_graph(irg, dump_allocated_block, NULL, &env);
+ fprintf(env.f, "}\n");
+ fclose(env.f);
}
}
#include "irnode.h"
#include "config.h"
+#include "bearch.h"
+
/** Undefine this to disable debugging mode. */
#define BE_DEBUG 1
* @param irg The irg. Note that scheduling, register allocation must
* have been performed.
*/
-void dump_allocated_irg(ir_graph *irg, char *suffix);
+void dump_allocated_irg(arch_env_t *env, ir_graph *irg, char *suffix);