From 83c9157ff224552a9b16a73fe4a16451f4963831 Mon Sep 17 00:00:00 2001 From: Sebastian Hack Date: Wed, 11 May 2005 12:50:15 +0000 Subject: [PATCH] Added new arch interface --- ir/be/bearch.h | 375 +++++++++++++++++++++++++++++++------------- ir/be/bearch_firm.c | 124 ++++++++++----- ir/be/bechordal.c | 106 ++++--------- ir/be/bechordal.h | 2 +- ir/be/bechordal_t.h | 2 +- ir/be/bemain.c | 80 ++-------- ir/be/benumb.c | 8 - ir/be/beutil.c | 38 +++-- ir/be/beutil.h | 4 +- 9 files changed, 428 insertions(+), 311 deletions(-) diff --git a/ir/be/bearch.h b/ir/be/bearch.h index 568d90c79..e36130810 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -16,12 +16,15 @@ #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, @@ -41,6 +44,7 @@ struct _arch_register_t { 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 * @@ -56,41 +60,29 @@ static INLINE int _arch_register_get_index(const arch_register_t *reg) #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) { @@ -136,61 +128,245 @@ struct _arch_enum_t { }; 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. @@ -215,60 +391,45 @@ struct _arch_isa_if_t { */ 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 */ diff --git a/ir/be/bearch_firm.c b/ir/be/bearch_firm.c index cf5e5317e..f52dc931a 100644 --- a/ir/be/bearch_firm.c +++ b/ir/be/bearch_firm.c @@ -6,21 +6,20 @@ #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) { @@ -66,60 +65,99 @@ static const arch_register_class_t *firm_get_reg_class(int i) 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, }; diff --git a/ir/be/bechordal.c b/ir/be/bechordal.c index b8b7847e3..cadaf20bf 100644 --- a/ir/be/bechordal.c +++ b/ir/be/bechordal.c @@ -2,7 +2,11 @@ * 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 @@ -69,7 +73,7 @@ typedef struct _env_t { 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. */ @@ -423,6 +427,7 @@ static void dump_ifg(ir_graph *irg, set *edges, const char *filename) #endif /* BUILD_GRAPH */ + /** * Add an interval border to the list of a block's list * of interval border. @@ -516,7 +521,6 @@ static void pressure(ir_node *block, void *env_ptr) 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); @@ -532,7 +536,7 @@ static void pressure(ir_node *block, void *env_ptr) 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); } @@ -553,7 +557,7 @@ static void pressure(ir_node *block, void *env_ptr) * 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); @@ -573,7 +577,7 @@ static void pressure(ir_node *block, void *env_ptr) 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)); @@ -593,7 +597,7 @@ static void pressure(ir_node *block, void *env_ptr) * 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)); @@ -611,12 +615,8 @@ static void assign(ir_node *block, void *env_ptr) 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);*/ @@ -643,14 +643,16 @@ static void assign(ir_node *block, void *env_ptr) * 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)); @@ -663,7 +665,7 @@ static void assign(ir_node *block, void *env_ptr) * 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); /* @@ -671,83 +673,41 @@ static void assign(ir_node *block, void *env_ptr) * 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); } @@ -759,7 +719,7 @@ void be_ra_chordal_init(void) } 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); @@ -781,7 +741,7 @@ void be_ra_chordal(ir_graph *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 */ diff --git a/ir/be/bechordal.h b/ir/be/bechordal.h index 362d09306..ef97007e4 100644 --- a/ir/be/bechordal.h +++ b/ir/be/bechordal.h @@ -19,7 +19,7 @@ * @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); /** diff --git a/ir/be/bechordal_t.h b/ir/be/bechordal_t.h index 340362849..7898bd0d2 100644 --- a/ir/be/bechordal_t.h +++ b/ir/be/bechordal_t.h @@ -19,7 +19,7 @@ typedef struct _border_t { #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). */ diff --git a/ir/be/bemain.c b/ir/be/bemain.c index 12fbc016d..3fd710d98 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -28,6 +28,7 @@ #include "bearch.h" #include "becopyoptmain.h" #include "becopystat.h" +#include "bearch_firm.h" #include "beasm_dump_globals.h" #include "beasm_asm_gnu.h" @@ -37,68 +38,9 @@ #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(); @@ -110,13 +52,23 @@ void be_init(void) #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; @@ -142,10 +94,10 @@ static void be_main_loop(void) 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); diff --git a/ir/be/benumb.c b/ir/be/benumb.c index 04dc9c71b..db88ac47e 100644 --- a/ir/be/benumb.c +++ b/ir/be/benumb.c @@ -25,13 +25,6 @@ FIRM_IMPL1(get_block_node_count, int, const ir_node *) 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)); @@ -73,7 +66,6 @@ void be_numbering_done(ir_graph *irg) 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)); } diff --git a/ir/be/beutil.c b/ir/be/beutil.c index 730bda510..09c88cb5c 100644 --- a/ir/be/beutil.c +++ b/ir/be/beutil.c @@ -14,27 +14,37 @@ #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 = ", "; } } @@ -52,18 +62,20 @@ static void dump_allocated_block(ir_node *block, void *env) } } -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); } } diff --git a/ir/be/beutil.h b/ir/be/beutil.h index 44abe1a6a..7420f4400 100644 --- a/ir/be/beutil.h +++ b/ir/be/beutil.h @@ -7,6 +7,8 @@ #include "irnode.h" #include "config.h" +#include "bearch.h" + /** Undefine this to disable debugging mode. */ #define BE_DEBUG 1 @@ -51,7 +53,7 @@ void localize_consts(ir_graph *irg); * @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); -- 2.20.1