From 21d6dc90da67b8ef549565754b353e700e901cac Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 25 Jun 2007 23:11:31 +0000 Subject: [PATCH] adapt mips backend to new transform logic, use Immediate nodes, fixes [r14762] --- ir/be/mips/bearch_mips.c | 135 ++--- ir/be/mips/bearch_mips.h | 3 + ir/be/mips/bearch_mips_t.h | 1 + ir/be/mips/mips_emitter.c | 70 ++- ir/be/mips/mips_emitter.h | 12 +- ir/be/mips/mips_new_nodes.c | 247 +++++----- ir/be/mips/mips_new_nodes.h | 22 +- ir/be/mips/mips_nodes_attr.h | 28 +- ir/be/mips/mips_scheduler.c | 3 +- ir/be/mips/mips_spec.pl | 384 +++++++-------- ir/be/mips/mips_transform.c | 923 +++++++++++++++++++++-------------- ir/be/mips/mips_transform.h | 6 +- 12 files changed, 1036 insertions(+), 798 deletions(-) diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index f32a49ae2..3fb250641 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -154,8 +154,7 @@ static void mips_set_irn_reg(const void *self, ir_node *irn, slots = get_mips_slots(irn); slots[pos] = reg; - } - else { + } else { /* here we set the registers for the Phi nodes */ mips_set_firm_reg(irn, reg, cur_reg_set); } @@ -209,51 +208,76 @@ static arch_irn_flags_t mips_get_flags(const void *self, const ir_node *irn) (void) self; irn = skip_Proj_const(irn); - if (is_mips_irn(irn)) { - return get_mips_flags(irn); - } - else if (is_Unknown(irn)) { - return arch_irn_flags_ignore; - } + if (!is_mips_irn(irn)) + return 0; - return 0; + return get_mips_flags(irn); +} + +int mips_is_Load(const ir_node *node) +{ + return is_mips_lw(node) || is_mips_lh(node) || is_mips_lhu(node) || + is_mips_lb(node) || is_mips_lbu(node); +} + +int mips_is_Store(const ir_node *node) +{ + return is_mips_sw(node) || is_mips_sh(node) || is_mips_sb(node); } -static -ir_entity *mips_get_frame_entity(const void *self, const ir_node *node) +static ir_entity *mips_get_frame_entity(const void *self, const ir_node *node) { - const mips_attr_t *attr; + const mips_load_store_attr_t *attr; (void) self; if(!is_mips_irn(node)) return NULL; + if(!mips_is_Load(node) && !mips_is_Store(node)) + return NULL; - attr = get_mips_attr_const(node); + attr = get_mips_load_store_attr_const(node); return attr->stack_entity; } -static -void mips_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent) +static void mips_set_frame_entity(const void *self, ir_node *node, + ir_entity *entity) { - mips_attr_t *attr = get_mips_attr(irn); + mips_load_store_attr_t *attr; (void) self; - attr->stack_entity = ent; + + if(!is_mips_irn(node)) { + panic("trying to set frame entity on non load/store node %+F\n", node); + } + if(!mips_is_Load(node) && !mips_is_Store(node)) { + panic("trying to set frame entity on non load/store node %+F\n", node); + } + + attr = get_irn_generic_attr(node); + attr->stack_entity = entity; } /** * This function is called by the generic backend to correct offsets for * nodes accessing the stack. */ -static void mips_set_frame_offset(const void *self, ir_node *irn, int offset) +static void mips_set_frame_offset(const void *self, ir_node *node, int offset) { + mips_load_store_attr_t *attr; (void) self; - (void) irn; - (void) offset; - panic("TODO"); -#if 0 - mips_attr_t *attr = get_mips_attr(irn); - attr->stack_entity_offset = offset; -#endif + + if(!is_mips_irn(node)) { + panic("trying to set frame offset on non load/store node %+F\n", node); + } + if(!mips_is_Load(node) && !mips_is_Store(node)) { + panic("trying to set frame offset on non load/store node %+F\n", node); + } + + attr = get_irn_generic_attr(node); + attr->offset += offset; + + if(attr->offset < -32768 || attr->offset > 32767) { + panic("Out of stack space! (mips supports only 16bit offsets)"); + } } static int mips_get_sp_bias(const void *self, const ir_node *irn) @@ -465,8 +489,7 @@ static void mips_prepare_graph(void *self) { } // walk the graph and transform firm nodes into mips nodes where possible - irg_walk_blkwise_graph(cg->irg, mips_pre_transform_node, mips_transform_node, cg); - + mips_transform_graph(cg); dump_ir_block_graph_sched(cg->irg, "-transformed"); } @@ -559,6 +582,8 @@ static void *mips_cg_init(be_irg_t *birg) mips_irn_ops.cg = cg; + isa->cg = cg; + return (arch_code_generator_t *)cg; } @@ -584,6 +609,7 @@ static mips_isa_t mips_isa_template = { 5, /* reload costs */ }, NULL_EMITTER, /* emitter environment */ + NULL, /* cg */ }; /** @@ -690,9 +716,7 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap { mips_abi_env_t *env = self; ir_graph *irg = env->irg; - dbg_info *dbg = NULL; // TODO where can I get this from? ir_node *block = get_irg_start_block(env->irg); - mips_attr_t *attr; ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]); ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]); int initialstackframesize; @@ -709,11 +733,10 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap initialstackframesize = 24; // - setup first part of stackframe - sp = new_rd_mips_addiu(dbg, irg, block, sp); - attr = get_mips_attr(sp); - attr->tv = new_tarval_from_long(-initialstackframesize, mode_Is); + sp = new_rd_mips_addu(NULL, irg, block, sp, + mips_create_Immediate(initialstackframesize)); mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]); - //arch_set_irn_register(mips_get_arg_env(), sp, &mips_gp_regs[REG_SP]); + set_mips_flags(sp, arch_irn_flags_ignore); /* TODO: where to get an edge with a0-a3 int i; @@ -729,20 +752,18 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap */ reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]); - store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg); - attr = get_mips_attr(store); - attr->tv = new_tarval_from_long(16, mode_Hs); + store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 16); mm[4] = store; reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_RA]); - store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg); - attr = get_mips_attr(store); - attr->tv = new_tarval_from_long(20, mode_Hs); + store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 20); mm[5] = store; - // TODO ideally we would route these mem edges directly towards the epilogue + /* Note: ideally we would route these mem edges directly towards the + * epilogue, but this is currently not supported so we sync all mems + * together */ sync = new_r_Sync(irg, block, 2, mm+4); *mem = sync; } else { @@ -750,26 +771,22 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap initialstackframesize = 4; // save old framepointer - sp = new_rd_mips_addiu(dbg, irg, block, sp); - attr = get_mips_attr(sp); - attr->tv = new_tarval_from_long(-initialstackframesize, mode_Is); + sp = new_rd_mips_addu(NULL, irg, block, sp, + mips_create_Immediate(-initialstackframesize)); mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]); - //arch_set_irn_register(mips_get_arg_env(), sp, &mips_gp_regs[REG_SP]); + set_mips_flags(sp, arch_irn_flags_ignore); reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]); - store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg); - attr = get_mips_attr(store); - attr->tv = new_tarval_from_long(0, mode_Hs); + store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 0); *mem = store; } // setup framepointer - fp = new_rd_mips_addiu(dbg, irg, block, sp); - attr = get_mips_attr(fp); - attr->tv = new_tarval_from_long(initialstackframesize, mode_Is); + fp = new_rd_mips_addu(NULL, irg, block, sp, + mips_create_Immediate(-initialstackframesize)); mips_set_irn_reg(NULL, fp, &mips_gp_regs[REG_FP]); - //arch_set_irn_register(mips_get_arg_env(), fp, &mips_gp_regs[REG_FP]); + set_mips_flags(fp, arch_irn_flags_ignore); be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_FP], fp); be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_SP], sp); @@ -779,10 +796,9 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *reg_map) { - mips_abi_env_t *env = self; + mips_abi_env_t *env = self; + ir_graph *irg = env->irg; - dbg_info *dbg = NULL; // TODO where can I get this from? - mips_attr_t *attr; ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]); ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]); ir_node *load; @@ -790,15 +806,14 @@ static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *r int fp_save_offset = env->debug ? 16 : 0; // copy fp to sp - sp = new_rd_mips_move(dbg, irg, block, fp); + sp = new_rd_mips_or(NULL, irg, block, fp, mips_create_zero()); mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]); - //arch_set_irn_register(mips_get_arg_env(), fp, &mips_gp_regs[REG_SP]); + set_mips_flags(sp, arch_irn_flags_ignore); // 1. restore fp - load = new_rd_mips_lw(dbg, irg, block, *mem, sp); - attr = get_mips_attr(load); - // sp is at the fp address already, so we have to do fp_save_offset - initial_frame_size - attr->tv = new_tarval_from_long(fp_save_offset - initial_frame_size, mode_Hs); + load = new_rd_mips_lw(NULL, irg, block, sp, *mem, NULL, + fp_save_offset - initial_frame_size); + set_mips_flags(load, arch_irn_flags_ignore); fp = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_res); *mem = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_M); diff --git a/ir/be/mips/bearch_mips.h b/ir/be/mips/bearch_mips.h index 5496dbb45..b863ce9a7 100644 --- a/ir/be/mips/bearch_mips.h +++ b/ir/be/mips/bearch_mips.h @@ -44,4 +44,7 @@ void mips_set_block_sched_nr(ir_node *block, int nr); /** get a block schedule number */ int mips_get_block_sched_nr(ir_node *block); +int mips_is_Load(const ir_node *node); +int mips_is_Store(const ir_node *node); + #endif diff --git a/ir/be/mips/bearch_mips_t.h b/ir/be/mips/bearch_mips_t.h index edf83f7c5..afd85abff 100644 --- a/ir/be/mips/bearch_mips_t.h +++ b/ir/be/mips/bearch_mips_t.h @@ -52,6 +52,7 @@ struct mips_code_gen_t { struct mips_isa_t { arch_isa_t arch_isa; /**< must be derived from arch_isa_t */ be_emit_env_t emit; /**< An emitter environment for the GAS emitter. */ + mips_code_gen_t *cg; }; struct mips_irn_ops_t { diff --git a/ir/be/mips/mips_emitter.c b/ir/be/mips/mips_emitter.c index 6a1ea2589..158df07f4 100644 --- a/ir/be/mips/mips_emitter.c +++ b/ir/be/mips/mips_emitter.c @@ -229,27 +229,78 @@ static const char *node_const_to_str(ir_node *n) } #endif +void mips_emit_load_store_address(mips_emit_env_t *env, const ir_node *node, + int pos) +{ + const mips_load_store_attr_t *attr = get_mips_load_store_attr_const(node); + + be_emit_irprintf(env->emit, "%d(", attr->offset); + mips_emit_source_register(env, node, pos); + be_emit_char(env->emit, ')'); +} + +void mips_emit_immediate_suffix(mips_emit_env_t *env, const ir_node *node, + int pos) +{ + ir_node *op = get_irn_n(node, pos); + if(is_mips_Immediate(op)) + be_emit_char(env->emit, 'i'); +} + void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node) { - const mips_attr_t *attr = get_mips_attr_const(node); + const mips_immediate_attr_t *attr = get_mips_immediate_attr_const(node); + + switch(attr->imm_type) { + case MIPS_IMM_CONST: + be_emit_irprintf(env->emit, "%d", attr->val); + break; + case MIPS_IMM_SYMCONST_LO: + be_emit_cstring(env->emit, "%lo($"); + be_emit_ident(env->emit, get_entity_ld_ident(attr->entity)); + if(attr->val != 0) { + be_emit_irprintf(env->emit, "%+d", attr->val); + } + be_emit_char(env->emit, ')'); + break; + case MIPS_IMM_SYMCONST_HI: + be_emit_cstring(env->emit, "%hi($"); + be_emit_ident(env->emit, get_entity_ld_ident(attr->entity)); + if(attr->val != 0) { + be_emit_irprintf(env->emit, "%+d", attr->val); + } + be_emit_char(env->emit, ')'); + break; + default: + panic("invalid immediate type found"); + } +} - if(attr->tv != NULL) { - be_emit_tarval(env->emit, attr->tv); +/** + * Emit the name of the destination register at given output position. + */ +void mips_emit_source_register_or_immediate(mips_emit_env_t *env, + const ir_node *node, int pos) +{ + const ir_node *op = get_irn_n(node, pos); + if(is_mips_Immediate(op)) { + mips_emit_immediate(env, op); } else { - be_emit_cstring(env->emit, "/* TODO */ 0"); + mips_emit_source_register(env, node, pos); } } +#if 0 /* * Add a number to a prefix. This number will not be used a second time. */ -static -char *get_unique_label(char *buf, size_t buflen, const char *prefix) +static char *get_unique_label(char *buf, size_t buflen, const char *prefix) { static unsigned long id = 0; snprintf(buf, buflen, "%s%lu", prefix, ++id); return buf; } +#endif /************************************************************************/ /* ABI Handling */ @@ -450,6 +501,7 @@ void mips_emit_jump_or_fallthrough(mips_emit_env_t *env, const ir_node *node, * * ************************************************************************/ +#if 0 /* jump table entry (target and corresponding number) */ typedef struct _branch_t { ir_node *target; @@ -469,7 +521,8 @@ typedef struct _jmp_tbl_t { /** * Compare two variables of type branch_t. Used to sort all switch cases */ -static int mips_cmp_branch_t(const void *a, const void *b) { +static int mips_cmp_branch_t(const void *a, const void *b) +{ branch_t *b1 = (branch_t *)a; branch_t *b2 = (branch_t *)b; @@ -573,6 +626,7 @@ void dump_jump_tables(ir_node* node, void *data) be_emit_write_line(env->emit); } } +#endif /*********************************************************************************** * _ __ _ @@ -689,7 +743,7 @@ void mips_emit_func_prolog(mips_emit_env_t *env, ir_graph *irg) be_emit_env_t *eenv = env->emit; // dump jump tables - irg_walk_graph(irg, NULL, dump_jump_tables, env); + //irg_walk_graph(irg, NULL, dump_jump_tables, env); be_emit_write_line(eenv); be_gas_emit_switch_section(eenv, GAS_SECTION_TEXT); diff --git a/ir/be/mips/mips_emitter.h b/ir/be/mips/mips_emitter.h index 6b11d3b0b..7b65f01f6 100644 --- a/ir/be/mips/mips_emitter.h +++ b/ir/be/mips/mips_emitter.h @@ -42,9 +42,17 @@ struct mips_emit_env_t { mips_isa_t *isa; }; -void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, int pos); -void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, int pos); +void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, + int pos); +void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, + int pos); +void mips_emit_source_register_or_immediate(mips_emit_env_t *env, + const ir_node *node, int pos); void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node); +void mips_emit_immediate_suffix(mips_emit_env_t *env, const ir_node *node, + int pos); +void mips_emit_load_store_address(mips_emit_env_t *env, const ir_node *node, + int pos); void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node); void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, long pn); diff --git a/ir/be/mips/mips_new_nodes.c b/ir/be/mips/mips_new_nodes.c index 3683fa45a..126aea2c7 100644 --- a/ir/be/mips/mips_new_nodes.c +++ b/ir/be/mips/mips_new_nodes.c @@ -65,9 +65,12 @@ /** * Dumps the register requirements for either in or out. */ -static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) { +static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, + int inout) +{ + const mips_attr_t *attr = get_mips_attr_const(n); char *dir = inout ? "out" : "in"; - int max = inout ? get_mips_n_res(n) : get_irn_arity(n); + int max = inout ? ARR_LEN(attr->slots) : get_irn_arity(n); char buf[1024]; int i; @@ -116,11 +119,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, * @return 0 on success or != 0 on failure */ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { - ir_mode *mode = NULL; int bad = 0; int i; - mips_attr_t *attr; - char buf[64]; + const mips_attr_t *attr = get_mips_attr_const(n); const arch_register_req_t **reqs; const arch_register_t **slots; @@ -130,20 +131,15 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { break; case dump_node_mode_txt: - mode = get_irn_mode(n); - - if (mode) { - fprintf(F, "[%s]", get_mode_name(mode)); - } - else { - fprintf(F, "[?NOMODE?]"); - } break; case dump_node_nodeattr_txt: - /* TODO: dump some attributes which should show up */ - /* in node name in dump (e.g. consts or the like) */ + if(is_mips_Immediate(n)) { + const mips_immediate_attr_t *attr + = get_mips_immediate_attr_const(n); + fprintf(F, " %ld", attr->val); + } break; @@ -178,7 +174,7 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { fprintf(F, "\n"); /* dump n_res */ - fprintf(F, "n_res = %d\n", get_mips_n_res(n)); + fprintf(F, "n_res = %d\n", ARR_LEN(attr->slots)); /* dump flags */ fprintf(F, "flags ="); @@ -198,17 +194,6 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { } fprintf(F, " (%d)\n", attr->flags); - if(attr->stack_entity != NULL) { - fprintf(F, " stack entity %s\n", get_entity_name(attr->stack_entity)); - } - if(attr->tv != NULL) { - tarval_snprintf(buf, sizeof(buf), attr->tv); - fprintf(F, " tarval %s\n", buf); - } - if(attr->symconst != NULL) { - fprintf(F, " symconst '%s'\n", get_entity_name(attr->symconst)); - } - fprintf(F, "=== mips attr end ===\n"); /* end of: case dump_node_info_txt */ break; @@ -231,12 +216,27 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { * |___/ ***************************************************************************************************/ -mips_attr_t *get_mips_attr(ir_node *node) { +mips_attr_t *get_mips_attr(ir_node *node) +{ assert(is_mips_irn(node) && "need mips node to get attributes"); return (mips_attr_t *) get_irn_generic_attr(node); } -const mips_attr_t *get_mips_attr_const(const ir_node *node) { +const mips_attr_t *get_mips_attr_const(const ir_node *node) +{ + assert(is_mips_irn(node) && "need mips node to get attributes"); + return get_irn_generic_attr_const(node); +} + +const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node) +{ + assert(is_mips_irn(node) && "need mips node to get attributes"); + return get_irn_generic_attr_const(node); +} + +const mips_load_store_attr_t *get_mips_load_store_attr_const( + const ir_node *node) +{ assert(is_mips_irn(node) && "need mips node to get attributes"); return get_irn_generic_attr_const(node); } @@ -244,7 +244,8 @@ const mips_attr_t *get_mips_attr_const(const ir_node *node) { /** * Returns the argument register requirements of a mips node. */ -const arch_register_req_t **get_mips_in_req_all(const ir_node *node) { +const arch_register_req_t **get_mips_in_req_all(const ir_node *node) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->in_req; } @@ -252,7 +253,8 @@ const arch_register_req_t **get_mips_in_req_all(const ir_node *node) { /** * Returns the result register requirements of an mips node. */ -const arch_register_req_t **get_mips_out_req_all(const ir_node *node) { +const arch_register_req_t **get_mips_out_req_all(const ir_node *node) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->out_req; } @@ -260,7 +262,8 @@ const arch_register_req_t **get_mips_out_req_all(const ir_node *node) { /** * Returns the argument register requirement at position pos of an mips node. */ -const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) { +const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->in_req[pos]; } @@ -268,7 +271,8 @@ const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) { /** * Returns the result register requirement at position pos of an mips node. */ -const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) { +const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->out_req[pos]; } @@ -276,7 +280,8 @@ const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) { /** * Sets the OUT register requirements at position pos. */ -void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) { +void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) +{ mips_attr_t *attr = get_mips_attr(node); attr->out_req[pos] = req; } @@ -284,7 +289,8 @@ void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) { /** * Sets the IN register requirements at position pos. */ -void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) { +void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) +{ mips_attr_t *attr = get_mips_attr(node); attr->in_req[pos] = req; } @@ -292,7 +298,8 @@ void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) { /** * Returns the register flag of an mips node. */ -arch_irn_flags_t get_mips_flags(const ir_node *node) { +arch_irn_flags_t get_mips_flags(const ir_node *node) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->flags; } @@ -300,7 +307,8 @@ arch_irn_flags_t get_mips_flags(const ir_node *node) { /** * Sets the register flag of an mips node. */ -void set_mips_flags(ir_node *node, arch_irn_flags_t flags) { +void set_mips_flags(ir_node *node, arch_irn_flags_t flags) +{ mips_attr_t *attr = get_mips_attr(node); attr->flags = flags; } @@ -308,7 +316,8 @@ void set_mips_flags(ir_node *node, arch_irn_flags_t flags) { /** * Returns the result register slots of an mips node. */ -const arch_register_t **get_mips_slots(const ir_node *node) { +const arch_register_t **get_mips_slots(const ir_node *node) +{ const mips_attr_t *attr = get_mips_attr_const(node); return attr->slots; } @@ -316,7 +325,8 @@ const arch_register_t **get_mips_slots(const ir_node *node) { /** * Returns the name of the OUT register at position pos. */ -const char *get_mips_out_reg_name(const ir_node *node, int pos) { +const char *get_mips_out_reg_name(const ir_node *node, int pos) +{ const mips_attr_t *attr = get_mips_attr_const(node); assert(is_mips_irn(node) && "Not an mips node."); @@ -329,7 +339,8 @@ const char *get_mips_out_reg_name(const ir_node *node, int pos) { /** * Returns the index of the OUT register at position pos within its register class. */ -int get_mips_out_regnr(const ir_node *node, int pos) { +int get_mips_out_regnr(const ir_node *node, int pos) +{ const mips_attr_t *attr = get_mips_attr_const(node); assert(is_mips_irn(node) && "Not an mips node."); @@ -342,7 +353,8 @@ int get_mips_out_regnr(const ir_node *node, int pos) { /** * Returns the OUT register at position pos. */ -const arch_register_t *get_mips_out_reg(const ir_node *node, int pos) { +const arch_register_t *get_mips_out_reg(const ir_node *node, int pos) +{ const mips_attr_t *attr = get_mips_attr_const(node); assert(is_mips_irn(node) && "Not an mips node."); @@ -352,22 +364,14 @@ const arch_register_t *get_mips_out_reg(const ir_node *node, int pos) { return attr->slots[pos]; } -/** - * Returns the number of results. - */ -int get_mips_n_res(const ir_node *node) { - const mips_attr_t *attr = get_mips_attr_const(node); - return ARR_LEN(attr->slots); -} - /** * Initializes the nodes attributes. */ -void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, - const arch_register_req_t **in_reqs, - const arch_register_req_t **out_reqs, - const be_execution_unit_t ***execution_units, - int n_res, unsigned latency) +static void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, + const arch_register_req_t **in_reqs, + const arch_register_req_t **out_reqs, + const be_execution_unit_t ***execution_units, + int n_res, unsigned latency) { ir_graph *irg = get_irn_irg(node); struct obstack *obst = get_irg_obstack(irg); @@ -383,18 +387,30 @@ void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, memset(attr->slots, 0, n_res * sizeof(attr->slots[0])); } -static -int mips_compare_attr(ir_node *node_a, ir_node *node_b) +static void init_mips_immediate_attributes(ir_node *node, + mips_immediate_type_t type, + ir_entity *entity, long val) +{ + mips_immediate_attr_t *attr = get_irn_generic_attr(node); + + attr->imm_type = type; + attr->entity = entity; + attr->val = val; +} + +static void init_mips_load_store_attributes(ir_node *node, ir_entity *entity, + long offset) +{ + mips_load_store_attr_t *attr = get_irn_generic_attr(node); + attr->stack_entity = entity; + attr->offset = offset; +} + +static int mips_compare_nodes_attr(ir_node *node_a, ir_node *node_b) { const mips_attr_t *a = get_mips_attr_const(node_a); const mips_attr_t *b = get_mips_attr_const(node_b); - if(a->tv != b->tv) - return 1; - if(a->symconst != b->symconst) - return 1; - if(a->stack_entity != b->stack_entity) - return 1; if(a->flags != b->flags) return 1; if(ARR_LEN(a->slots) != ARR_LEN(b->slots)) @@ -405,86 +421,47 @@ int mips_compare_attr(ir_node *node_a, ir_node *node_b) return 0; } -/************************************************************************ - * ___ _____ _ _ _ - * |_ _| ___|__ | | __| (_)_ __ __ _ - * | || |_ / _ \| |/ _` | | '_ \ / _` | - * | || _| (_) | | (_| | | | | | (_| | - * |___|_| \___/|_|\__,_|_|_| |_|\__, | - * |___/ - ************************************************************************/ - -#if 0 -// test if a tarval can be expressed in a 16bit immediate value -static int is_tarval_16(ir_node* node) +static int mips_compare_immediate_attr(ir_node *node_a, ir_node *node_b) { - mips_attr_t *attr = get_mips_attr(node); - tarval* tv = attr->tv; - long val = get_tarval_long(tv); - if(get_mode_sign(get_irn_mode(node))) { - if(val < -32768 || val > 32767) - return 0; - } else { - unsigned long uval = (unsigned long) val; - if(uval > 65536) - return 0; - } + const mips_immediate_attr_t *a = get_mips_immediate_attr_const(node_a); + const mips_immediate_attr_t *b = get_mips_immediate_attr_const(node_b); - return 1; + if(a->attr.flags != b->attr.flags) + return 1; + if(a->val != b->val) + return 1; + + return 0; } -#define MIPS_MAKE_IFOLDING_TRANSFORM(srcnode, inode, commutative) \ -ir_node *mips_transform_##srcnode(ir_node* node) \ -{ \ - ir_node* op1 = get_irn_n(node, 0); \ - ir_node* op2 = get_irn_n(node, 1); \ - ir_node* result; \ - if(op1 == NULL || op2 == NULL) \ - return node; \ - \ - if((is_mips_lli(op2) || is_mips_lui(op2)) && is_tarval_16(op2)) { \ - mips_attr_t *attr, *op_attr = get_mips_attr(op2); \ - long val = get_tarval_long(op_attr->tv); \ - result = new_rd_mips_##inode(get_irn_dbg_info(node), get_irn_irg(node), get_nodes_block(node), \ - op1); \ - attr = get_mips_attr(result); \ - attr->tv = new_tarval_from_long(val, get_mode_sign(get_irn_mode(node)) ? mode_Hs : mode_Hu); \ - return result; \ - } \ - \ - if(commutative && (is_mips_lli(op1) || is_mips_lui(op1)) && is_tarval_16(op1)) { \ - mips_attr_t *attr, *op_attr = get_mips_attr(op1); \ - long val = get_tarval_long(op_attr->tv); \ - result = new_rd_mips_##inode(get_irn_dbg_info(node), get_irn_irg(node), get_nodes_block(node), \ - op2); \ - attr = get_mips_attr(result); \ - attr->tv = new_tarval_from_long(val, get_mode_sign(get_irn_mode(node)) ? mode_Hs : mode_Hu); \ - return result; \ - } \ - \ - return node; \ +static int mips_compare_load_store_attr(ir_node *node_a, ir_node *node_b) +{ + const mips_load_store_attr_t *a = get_mips_load_store_attr_const(node_a); + const mips_load_store_attr_t *b = get_mips_load_store_attr_const(node_b); + + if(mips_compare_nodes_attr(node_a, node_b)) + return 1; + if(a->stack_entity != b->stack_entity) + return 1; + if(a->offset != b->offset) + return 1; + + return 0; } -MIPS_MAKE_IFOLDING_TRANSFORM(addu, addiu, 1) -MIPS_MAKE_IFOLDING_TRANSFORM(and, andi, 1) -MIPS_MAKE_IFOLDING_TRANSFORM(or, ori, 1) -MIPS_MAKE_IFOLDING_TRANSFORM(sra, srai, 0) -MIPS_MAKE_IFOLDING_TRANSFORM(xor, xori, 1) -MIPS_MAKE_IFOLDING_TRANSFORM(sl, sli, 0) -MIPS_MAKE_IFOLDING_TRANSFORM(sr, sri, 0) -MIPS_MAKE_IFOLDING_TRANSFORM(slt, slti, 0) - -void mips_init_opcode_transforms(void) { - op_mips_addu->ops.transform_node = mips_transform_addu; - op_mips_and->ops.transform_node = mips_transform_and; - op_mips_or->ops.transform_node = mips_transform_or; - op_mips_sra->ops.transform_node = mips_transform_sra; - op_mips_xor->ops.transform_node = mips_transform_xor; - op_mips_sl->ops.transform_node = mips_transform_sl; - op_mips_sr->ops.transform_node = mips_transform_sr; - op_mips_slt->ops.transform_node = mips_transform_slt; +static void mips_copy_attr(const ir_node *old_node , ir_node *new_node) +{ + ir_graph *irg = get_irn_irg(new_node); + struct obstack *obst = get_irg_obstack(irg); + const mips_attr_t *attr_old = get_mips_attr_const(old_node); + mips_attr_t *attr_new = get_mips_attr(new_node); + + /* copy the attributes */ + memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node))); + + /* copy register assignments */ + attr_new->slots = DUP_ARR_D(arch_register_t*, obst, attr_old->slots); } -#endif /*************************************************************************************** * _ _ _ diff --git a/ir/be/mips/mips_new_nodes.h b/ir/be/mips/mips_new_nodes.h index 91497f658..ef7c7b377 100644 --- a/ir/be/mips/mips_new_nodes.h +++ b/ir/be/mips/mips_new_nodes.h @@ -44,6 +44,10 @@ */ mips_attr_t *get_mips_attr(ir_node *node); const mips_attr_t *get_mips_attr_const(const ir_node *node); +const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node); +const mips_load_store_attr_t *get_mips_load_store_attr_const( + const ir_node *node); + /** * Returns the argument register requirements of an mips node. */ @@ -104,24 +108,6 @@ int get_mips_out_regnr(const ir_node *node, int pos); */ const arch_register_t *get_mips_out_reg(const ir_node *node, int pos); -/** - * Returns the number of results. - */ -int get_mips_n_res(const ir_node *node); - - -/** - * Initializes the nodes attributes. - */ -void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_register_req_t **in_reqs, - const arch_register_req_t **out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency); - -/** - * Initialize transform ops for the mips opcodes - */ -void mips_init_opcode_transforms(void); - - /* Include the generated headers */ #include "gen_mips_new_nodes.h" diff --git a/ir/be/mips/mips_nodes_attr.h b/ir/be/mips/mips_nodes_attr.h index eae48cd0d..37f78a73e 100644 --- a/ir/be/mips/mips_nodes_attr.h +++ b/ir/be/mips/mips_nodes_attr.h @@ -28,15 +28,12 @@ #include "../bearch_t.h" #include "irmode_t.h" +#include "irnode_t.h" -typedef struct _mips_attr_t { +typedef struct mips_attr_t { + except_attr exc; /**< the exception attribute. MUST be the first one. */ arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */ - tarval *tv; /**< contains the immediate value */ - ir_entity *symconst; - - ir_mode *original_mode; /**< contains the original mode of the node */ - ir_entity *stack_entity; /**< contains the entity on the stack for a load/store mode */ int switch_default_pn; /**< proj number of default case in switch */ const arch_register_req_t **in_req; /**< register requirements for arguments */ @@ -45,4 +42,23 @@ typedef struct _mips_attr_t { const arch_register_t **slots; /**< register slots for assigned registers */ } mips_attr_t; +typedef enum mips_immediate_type_t { + MIPS_IMM_CONST, + MIPS_IMM_SYMCONST_LO, + MIPS_IMM_SYMCONST_HI +} mips_immediate_type_t; + +typedef struct mips_immediate_attr_t { + mips_attr_t attr; + mips_immediate_type_t imm_type; + ir_entity *entity; + long val; +} mips_immediate_attr_t; + +typedef struct mips_load_store_attr_t { + mips_attr_t attr; + ir_entity *stack_entity; + long offset; +} mips_load_store_attr_t; + #endif diff --git a/ir/be/mips/mips_scheduler.c b/ir/be/mips/mips_scheduler.c index 645bea1b8..5ab8ca697 100644 --- a/ir/be/mips/mips_scheduler.c +++ b/ir/be/mips/mips_scheduler.c @@ -208,8 +208,7 @@ int mips_to_appear_in_schedule(void *block_env, const ir_node *node) if(!is_mips_irn(node)) return -1; - - if(is_mips_zero(node)) + if(is_mips_zero(node) || is_mips_Immediate(node)) return 0; return 1; diff --git a/ir/be/mips/mips_spec.pl b/ir/be/mips/mips_spec.pl index 61664c460..e93e2be7e 100644 --- a/ir/be/mips/mips_spec.pl +++ b/ir/be/mips/mips_spec.pl @@ -121,23 +121,47 @@ $new_emit_syntax = 1; { name => "sp", type => 4 }, # stack pointer { name => "fp", type => 4 }, # frame pointer { name => "ra", type => 2+1 }, # return address + { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes { mode => "mode_Iu" } ], ); # %reg_classes %emit_templates = ( - S0 => "${arch}_emit_source_register(env, node, 0);", - S1 => "${arch}_emit_source_register(env, node, 1);", - S2 => "${arch}_emit_source_register(env, node, 2);", - D0 => "${arch}_emit_dest_register(env, node, 0);", - D1 => "${arch}_emit_dest_register(env, node, 1);", - D2 => "${arch}_emit_dest_register(env, node, 2);", - C => "${arch}_emit_immediate(env, node);", + S0 => "${arch}_emit_source_register(env, node, 0);", + S1 => "${arch}_emit_source_register(env, node, 1);", + S2 => "${arch}_emit_source_register(env, node, 2);", + SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);", + D0 => "${arch}_emit_dest_register(env, node, 0);", + D1 => "${arch}_emit_dest_register(env, node, 1);", + D2 => "${arch}_emit_dest_register(env, node, 2);", + A0 => "${arch}_emit_load_store_address(env, node, 0);", + I => "${arch}_emit_immediate_suffix(env, node, 1);", + C => "${arch}_emit_immediate(env, node);", JumpTarget => "${arch}_emit_jump_target(env, node);", JumpTarget1 => "${arch}_emit_jump_target_proj(env, node, 1);", JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(env, node, 0);", ); +$default_attr_type = "mips_attr_t"; +$default_copy_attr = "mips_copy_attr"; + +$mode_gp = "mode_Iu"; + +%init_attr = ( + mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", + + mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n". + "\tinit_mips_immediate_attributes(res, imm_type, entity, val);", + + mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n". + "\tinit_mips_load_store_attributes(res, entity, offset);", +); + +%compare_attr = ( + mips_attr_t => "mips_compare_nodes_attr", + mips_immediate_attr_t => "mips_compare_immediate_attr", + mips_load_store_attr_t => "mips_compare_load_store_attr", +); #--------------------------------------------------# # _ # @@ -152,6 +176,16 @@ $new_emit_syntax = 1; %nodes = ( +Immediate => { + state => "pinned", + op_flags => "c", + irn_flags => "I", + reg_req => { out => [ "gp_NOREG" ] }, + attr => "mips_immediate_type_t imm_type, ir_entity *entity, long val", + attr_type => "mips_immediate_attr_t", + mode => $mode_gp, +}, + #-----------------------------------------------------------------# # _ _ _ # # (_) | | | | # @@ -166,210 +200,146 @@ $new_emit_syntax = 1; # commutative operations addu => { - op_flags => "C", + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. addu %D0, %S0, %S1', - mode => "mode_Iu", -}, - -addiu => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. addiu %D0, %S0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu", + ins => [ "left", "right" ], + emit => '. add%I%.u %D0, %S0, %SI1', + mode => $mode_gp, }, and => { - op_flags => "C", + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. and %D0, %S0, %S1', - mode => "mode_Iu", -}, - -andi => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. andi %D0, %S0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu", + ins => [ "left", "right" ], + emit => '. and%I %D0, %S0, %SI1', + mode => $mode_gp, }, div => { - reg_req => { in => [ "gp", "gp" ], out => [ "none" ] }, + reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] }, + ins => [ "left", "right" ], + outs => [ "lohi", "M" ], emit => '. div %S0, %S1', mode => "mode_M", }, divu => { - reg_req => { in => [ "gp", "gp" ], out => [ "none" ] }, + reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] }, + ins => [ "left", "right" ], + outs => [ "lohi", "M" ], emit => '. divu %S0, %S1', mode => "mode_M", }, mult => { - op_flags => "C", reg_req => { in => [ "gp", "gp" ], out => [ "none" ] }, + ins => [ "left", "right" ], emit => '. mult %S0, %S1', mode => "mode_M" }, multu => { - op_flags => "C", reg_req => { in => [ "gp", "gp" ], out => [ "none" ] }, + ins => [ "left", "right" ], emit => '. multu %S0, %S1', mode => "mode_M", }, nor => { - op_flags => "C", + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. nor %D0, %S0, %S1', - mode => "mode_Iu" -}, - -not => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. nor %D0, %S0, $zero', - mode => "mode_Iu" + emit => '. nor%I %D0, %S0, %SI1', + mode => $mode_gp }, or => { - op_flags => "C", + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. or %D0, %S0, %S1', - mode => "mode_Iu" -}, - -ori => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. ori %D0, %S0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu" + ins => [ "left", "right" ], + emit => '. or%I %D0, %S0, %SI1', + mode => $mode_gp }, -sl => { +sll => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => ' - if (mode_is_signed(get_irn_mode(node))) { - . sal %D0, %S0, %S1 - } else { - . sll %D0, %S0, %S1 - } -', - mode => "mode_Iu", -}, - -sli => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => ' - if (mode_is_signed(get_irn_mode(node))) { - . sal %D0, %S0, %C - } else { - . sll %D0, %S0, %C - } -', - mode => "mode_Iu", + ins => [ "left", "right" ], + emit => '. sll %D0, %S0, %SI1', + mode => $mode_gp, }, sra => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. sra %D0, %S0, %S1', - mode => "mode_Iu" -}, - -srai => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. sra %D0, %S0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu", -}, - -sr => { - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => ' - if (mode_is_signed(get_irn_mode(node))) { - . sra %D0, %S0, %S1 - } else { - . srl %D0, %S0, %S1 - } -', - mode => "mode_Iu", -}, - -sri => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => ' - if (mode_is_signed(get_irn_mode(node))) { - . sra %D0, %S0, %C - } else { - . srl %D0, %S0, %C - } -', - mode => "mode_Iu" -}, - -srlv => { - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. srlv %D0, %S0, %S1', - mode => "mode_Iu" + ins => [ "left", "right" ], + emit => '. sra %D0, %S0, %SI1', + mode => $mode_gp }, -sllv => { +srl => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. sllv %D0, %S0, %S1', - mode => "mode_Iu" + ins => [ "left", "right" ], + emit => '. srl %D0, %S0, %SI1', + mode => $mode_gp, }, -sub => { +subu => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + ins => [ "left", "right" ], emit => '. subu %D0, %S0, %S1', - mode => "mode_Iu" -}, - -subuzero => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. subu %D0, $zero, %S0', - mode => "mode_Iu", + mode => $mode_gp }, xor => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. xor %D0, %S0, %S1', - mode => "mode_Iu", + ins => [ "left", "right" ], + emit => '. xor%I %D0, %S0, %SI1', + mode => $mode_gp, }, -xori => { +seb => { + op_flags => "R", reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. xori %D0, %S0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu", + ins => [ "val" ], + emit => '.seb %D0, %S0', + mode => $mode_gp, }, -# ____ _ _ -# / ___|___ _ __ ___| |_ __ _ _ __ | |_ ___ -# | | / _ \| '_ \/ __| __/ _` | '_ \| __/ __| -# | |__| (_) | | | \__ \ || (_| | | | | |_\__ \ -# \____\___/|_| |_|___/\__\__,_|_| |_|\__|___/ -# +seh => { + op_flags => "R", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + ins => [ "val" ], + emit => '.seh %D0, %S0', + mode => $mode_gp, +}, -# load upper imediate lui => { op_flags => "c", + irn_flags => "R", reg_req => { out => [ "gp" ] }, - emit => '. lui %D0, %C', - cmp_attr => 'return attr_a->tv != attr_b->tv;', - mode => "mode_Iu", + emit => '.lui %D0, %C', + attr_type => "mips_immediate_attr_t", + attr => "mips_immediate_type_t imm_type, ir_entity *entity, long val", + mode => $mode_gp, }, mflo => { + irn_flags => "R", reg_req => { in => [ "none" ], out => [ "gp" ] }, + ins => [ "lohi" ], emit => '. mflo %D0', - mode => "mode_Iu" + mode => $mode_gp }, mfhi => { + irn_flags => "R", reg_req => { in => [ "none" ], out => [ "gp" ] }, + ins => [ "lohi" ], emit => '. mfhi %D0', - mode => "mode_Iu" + mode => $mode_gp }, zero => { @@ -378,7 +348,7 @@ zero => { irn_flags => "I", reg_req => { out => [ "zero" ] }, emit => '', - mode => "mode_Iu" + mode => $mode_gp }, # @@ -391,27 +361,17 @@ zero => { # slt => { + op_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. slt %D0, %S0, %S1', - mode => "mode_Iu", + emit => '. slt%I %D0, %S0, %SI1', + mode => $mode_gp, }, sltu => { - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. sltu %D0, %S0, %S1', - mode => "mode_Iu", -}, - -slti => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. slti %D0, %S0, %C', - mode => "mode_Iu", -}, - -sltiu => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. slti %D0, %S0, %C', - mode => "mode_Iu", + op_flags => "R", + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + emit => '. slt%I%.u %D0, %S0, %SI1', + mode => $mode_gp, }, beq => { @@ -474,73 +434,91 @@ SwitchJump => { # lw => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp" ], out => [ "gp", "none" ] }, - outs => [ "res", "M" ], - emit => '. lw %D0, %C(%S1)', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + emit => '. lw %D0, %A0', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, lh => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp" ], out => [ "gp", "none" ] }, - outs => [ "res", "M" ], - emit => '. lh %D0, %C(%S1)', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + emit => '. lh %D0, %A0', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, lhu => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp" ], out => [ "gp", "none" ] }, - outs => [ "res", "M" ], - emit => '. lhu %D0, %C(%S1)', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + emit => '. lhu %D0, %A0', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, lb => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp" ], out => [ "gp", "none" ] }, - outs => [ "res", "M" ], - emit => '. lb %D0, %C(%S1)', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + emit => '. lb %D0, %A0', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, lbu => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp" ], out => [ "gp", "none" ] }, - outs => [ "res", "M" ], - emit => '. lbu %D0, %C(%S1)', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + emit => '. lbu %D0, %A0', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, sw => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp", "gp" ], out => [ "none" ] }, - emit => '. sw %S2, %C(%S1)', - mode => 'mode_M', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "ptr", "val", "mem" ], + emit => '. sw %S1, %A0', + mode => 'mode_M', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, sh => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp", "gp" ], out => [ "none" ] }, - emit => '. sh %S2, %C(%S1)', - mode => 'mode_M', + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "ptr", "val", "mem" ], + emit => '. sh %S1, %A0', + mode => 'mode_M', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, sb => { - op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "none", "gp", "gp" ], out => [ "none" ] }, - emit => '. sb %S2, %C(%S1)', - mode => 'mode_M', -}, - -move => { - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. move %D0, %S0', - mode => "mode_Iu" + op_flags => "L|F", + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "ptr", "val", "mem" ], + emit => '. sb %S1, %A0', + mode => 'mode_M', + attr_type => "mips_load_store_attr_t", + attr => "ir_entity *entity, long offset", }, # diff --git a/ir/be/mips/mips_transform.c b/ir/be/mips/mips_transform.c index 4db5dd924..7c8b9eb36 100644 --- a/ir/be/mips/mips_transform.c +++ b/ir/be/mips/mips_transform.c @@ -36,6 +36,8 @@ #include "iredges.h" #include "irvrfy.h" #include "ircons.h" +#include "irprintf.h" +#include "irop.h" #include "dbginfo.h" #include "iropt_t.h" #include "debug.h" @@ -46,6 +48,7 @@ #include "../besched.h" #include "../besched_t.h" #include "../beirg_t.h" +#include "../betranshlp.h" #include "bearch_mips_t.h" #include "mips_nodes_attr.h" @@ -58,6 +61,9 @@ #include "gen_mips_regalloc_if.h" +/** hold the current code generator during transformation */ +static mips_code_gen_t *env_cg = NULL; + /**************************************************************************************************** * _ _ __ _ _ * | | | | / _| | | (_) @@ -68,145 +74,314 @@ * ****************************************************************************************************/ -#define MIPS_GENBINFUNC(mips_nodetype) \ - static ir_node* mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op1, ir_node *op2) {\ - ASSERT_NO_FLOAT(env->mode); \ - /*assert(get_irn_mode(op1) == get_irn_mode(op2));*/ \ - /*assert(get_irn_mode(op1) == env->mode);*/ \ - assert(get_mode_size_bits(env->mode) == 32); \ - return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op1, op2); \ - } +typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, + ir_node *block, ir_node *left, ir_node *right); -MIPS_GENBINFUNC(addu) -MIPS_GENBINFUNC(sub) -MIPS_GENBINFUNC(and) -MIPS_GENBINFUNC(or) -MIPS_GENBINFUNC(xor) -MIPS_GENBINFUNC(sl) -MIPS_GENBINFUNC(sr) -MIPS_GENBINFUNC(sra) - -#define MIPS_GENUNFUNC(mips_nodetype) \ - static ir_node *mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op) { \ - ASSERT_NO_FLOAT(env->mode); \ - assert(get_irn_mode(op) == env->mode); \ - assert(get_mode_size_bits(env->mode) == 32); \ - return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op); \ - } +static INLINE int mode_needs_gp_reg(ir_mode *mode) { + return mode_is_int(mode) || mode_is_character(mode) + || mode_is_reference(mode); +} -MIPS_GENUNFUNC(not) +ir_node *mips_create_Immediate(long val) +{ + ir_graph *irg = current_ir_graph; + ir_node *block = get_irg_start_block(irg); + const arch_register_t **slots; + ir_node *res; -static -ir_node* gen_zero(mips_transform_env_t *env) + assert(val >= -32768 && val <= 32767); + res = new_rd_mips_Immediate(NULL, irg, block, MIPS_IMM_CONST, NULL, + val); + slots = get_mips_slots(res); + slots[0] = &mips_gp_regs[REG_GP_NOREG]; + + return res; +} + +ir_node* mips_create_zero(void) { - ir_graph *irg = env->irg; + ir_graph *irg = current_ir_graph; ir_node *block = get_irg_start_block(irg); ir_node *zero = new_rd_mips_zero(NULL, irg, block); + const arch_register_t **slots = get_mips_slots(zero); - arch_set_irn_register(env->cg->arch_env, zero, &mips_gp_regs[REG_ZERO]); + slots[0] = &mips_gp_regs[REG_ZERO]; return zero; } -static -ir_node* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant) +static ir_node *try_create_Immediate(ir_node *node) { - tarval* tv = get_Const_tarval(constant); - ir_node *upper_node; - ir_node *lower_node; - mips_attr_t *attr; - ir_mode* mode = get_irn_mode(constant); + tarval *tv; + long val; + ir_mode *mode; + + if(!is_Const(node)) + return NULL; + + mode = get_irn_mode(node); + if(!mode_needs_gp_reg(mode)) + return NULL; + + tv = get_Const_tarval(node); + if(tarval_is_long(tv)) { + val = get_tarval_long(tv); + } else if(tarval_is_null(tv)) { + val = 0; + } else { + ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n", + node); + return NULL; + } + + if(val < -32768 || val > 32767) + return NULL; + + return mips_create_Immediate(val); +} + +static void create_binop_operands(ir_node **new_left, ir_node **new_right, + ir_node *left, ir_node *right, + int is_commutative) +{ + *new_right = try_create_Immediate(right); + if(*new_right != NULL) { + *new_left = be_transform_node(left); + return; + } + if(is_commutative) { + *new_right = try_create_Immediate(left); + if(*new_right != NULL) { + *new_left = be_transform_node(right); + return; + } + } + + *new_left = be_transform_node(left); + *new_right = be_transform_node(right); +} + +static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right, + construct_binop_func func, int supports_immediate) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *res; + ir_node *new_left, *new_right; + + assert(mode_needs_gp_reg(get_irn_mode(node))); + + if(supports_immediate) { + int is_commutative = is_op_commutative(get_irn_op(node)); + create_binop_operands(&new_left, &new_right, left, right, + is_commutative); + } else { + new_left = be_transform_node(left); + new_right = be_transform_node(right); + } + + res = func(dbgi, irg, block, new_left, new_right); + + return res; +} + +static ir_node *gen_Add(ir_node *node) +{ + /* TODO: match add(symconst, const) */ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_addu, 1); +} + +static ir_node *gen_Sub(ir_node *node) +{ + return gen_binop(node, get_Sub_left(node), get_Sub_right(node), + new_rd_mips_addu, 0); +} + +static ir_node *gen_And(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_and, 1); +} + +static ir_node *gen_Or(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_or, 1); +} + +static ir_node *gen_Eor(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_xor, 1); +} + +static ir_node *gen_Shl(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_sll, 1); +} + +static ir_node *gen_Shr(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_srl, 1); +} + +static ir_node *gen_Shrs(ir_node *node) +{ + return gen_binop(node, get_Add_left(node), get_Add_right(node), + new_rd_mips_sra, 1); +} + +static ir_node *gen_Not(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Not_op(node); + ir_node *new_op; + ir_node *res; + ir_node *one; + + /* we can transform not->or to nor */ + if(is_Or(op)) { + return gen_binop(op, get_Or_left(op), get_Or_right(op), + new_rd_mips_nor, 1); + } + + /* construct (op < 1) */ + one = mips_create_Immediate(1); + new_op = be_transform_node(op); + res = new_rd_mips_sltu(dbgi, irg, block, new_op, one); + + return res; +} + +static ir_node *gen_Minus(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Minus_op(node); + ir_node *new_op = be_transform_node(op); + ir_node *res; + ir_node *zero; + + /* construct (0 - op) */ + zero = mips_create_zero(); + res = new_rd_mips_subu(dbgi, irg, block, zero, new_op); + + return res; +} + +static ir_node *gen_Abs(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Abs_op(node); + ir_node *new_op = be_transform_node(op); + ir_node *sra_const, *sra, *add, *xor; + + /* TODO: support other bit sizes... */ + assert(get_mode_size_bits(get_irn_mode(node)) == 32); + sra_const = mips_create_Immediate(31); + sra = new_rd_mips_sra(dbgi, irg, block, new_op, sra_const); + add = new_rd_mips_addu(dbgi, irg, block, new_op, sra); + xor = new_rd_mips_xor(dbgi, irg, block, sra, add); + + return xor; +} + +static ir_node* gen_Const(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + tarval *tv = get_Const_tarval(node); + ir_node *upper_node; + ir_node *lower_node; + ir_node *or_const; unsigned long val, lower, upper; + if(tarval_is_long(tv)) { + val = get_tarval_long(tv); + } else if(tarval_is_null(tv)) { + val = 0; + } else { + panic("Can't get value of tarval %+F\n", node); + } + val = get_tarval_long(tv); lower = val & 0xffff; upper = (val >> 16) & 0xffff; if(upper == 0) { - upper_node = gen_zero(env); + upper_node = mips_create_zero(); } else { - upper_node = new_rd_mips_lui(dbg, irg, block); - attr = get_mips_attr(upper_node); - attr->tv = new_tarval_from_long(val, mode); + upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL, + upper); } if(lower == 0) return upper_node; - lower_node = new_rd_mips_ori(dbg, irg, block, upper_node); - attr = get_mips_attr(lower_node); - attr->tv = new_tarval_from_long(lower, mode); + or_const = mips_create_Immediate(lower); + lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const); return lower_node; } -static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) { - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(pred); - ir_graph *irg = get_irn_irg(node); - ir_node *block; - - if(get_irn_opcode(node) == iro_Phi) { - ir_node *phipred = get_nodes_block(node); - block = get_Block_cfgpred_block(phipred, n); - } else { - block = get_nodes_block(node); - } - - return gen_node_for_Const(env, dbg, irg, block, pred); -} - -static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred) +static ir_node* gen_SymConst(ir_node *node) { - mips_attr_t *attr; - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(pred); - ir_graph *irg = get_irn_irg(node); - ir_node *block; + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); ir_entity *entity; - ir_node *lui, *ori; + ir_node *lui, *or_const, *or; - block = get_nodes_block(pred); - - if(get_SymConst_kind(pred) != symconst_addr_ent) { + if(get_SymConst_kind(node) != symconst_addr_ent) { panic("Only address entity symconsts supported in mips backend"); } - entity = get_SymConst_entity(pred); - - lui = new_rd_mips_lui(dbg, irg, block); - attr = get_mips_attr(lui); - attr->symconst = entity; + entity = get_SymConst_entity(node); - ori = new_rd_mips_ori(dbg, irg, block, lui); - attr = get_mips_attr(ori); - attr->symconst = entity; + lui = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_SYMCONST_HI, + entity, 0); + or_const = new_rd_mips_Immediate(dbgi, irg, block, + MIPS_IMM_SYMCONST_LO, entity, 0); + or = new_rd_mips_or(dbgi, irg, block, lui, or_const); - return ori; + return or; } typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg, - ir_node *block, ir_node *mem, ir_node *ptr); + ir_node *block, ir_node *ptr, ir_node *mem, + ir_entity *entity, long offset); /** * Generates a mips node for a firm Load node */ -static ir_node *gen_node_for_Load(mips_transform_env_t *env) { - ir_graph *irg = env->irg; - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *mem = get_Load_mem(node); - ir_node *ptr = get_Load_ptr(node); - ir_mode *mode = get_Load_mode(node); - int sign = get_mode_sign(mode); - ir_node *result; +static ir_node *gen_Load(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *mem = get_Load_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_node *ptr = get_Load_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_mode *mode = get_Load_mode(node); + int sign = get_mode_sign(mode); + ir_node *res; gen_load_func func; - ASSERT_NO_FLOAT(get_irn_mode(node)); + ASSERT_NO_FLOAT(mode); + assert(mode_needs_gp_reg(mode)); - assert(mode->vector_elem == 1); - assert(mode->sort == irms_int_number || mode->sort == irms_reference); + /* TODO: make use of offset in ptrs */ switch(get_mode_size_bits(mode)) { case 32: @@ -222,33 +397,35 @@ static ir_node *gen_node_for_Load(mips_transform_env_t *env) { panic("mips backend only support 32, 16, 8 bit loads"); } - result = func(dbg, irg, block, mem, ptr); - return result; + res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0); + set_irn_pinned(res, get_irn_pinned(node)); + + return res; } typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg, - ir_node *block, ir_node *mem, ir_node *ptr, - ir_node *val); + ir_node *block, ir_node *ptr, ir_node *val, + ir_node *mem, ir_entity *ent, long offset); /** * Generates a mips node for a firm Store node */ -static ir_node *gen_node_for_Store(mips_transform_env_t *env) { - ir_graph *irg = env->irg; - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *mem = get_Store_mem(node); - ir_node *ptr = get_Store_ptr(node); - ir_node *val = get_Store_value(node); - ir_mode *mode = get_irn_mode(val); +static ir_node *gen_Store(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *mem = get_Store_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_node *ptr = get_Store_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *val = get_Store_value(node); + ir_node *new_val = be_transform_node(val); + ir_mode *mode = get_irn_mode(val); gen_store_func func; - ir_node *result; - - ASSERT_NO_FLOAT(mode); + ir_node *res; - assert(mode->vector_elem == 1); - assert(mode->sort == irms_int_number || mode->sort == irms_reference); + assert(mode_needs_gp_reg(mode)); switch(get_mode_size_bits(mode)) { case 32: @@ -264,96 +441,150 @@ static ir_node *gen_node_for_Store(mips_transform_env_t *env) { panic("store only supported for 32, 16, 8 bit values in mips backend"); } - result = func(dbg, irg, block, mem, ptr, val); - return result; -} + res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0); + set_irn_pinned(res, get_irn_pinned(node)); -static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) { - ir_node *proj = env->irn; - ir_node *new_proj; - ir_node *pred = get_irn_n(proj, 0); - mips_attr_t *attr; - long n; + return res; +} - n = get_Proj_proj(proj); +static ir_node *gen_Proj_DivMod(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *divmod = get_Proj_pred(node); + ir_node *new_div = be_transform_node(divmod); + long pn = get_Proj_proj(node); + ir_node *proj; - // set the div mode to the DivMod node - attr = get_mips_attr(pred); - assert(attr->original_mode == NULL || attr->original_mode == env->mode); - attr->original_mode = env->mode; + assert(is_mips_div(new_div) || is_mips_divu(new_div)); - // we have to construct a new proj here, to avoid circular refs that - // happen when we reuse the old one - new_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_ANY, 1, &pred); - set_Proj_proj(new_proj, n); + switch(get_irn_opcode(divmod)) { + case iro_Div: + switch(pn) { + case pn_Div_M: + return new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_M); + case pn_Div_res: + proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_lohi); + return new_rd_mips_mflo(dbgi, irg, block, proj); + default: + break; + } + case iro_Mod: + switch(pn) { + case pn_Mod_M: + return new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_M); + case pn_Mod_res: + proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_lohi); + return new_rd_mips_mfhi(dbgi, irg, block, proj); + default: + break; + } - if(n == pn_DivMod_res_div) { - return new_rd_mips_mflo(env->dbg, env->irg, env->block, new_proj); - } else if(n == pn_DivMod_res_mod) { - return new_rd_mips_mfhi(env->dbg, env->irg, env->block, new_proj); + case iro_DivMod: + switch(pn) { + case pn_Div_M: + return new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_M); + case pn_DivMod_res_div: + proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_lohi); + return new_rd_mips_mflo(dbgi, irg, block, proj); + case pn_DivMod_res_mod: + proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M, + pn_mips_div_lohi); + return new_rd_mips_mfhi(dbgi, irg, block, proj); + default: + break; + } + default: + break; } - return proj; + panic("invalid proj attached to %+F\n", divmod); } -static -ir_node *gen_node_for_Proj(mips_transform_env_t *env) +static ir_node *gen_Proj_Start(ir_node *node) { - ir_node *proj = env->irn; - ir_mode *mode = get_irn_mode(proj); - ir_node *predecessor = get_Proj_pred(proj); - - // all DivMods, Div, Mod should be replaced by now - assert(get_irn_opcode(predecessor) != iro_DivMod); - assert(get_irn_opcode(predecessor) != iro_Div); - assert(get_irn_opcode(predecessor) != iro_Mod); - - if(is_mips_div(predecessor)) - return gen_node_for_div_Proj(env); - - if(is_mips_lw(predecessor) || is_mips_lh(predecessor) - || is_mips_lhu(predecessor) || is_mips_lb(predecessor) - || is_mips_lbu(predecessor)) { - - long pn = get_Proj_proj(proj); - if(pn == pn_Load_M) { - set_Proj_proj(proj, pn_mips_lw_M); - } else if(pn == pn_Load_res) { - set_Proj_proj(proj, pn_mips_lw_res); - } + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + long pn = get_Proj_proj(node); + + if(pn == pn_Start_X_initial_exec) { + /* we exchange the projx with a jump */ + ir_node *jump = new_rd_Jmp(dbgi, irg, block); + return jump; } - -#if 0 - if(get_irn_opcode(predecessor) == iro_Cond) { - ir_node *selector = get_Cond_selector(predecessor); - ir_mode *mode = get_irn_mode(selector); - n = get_Proj_proj(proj); - - if(get_mode_sort(mode) == irms_internal_boolean) { - assert(n == pn_Cond_true || n == pn_Cond_false); - return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true); - } + if(node == be_get_old_anchor(anchor_tls)) { + /* TODO... */ + return be_duplicate_node(node); } -#endif + return be_duplicate_node(node); +} + +static ir_node *gen_Proj(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *pred = get_Proj_pred(node); - if(get_mode_sort(mode) == irms_int_number) { - set_irn_mode(proj, mode_Iu); + switch(get_irn_opcode(pred)) { + case iro_Load: + break; + case iro_Store: + break; + case iro_Div: + case iro_Mod: + case iro_DivMod: + return gen_Proj_DivMod(node); + + case iro_Start: + return gen_Proj_Start(node); + + default: + assert(get_irn_mode(node) != mode_T); + if(mode_needs_gp_reg(get_irn_mode(node))) { + ir_node *new_pred = be_transform_node(pred); + ir_node *block = be_transform_node(get_nodes_block(node)); + long pn = get_Proj_proj(node); + + return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn); + } + break; } - return proj; + return be_duplicate_node(node); } -static -ir_node *gen_node_for_Phi(mips_transform_env_t *env) +static ir_node *gen_Phi(ir_node *node) { - ir_node *node = env->irn; - ir_mode *mode = get_irn_mode(node); - - if(get_mode_sort(mode) == irms_int_number) { - set_irn_mode(node, mode_Iu); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); + ir_node *phi; + + if(mode_needs_gp_reg(mode)) { + assert(get_mode_size_bits(mode) <= 32); + mode = mode_Iu; } - return node; + /* phi nodes allow loops, so we use the old arguments for now + * and fix this later */ + phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), + get_irn_in(node) + 1); + copy_node_attr(node, phi); + be_duplicate_deps(node, phi); + + be_set_transformed_node(node, phi); + be_enqueue_preds(node); + + return phi; } #if 0 @@ -459,59 +690,60 @@ ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env) } #endif -static -ir_node *gen_node_for_Cond(mips_transform_env_t *env) +static ir_node *gen_Cond(ir_node *node) { - ir_graph *irg = env->irg; - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *sel_proj = get_Cond_selector(node); - ir_node *cmp = get_Proj_pred(sel_proj); - ir_node *op1, *op2; + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *sel_proj = get_Cond_selector(node); + ir_node *cmp = get_Proj_pred(sel_proj); + ir_node *left = get_Cmp_left(cmp); + ir_node *new_left = be_transform_node(left); + ir_node *right = get_Cmp_right(cmp); + ir_node *new_right = be_transform_node(right); + long pnc = get_Proj_proj(sel_proj); ir_node *res; ir_node *slt; ir_node *zero; - long pn = get_Proj_proj(sel_proj); - op1 = get_Cmp_left(cmp); - op2 = get_Cmp_right(cmp); - switch(pn) { + /* TODO: use blez & co. when possible */ + + switch(pnc) { case pn_Cmp_False: case pn_Cmp_True: case pn_Cmp_Leg: panic("mips backend can't handle unoptimized constant Cond"); case pn_Cmp_Eq: - res = new_rd_mips_beq(dbg, irg, block, op1, op2); + res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right); break; case pn_Cmp_Lt: - zero = gen_zero(env); - slt = new_rd_mips_slt(dbg, irg, block, op1, op2); - res = new_rd_mips_bne(dbg, irg, block, slt, zero); + zero = mips_create_zero(); + slt = new_rd_mips_slt(dbgi, irg, block, new_left, new_right); + res = new_rd_mips_bne(dbgi, irg, block, slt, zero); break; case pn_Cmp_Le: - zero = gen_zero(env); - slt = new_rd_mips_slt(dbg, irg, block, op2, op1); - res = new_rd_mips_beq(dbg, irg, block, slt, zero); + zero = mips_create_zero(); + slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left); + res = new_rd_mips_beq(dbgi, irg, block, slt, zero); break; case pn_Cmp_Gt: - zero = gen_zero(env); - slt = new_rd_mips_slt(dbg, irg, block, op2, op1); - res = new_rd_mips_bne(dbg, irg, block, slt, zero); + zero = mips_create_zero(); + slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left); + res = new_rd_mips_bne(dbgi, irg, block, slt, zero); break; case pn_Cmp_Ge: - zero = gen_zero(env); - slt = new_rd_mips_slt(dbg, irg, block, op2, op1); - res = new_rd_mips_bne(dbg, irg, block, slt, zero); + zero = mips_create_zero(); + slt = new_rd_mips_slt(dbgi, irg, block, new_right, new_left); + res = new_rd_mips_bne(dbgi, irg, block, slt, zero); break; case pn_Cmp_Lg: - res = new_rd_mips_bne(dbg, irg, block, op1, op2); + res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right); break; default: @@ -521,115 +753,92 @@ ir_node *gen_node_for_Cond(mips_transform_env_t *env) return res; } -static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) { - ir_node *node = env->irn; - ir_node *pred; - ir_node *result; - mips_attr_t *attr; - - pred = get_Conv_op(node); - result = new_rd_mips_andi(env->dbg, env->irg, env->block, pred); - attr = get_mips_attr(result); - attr->tv = new_tarval_from_long(immediate, mode_Iu); - - return result; -} - -static ir_node *gen_node_for_Conv(mips_transform_env_t *env) { - ir_node *node = env->irn; - ir_node *pred; - ir_mode *srcmode; - ir_mode *destmode; - int dst_size, src_size; - - pred = get_Conv_op(node); - srcmode = get_irn_mode(pred); - destmode = get_irn_mode(node); +static ir_node *gen_Conv(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Conv_op(node); + ir_node *new_op = be_transform_node(op); + ir_mode *src_mode = get_irn_mode(op); + ir_mode *dst_mode = get_irn_mode(node); + int src_size = get_mode_size_bits(src_mode); + int dst_size = get_mode_size_bits(dst_mode); + ir_node *res; - dst_size = get_mode_size_bits(destmode); - src_size = get_mode_size_bits(srcmode); + assert(mode_needs_gp_reg(src_mode)); + assert(mode_needs_gp_reg(dst_mode)); - if(src_size == dst_size) { + /* we only need to do something on upconvs */ + if(src_size >= dst_size) { /* unnecessary conv */ - return pred; + return new_op; } -#if 0 - if(srcmode->size >= destmode->size) { - assert(srcmode->size > destmode->size || srcmode->sign != destmode->sign); - return new_rd_mips_reinterpret_conv(env->dbg, env->irg, env->block, pred); - } -#endif - if(srcmode->sign) { - /* TODO */ + if(mode_is_signed(src_mode)) { + if(src_size == 8) { + res = new_rd_mips_seb(dbgi, irg, block, new_op); + } else if(src_size == 16) { + res = new_rd_mips_seh(dbgi, irg, block, new_op); + } else { + panic("invalid conv %+F\n", node); + } } else { + ir_node *and_const; + if(src_size == 8) { - return create_conv_and(env, 0xff); + and_const = mips_create_Immediate(0xff); } else if(src_size == 16) { - return create_conv_and(env, 0xffff); + and_const = mips_create_Immediate(0xffff); + } else { + panic("invalid conv %+F\n", node); } + res = new_rd_mips_and(dbgi, irg, block, new_op, and_const); } - assert(0); - return NULL; + return res; } -static ir_node *gen_node_mips_div(mips_transform_env_t *env, ir_node* op1, ir_node* op2, long p_div, long p_mod, - long p_m, long p_x) +static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right, + ir_mode *mode) { - ir_node *node = env->irn; - ir_node *div; - const ir_edge_t *edge; - ir_mode *mode = get_irn_mode(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_left = be_transform_node(left); + ir_node *new_right = be_transform_node(right); + ir_node *res; if(mode_is_signed(mode)) { - div = new_rd_mips_div(env->dbg, env->irg, env->block, op1, op2); + res = new_rd_mips_div(dbgi, irg, block, new_left, new_right); } else { - div = new_rd_mips_divu(env->dbg, env->irg, env->block, op1, op2); + res = new_rd_mips_divu(dbgi, irg, block, new_left, new_right); } - // Adjust div projs - foreach_out_edge(node, edge) { - ir_node *proj = get_edge_src_irn(edge); - long n = get_Proj_proj(proj); - assert(is_Proj(proj) && "non-Proj from Mod node"); - if (n == p_div) { - set_Proj_proj(proj, pn_DivMod_res_div); - } else if (n == p_mod) { - set_Proj_proj(proj, pn_DivMod_res_mod); - } else if(n == p_m) { - set_Proj_proj(proj, pn_DivMod_M); - } else if(n == p_x) { - set_Proj_proj(proj, pn_DivMod_X_except); - } else { - assert(!"invalid proj"); - } - } + set_irn_pinned(res, get_irn_pinned(node)); - return div; + return res; } -static ir_node *gen_node_for_DivMod(mips_transform_env_t *env) { - ir_node *node = env->irn; - - return gen_node_mips_div(env, get_DivMod_left(node), get_DivMod_right(node), pn_DivMod_res_div, - pn_DivMod_res_mod, pn_DivMod_M, pn_DivMod_X_except); +static ir_node *gen_DivMod(ir_node *node) +{ + return create_div(node, get_DivMod_left(node), get_DivMod_right(node), + get_DivMod_resmode(node)); } -static ir_node *gen_node_for_Div(mips_transform_env_t *env) { - ir_node *node = env->irn; - - return gen_node_mips_div(env, get_Div_left(node), get_Div_right(node), pn_Div_res, -1, - pn_Div_M, pn_Div_X_except); +static ir_node *gen_Div(ir_node *node) +{ + return create_div(node, get_Div_left(node), get_Div_right(node), + get_Div_resmode(node)); } -static ir_node *gen_node_for_Mod(mips_transform_env_t *env) { - ir_node *node = env->irn; - - return gen_node_mips_div(env, get_Mod_left(node), get_Mod_right(node), -1, pn_Mod_res, - pn_Mod_M, pn_Mod_X_except); +static ir_node *gen_Mod(ir_node *node) +{ + return create_div(node, get_Mod_left(node), get_Mod_right(node), + get_Mod_resmode(node)); } +#if 0 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) { ir_node *node = env->irn; ir_node *mul; @@ -665,33 +874,6 @@ ir_node *gen_node_for_IJmp(mips_transform_env_t *env) { return new_rd_mips_jr(dbg, irg, block, target); } -static -ir_node *gen_node_for_Jmp(mips_transform_env_t *env) { - ir_graph *irg = env->irg; - ir_node *node = env->irn; - dbg_info *dbg = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - - return new_rd_mips_b(dbg, irg, block); -} - -static -ir_node *gen_node_for_Abs(mips_transform_env_t *env) { - ir_node *node = env->irn; - ir_node *sra, *add, *xor; - mips_attr_t *attr; - - // TODO for other bit sizes... - assert(get_mode_size_bits(env->mode) == 32); - sra = new_rd_mips_srai(env->dbg, env->irg, env->block, get_Abs_op(node)); - attr = get_mips_attr(sra); - attr->tv = new_tarval_from_long(31, mode_Iu); - add = new_rd_mips_addu(env->dbg, env->irg, env->block, get_Abs_op(node), sra); - xor = new_rd_mips_xor(env->dbg, env->irg, env->block, sra, add); - - return xor; -} - static ir_node *gen_node_for_Rot(mips_transform_env_t *env) { ir_node *node = env->irn; @@ -704,10 +886,13 @@ ir_node *gen_node_for_Rot(mips_transform_env_t *env) { return or; } +#endif -static ir_node *gen_node_for_Unknown(mips_transform_env_t *env) +static ir_node *gen_Unknown(ir_node *node) { - return gen_zero(env); + (void) node; + assert(mode_needs_gp_reg(get_irn_mode(node))); + return mips_create_zero(); } #if 0 @@ -873,15 +1058,13 @@ static void mips_transform_Spill(mips_transform_env_t* env) { ir_node *ptr = get_irn_n(node, 0); ir_node *val = get_irn_n(node, 1); ir_entity *ent = be_get_frame_entity(node); - mips_attr_t *attr; if(sched_is_scheduled(node)) { sched_point = sched_prev(node); } - store = new_rd_mips_sw(env->dbg, env->irg, env->block, nomem, ptr, val); - attr = get_mips_attr(store); - attr->stack_entity = ent; + store = new_rd_mips_sw(env->dbg, env->irg, env->block, ptr, val, nomem, + ent, 0); if (sched_point) { sched_add_after(sched_point, store); @@ -899,21 +1082,17 @@ static void mips_transform_Reload(mips_transform_env_t* env) { ir_node *mem = get_irn_n(node, 1); ir_entity *ent = be_get_frame_entity(node); const arch_register_t* reg; - mips_attr_t *attr; if(sched_is_scheduled(node)) { sched_point = sched_prev(node); } - load = new_rd_mips_lw(env->dbg, env->irg, env->block, mem, ptr); - attr = get_mips_attr(load); - attr->stack_entity = ent; + load = new_rd_mips_lw(env->dbg, env->irg, env->block, ptr, mem, ent, 0); proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res); if (sched_point) { sched_add_after(sched_point, load); - sched_add_after(load, proj); sched_remove(node); } @@ -946,7 +1125,8 @@ static ir_node *gen_node_for_StackParam(mips_transform_env_t *env) } #endif -static ir_node *gen_node_for_AddSP(mips_transform_env_t *env) +#if 0 +static ir_node *gen_AddSP(ir_node *node) { ir_node *node = env->irn; ir_node *op1, *op2; @@ -964,6 +1144,7 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env) return add; } +#endif /********************************************************* * _ _ _ @@ -975,7 +1156,55 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env) * *********************************************************/ +static ir_node *gen_Bad(ir_node *node) +{ + panic("Unexpected node %+F found in mips transform phase.\n", node); + return NULL; +} + +static void register_transformers(void) +{ + clear_irp_opcodes_generic_func(); + + op_Add->ops.generic = (op_func) gen_Add; + op_Sub->ops.generic = (op_func) gen_Sub; + op_And->ops.generic = (op_func) gen_And; + op_Or->ops.generic = (op_func) gen_Or; + op_Eor->ops.generic = (op_func) gen_Eor; + op_Shl->ops.generic = (op_func) gen_Shl; + op_Shr->ops.generic = (op_func) gen_Shr; + op_Shrs->ops.generic = (op_func) gen_Shrs; + op_Not->ops.generic = (op_func) gen_Not; + op_Minus->ops.generic = (op_func) gen_Minus; + op_Div->ops.generic = (op_func) gen_Div; + op_Mod->ops.generic = (op_func) gen_Mod; + op_DivMod->ops.generic = (op_func) gen_DivMod; + op_Abs->ops.generic = (op_func) gen_Abs; + op_Load->ops.generic = (op_func) gen_Load; + op_Store->ops.generic = (op_func) gen_Store; + op_Cond->ops.generic = (op_func) gen_Cond; + op_Conv->ops.generic = (op_func) gen_Conv; + op_Const->ops.generic = (op_func) gen_Const; + op_SymConst->ops.generic = (op_func) gen_SymConst; + op_Unknown->ops.generic = (op_func) gen_Unknown; + op_Proj->ops.generic = (op_func) gen_Proj; + op_Phi->ops.generic = (op_func) gen_Phi; + + op_Raise->ops.generic = (op_func) gen_Bad; + op_Sel->ops.generic = (op_func) gen_Bad; + op_InstOf->ops.generic = (op_func) gen_Bad; + op_Cast->ops.generic = (op_func) gen_Bad; + op_Free->ops.generic = (op_func) gen_Bad; + op_Tuple->ops.generic = (op_func) gen_Bad; + op_Id->ops.generic = (op_func) gen_Bad; + op_Confirm->ops.generic = (op_func) gen_Bad; + op_Filter->ops.generic = (op_func) gen_Bad; + op_CallBegin->ops.generic = (op_func) gen_Bad; + op_EndReg->ops.generic = (op_func) gen_Bad; + op_EndExcept->ops.generic = (op_func) gen_Bad; +} +#if 0 /** * Transforms the given firm node (and maybe some other related nodes) * into one or more assembler nodes. @@ -1127,43 +1356,13 @@ bad: exchange(node, asm_node); } } - -void mips_pre_transform_node(ir_node *node, void *env) { - mips_code_gen_t *cgenv = (mips_code_gen_t *)env; - int i; - - mips_transform_env_t tenv; - - if (is_Block(node)) - return; - - tenv.block = get_nodes_block(node); - tenv.dbg = get_irn_dbg_info(node); - tenv.irg = current_ir_graph; - tenv.irn = node; - tenv.mode = get_irn_mode(node); - tenv.cg = cgenv; - - if(is_Proj(node)) { -#if 0 - ir_node* pred = get_Proj_pred(node); - if(get_irn_opcode(pred) == iro_CopyB) { - mips_fix_CopyB_Proj(&tenv); - } #endif - } - for(i = 0; i < get_irn_arity(node); ++i) { - ir_node* pred = get_irn_n(node, i); - - if (is_Const(pred)) { - ir_node* constnode = exchange_node_for_Const(&tenv, pred, i); - set_irn_n(node, i, constnode); - } else if (get_irn_op(pred) == op_SymConst) { - ir_node* constnode = gen_node_for_SymConst(&tenv, pred); - set_irn_n(node, i, constnode); - } - } +void mips_transform_graph(mips_code_gen_t *cg) +{ + env_cg = cg; + register_transformers(); + be_transform_graph(cg->birg, NULL, cg); } /** diff --git a/ir/be/mips/mips_transform.h b/ir/be/mips/mips_transform.h index fa9b8f3ee..342f60ccc 100644 --- a/ir/be/mips/mips_transform.h +++ b/ir/be/mips/mips_transform.h @@ -36,8 +36,10 @@ */ ir_node *gen_code_for_CopyB(ir_node *blk, ir_node *node); -void mips_pre_transform_node(ir_node *node, void *env); -void mips_transform_node(ir_node *node, void *env); +ir_node *mips_create_Immediate(long offset); +ir_node *mips_create_zero(void); + +void mips_transform_graph(mips_code_gen_t *cg); void mips_after_ra_walker(ir_node *node, void *env); #endif -- 2.20.1