From 41c1e5961f419bbb5e58ce87195c80817efa932b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Thu, 9 Mar 2006 09:07:09 +0000 Subject: [PATCH] fixed some minor bugs code cleanups added new magic (register generic functions at op's) --- ir/be/ia32/bearch_ia32.c | 2 - ir/be/ia32/ia32_emitter.c | 198 ++++++++++++++++-------------------- ir/be/ia32/ia32_map_regs.c | 3 - ir/be/ia32/ia32_new_nodes.c | 90 ++++++++-------- ir/be/ia32/ia32_new_nodes.h | 5 + ir/be/ia32/ia32_optimize.c | 24 +---- ir/be/ia32/ia32_spec.pl | 119 +++++++++------------- ir/be/ia32/ia32_transform.c | 36 +++++-- 8 files changed, 217 insertions(+), 260 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index d69e0fd5c..412f3b286 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -190,8 +190,6 @@ static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) { irn = my_skip_proj(irn); if (is_cfop(irn)) return arch_irn_class_branch; - else if (is_ia32_Call(irn)) - return arch_irn_class_call; else if (is_ia32_irn(irn)) return arch_irn_class_normal; else diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 8a1f35f42..6ad076507 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -15,6 +15,7 @@ #include "irprog_t.h" #include "../besched.h" +#include "../benode_t.h" #include "ia32_emitter.h" #include "gen_ia32_emitter.h" @@ -58,11 +59,21 @@ char *ia32_emit_binop(const ir_node *n) { lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %4S", n, n); } break; - case ia32_am_Source: + case ia32_AddrModeS: lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %s", n, ia32_emit_am(n)); break; - case ia32_am_Dest: - lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %4S", ia32_emit_am(n), n); + case ia32_AddrModeD: + if (get_ia32_cnst(n)) { + lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %s", ia32_emit_am(n), get_ia32_cnst(n)); + } + else { + if (is_ia32_St(n)) { + lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %3S", ia32_emit_am(n), n); + } + else { + lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %4S", ia32_emit_am(n), n); + } + } break; default: assert(0 && "unsupported op type"); @@ -172,7 +183,7 @@ static int ia32_get_arg_type(const lc_arg_occ_t *occ) { /** * Returns the register at in position pos. */ -static const arch_register_t *get_in_reg(ir_node *irn, int pos) { +static const arch_register_t *get_in_reg(const ir_node *irn, int pos) { ir_node *op; const arch_register_t *reg = NULL; @@ -191,7 +202,7 @@ static const arch_register_t *get_in_reg(ir_node *irn, int pos) { /** * Returns the register at out position pos. */ -static const arch_register_t *get_out_reg(ir_node *irn, int pos) { +static const arch_register_t *get_out_reg(const ir_node *irn, int pos) { ir_node *proj; const arch_register_t *reg = NULL; @@ -275,9 +286,8 @@ static int ia32_get_reg_name(lc_appendable_t *app, if (!X) return lc_arg_append(app, occ, "(null)", 6); - buf = get_ia32_reg_name(X, nr, occ->conversion == 'S' ? IN_REG : OUT_REG); + buf = get_ia32_reg_name(X, nr, occ->conversion == 'S' ? IN_REG : OUT_REG); - lc_appendable_chadd(app, '%'); return lc_arg_append(app, occ, buf, strlen(buf)); } @@ -314,10 +324,7 @@ static int ia32_get_mode_suffix(lc_appendable_t *app, if (!X) return lc_arg_append(app, occ, "(null)", 6); - if (get_mode_size_bits(get_irn_mode(X)) == 32) - return lc_appendable_chadd(app, 's'); - else - return lc_appendable_chadd(app, 'd'); + return lc_appendable_chadd(app, get_mode_size_bits(get_irn_mode(X)) == 32 ? 's' : 'd'); } /** @@ -334,7 +341,6 @@ const lc_arg_env_t *ia32_get_arg_env(void) { if(env == NULL) { /* extend the firm printer */ env = firm_get_arg_env(); - //lc_arg_new_env(); lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler); lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler); @@ -443,7 +449,7 @@ static char *get_cfop_target(const ir_node *irn, char *buf) { /** * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false) */ -static void finish_CondJmp(FILE *F, ir_node *irn) { +static void finish_CondJmp(FILE *F, const ir_node *irn) { const ir_node *proj; const ir_edge_t *edge; char buf[SNPRINTF_BUF_LEN]; @@ -474,7 +480,7 @@ static void finish_CondJmp(FILE *F, ir_node *irn) { /** * Emits code for conditional jump with two variables. */ -static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) { +static void emit_ia32_CondJmp(const ir_node *irn, emit_env_t *env) { FILE *F = env->out; lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2S, %1S\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn, @@ -485,7 +491,7 @@ static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) { /** * Emits code for conditional jump with immediate. */ -void emit_ia32_CondJmp_i(ir_node *irn, emit_env_t *env) { +void emit_ia32_CondJmp_i(const ir_node *irn, emit_env_t *env) { FILE *F = env->out; lc_efprintf(ia32_get_arg_env(), F, "\tcmp %C, %1S\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0)); @@ -601,12 +607,11 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) { if (do_jmp_tbl) { /* emit the table */ if (tbl.min_value != 0) { - fprintf(F, "\tcmpl %lu, -%d", interval, tbl.min_value); - lc_efprintf(env, F, "(%1S)\t\t/* first switch value is not 0 */\n", irn); + lc_efprintf(env, F, "\tcmpl %lu, -%d(%1S)\t\t/* first switch value is not 0 */\n", + interval, tbl.min_value, irn); } else { - fprintf(F, "\tcmpl %lu, ", interval); - lc_efprintf(env, F, "%1S\t\t\t/* compare for switch */\n", irn); + lc_efprintf(env, F, "\tcmpl %lu, %1S\t\t\t/* compare for switch */\n", interval, irn); } fprintf(F, "\tja %s\t\t\t/* default jump if out of range */\n", get_cfop_target(tbl.defProj, buf)); @@ -614,7 +619,6 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) { if (tbl.num_branches > 1) { /* create table */ - //fprintf(F, "\tjmp *%s", tbl.label); lc_efprintf(env, F, "\tjmp *%s(,%1S,4)\t\t/* get jump table entry as target */\n", tbl.label, irn); fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n"); @@ -640,9 +644,7 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) { } else { // no jump table for (i = 0; i < tbl.num_branches; ++i) { - fprintf(F, "\tcmpl %d, ", tbl.branches[i].value); - lc_efprintf(env, F, "%1S", irn); - fprintf(F, "\t\t\t/* case %d */\n", tbl.branches[i].value); + lc_efprintf(env, F, "\tcmpl %d, %1S\t\t\t/* case %d */\n", tbl.branches[i].value, irn, i); fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf)); } @@ -658,7 +660,7 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) { /** * Emits code for a unconditional jump. */ -void emit_Jmp(ir_node *irn, emit_env_t *env) { +void emit_Jmp(const ir_node *irn, emit_env_t *env) { FILE *F = env->out; char buf[SNPRINTF_BUF_LEN]; @@ -681,7 +683,7 @@ void emit_Jmp(ir_node *irn, emit_env_t *env) { /** * Emits code for a proj -> node */ -void emit_Proj(ir_node *irn, emit_env_t *env) { +void emit_Proj(const ir_node *irn, emit_env_t *env) { ir_node *pred = get_Proj_pred(irn); if (get_irn_op(pred) == op_Start) { @@ -724,7 +726,7 @@ static void emit_CopyB_prolog(FILE *F, int rem, int size) { } } -void emit_ia32_CopyB(ir_node *irn, emit_env_t *emit_env) { +void emit_ia32_CopyB(const ir_node *irn, emit_env_t *emit_env) { FILE *F = emit_env->out; tarval *tv = get_ia32_Immop_tarval(irn); int rem = get_tarval_long(tv); @@ -735,7 +737,7 @@ void emit_ia32_CopyB(ir_node *irn, emit_env_t *emit_env) { fprintf(F, "\trep movsd\t\t\t\t/* memcopy */\n"); } -void emit_ia32_CopyB_i(ir_node *irn, emit_env_t *emit_env) { +void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) { tarval *tv = get_ia32_Immop_tarval(irn); int size = get_tarval_long(tv); FILE *F = emit_env->out; @@ -748,17 +750,41 @@ void emit_ia32_CopyB_i(ir_node *irn, emit_env_t *emit_env) { } } -/******************** - * _____ _ _ - * / ____| | | | - * | | __ _| | | - * | | / _` | | | - * | |___| (_| | | | - * \_____\__,_|_|_| + + +/******************************************* + * _ _ + * | | | | + * | |__ ___ _ __ ___ __| | ___ ___ + * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __| + * | |_) | __/ | | | (_) | (_| | __/\__ \ + * |_.__/ \___|_| |_|\___/ \__,_|\___||___/ * - ********************/ + *******************************************/ + +void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) { + FILE *F = emit_env->out; -void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) { + lc_efprintf(ia32_get_arg_env(), F, "\tcall %3S\t\t\t/* %+F(%+F) (be_Call) */\n", irn, irn, get_irn_n(irn, 2)); +} + +void emit_be_IncSP(const ir_node *irn, emit_env_t *emit_env) { + FILE *F = emit_env->out; + unsigned offs = be_get_IncSP_offset(irn); + be_stack_dir_t dir = be_get_IncSP_direction(irn); + + if (offs) { + lc_efprintf(ia32_get_arg_env(), F, "\tadd %1S,%s%u\t\t\t/* %+F (IncSP) */\n", irn, + (dir == be_stack_dir_along) ? " -" : " ", offs, irn); + } + else { + fprintf(F, "\t\t\t\t\t/* omitted IncSP with 0 */\n"); + } +} + +void emit_be_AddSP(const ir_node *irn, emit_env_t *emit_env) { + FILE *F = emit_env->out; + lc_efprintf(ia32_get_arg_env(), F, "\tadd %1D, %1S\t\t\t/* %+F (AddSP) */\n", irn, irn, irn); } @@ -778,98 +804,52 @@ void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) { * pointer of an opcode. */ void ia32_register_emitters(void) { - int i; #define IA32_EMIT(a) op_ia32_##a->ops.generic = (op_func)emit_ia32_##a #define EMIT(a) op_##a->ops.generic = (op_func)emit_##a +#define BE_EMIT(a) op_be_##a->ops.generic = (op_func)emit_be_##a - /* first clear all generic operations */ - for (i = get_irp_n_opcodes() - 1; i >= 0; --i) { - ir_op *op = get_irp_opcode(i); - op->ops.generic = (op_func)NULL; - } - - /* generated int emitter functions */ - IA32_EMIT(Const); - - IA32_EMIT(Add); - IA32_EMIT(Sub); - IA32_EMIT(Minus); - IA32_EMIT(Inc); - IA32_EMIT(Dec); - - IA32_EMIT(Max); - IA32_EMIT(Min); - IA32_EMIT(CMov); - - IA32_EMIT(And); - IA32_EMIT(Or); - IA32_EMIT(Eor); - IA32_EMIT(Not); - - IA32_EMIT(Shl); - IA32_EMIT(Shr); - IA32_EMIT(Shrs); - IA32_EMIT(RotL); - IA32_EMIT(RotR); - - IA32_EMIT(Lea); - - IA32_EMIT(Mul); - - IA32_EMIT(Cdq); - IA32_EMIT(DivMod); - - IA32_EMIT(Store); - IA32_EMIT(Load); - - IA32_EMIT(CopyB); - IA32_EMIT(CopyB_i); - - /* generated floating point emitter */ - IA32_EMIT(fConst); - - IA32_EMIT(fAdd); - IA32_EMIT(fSub); - - IA32_EMIT(fMul); - IA32_EMIT(fDiv); - - IA32_EMIT(fMin); - IA32_EMIT(fMax); - - IA32_EMIT(fLoad); - IA32_EMIT(fStore); + /* register all emitter functions defined in spec */ + ia32_register_spec_emitters(); /* other emitter functions */ IA32_EMIT(CondJmp); IA32_EMIT(SwitchJmp); - IA32_EMIT(Call); + IA32_EMIT(CopyB); + IA32_EMIT(CopyB_i); + + /* benode emitter */ + BE_EMIT(Call); + BE_EMIT(IncSP); + BE_EMIT(AddSP); + /* firm emitter */ EMIT(Jmp); EMIT(Proj); #undef IA32_EMIT +#undef BE_EMIT #undef EMIT } /** * Emits code for a node. */ -static void ia32_emit_node(ir_node *irn, void *env) { - emit_env_t *emit_env = env; - firm_dbg_module_t *mod = emit_env->mod; - FILE *F = emit_env->out; - ir_op *op = get_irn_op(irn); +static void ia32_emit_node(const ir_node *irn, void *env) { + emit_env_t *emit_env = env; + firm_dbg_module_t *mod = emit_env->mod; + FILE *F = emit_env->out; + ir_op *op = get_irn_op(irn); DBG((mod, LEVEL_1, "emitting code for %+F\n", irn)); if (op->ops.generic) { - void (*emit)(ir_node *, void *) = (void (*)(ir_node *, void *))op->ops.generic; + void (*emit)(const ir_node *, void *) = (void (*)(const ir_node *, void *))op->ops.generic; (*emit)(irn, env); } - - ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn); + else { + ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn); + } } /** @@ -877,7 +857,7 @@ static void ia32_emit_node(ir_node *irn, void *env) { * and emits code for each node. */ static void ia32_gen_block(ir_node *block, void *env) { - ir_node *irn; + const ir_node *irn; if (! is_Block(block)) return; @@ -892,7 +872,7 @@ static void ia32_gen_block(ir_node *block, void *env) { /** * Emits code for function start. */ -void ia32_emit_start(FILE *F, ir_graph *irg) { +static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) { const char *irg_name = get_entity_name(get_irg_entity(irg)); fprintf(F, "\t.text\n"); @@ -904,7 +884,7 @@ void ia32_emit_start(FILE *F, ir_graph *irg) { /** * Emits code for function end */ -void ia32_emit_end(FILE *F, ir_graph *irg) { +static void ia32_emit_func_epilog(FILE *F, ir_graph *irg) { const char *irg_name = get_entity_name(get_irg_entity(irg)); fprintf(F, "\tret\n"); @@ -915,7 +895,7 @@ void ia32_emit_end(FILE *F, ir_graph *irg) { * Sets labels for control flow nodes (jump target) * TODO: Jump optimization */ -void ia32_gen_labels(ir_node *block, void *env) { +static void ia32_gen_labels(ir_node *block, void *env) { ir_node *pred; int n = get_Block_n_cfgpreds(block); @@ -939,8 +919,8 @@ void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) { /* set the global arch_env (needed by print hooks) */ arch_env = cg->arch_env; - ia32_emit_start(F, irg); + ia32_emit_func_prolog(F, irg); irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env); irg_walk_blkwise_graph(irg, NULL, ia32_gen_block, &emit_env); - ia32_emit_end(F, irg); + ia32_emit_func_epilog(F, irg); } diff --git a/ir/be/ia32/ia32_map_regs.c b/ir/be/ia32/ia32_map_regs.c index 45fa91d56..16051a0aa 100644 --- a/ir/be/ia32/ia32_map_regs.c +++ b/ir/be/ia32/ia32_map_regs.c @@ -233,9 +233,6 @@ long ia32_translate_proj_pos(const ir_node *proj) { else assert(0 && "there should be no more Projs for a fDiv"); } - else if (is_ia32_Call(pred)) { - return 0; - } else if (get_irn_mode(proj) == mode_X && nr == pn_Start_X_initial_exec) { return 0; } diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 05bfde5b0..f5b562712 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -180,7 +180,6 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { ir_mode *mode = NULL; int bad = 0; int i, n_res, am_flav, flags; - ia32_attr_t *attr; const ia32_register_req_t **reqs; const arch_register_t **slots; @@ -192,23 +191,15 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { case dump_node_mode_txt: mode = get_irn_mode(n); - if (is_ia32_Load(n) || is_ia32_Store(n)) { + if (is_ia32_Ld(n) || is_ia32_St(n)) { mode = get_ia32_ls_mode(n); } - if (mode) { - fprintf(F, "[%s]", get_mode_name(mode)); - } - else { - fprintf(F, "[?NOMODE?]"); - } + fprintf(F, "[%s]", mode ? get_mode_name(mode) : "?NOMODE?"); break; case dump_node_nodeattr_txt: - if (is_ia32_Call(n)) { - fprintf(F, "&%s ", get_ia32_sc(n)); - } - else if (get_ia32_cnst(n)) { + if (get_ia32_cnst(n)) { char *pref = ""; if (get_ia32_sc(n)) { @@ -230,7 +221,6 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { break; case dump_node_info_txt: - attr = get_ia32_attr(n); n_res = get_ia32_n_res(n); fprintf(F, "=== IA32 attr begin ===\n"); @@ -250,15 +240,10 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { slots = get_ia32_slots(n); if (slots && n_res > 0) { for (i = 0; i < n_res; i++) { - if (slots[i]) { - fprintf(F, "reg #%d = %s\n", i, slots[i]->name); - } - else { - fprintf(F, "reg #%d = n/a\n", i); - } + fprintf(F, "reg #%d = %s\n", i, slots[i] ? slots[i]->name : "n/a"); } + fprintf(F, "\n"); } - fprintf(F, "\n"); /* dump op type */ fprintf(F, "op = "); @@ -510,15 +495,12 @@ static void extend_ia32_am_offs(ir_node *node, char *offset, char op) { /* offset could already have an explicit sign */ /* -> supersede op if necessary */ - if (offset[0] == '-' && op == '-') { - op = '+'; - } - else if (offset[0] == '-' && op == '+') { - op = '-'; - } - - /* skip explicit sign */ if (offset[0] == '-' || offset[0] == '+') { + if (offset[0] == '-') { + op = (op == '-') ? '+' : '-'; + } + + /* skip explicit sign */ offset++; } @@ -563,8 +545,8 @@ int get_ia32_am_scale(const ir_node *node) { * Sets the index register scale for addrmode. */ void set_ia32_am_scale(ir_node *node, int scale) { - ia32_attr_t *attr = get_ia32_attr(node); - attr->data.am_scale = scale; + ia32_attr_t *attr = get_ia32_attr(node); + attr->data.am_scale = scale; } /** @@ -617,7 +599,7 @@ char *get_ia32_cnst(const ir_node *node) { * Sets the uses_frame flag. */ void set_ia32_use_frame(ir_node *node) { - ia32_attr_t *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); attr->data.use_frame = 1; } @@ -625,7 +607,7 @@ void set_ia32_use_frame(ir_node *node) { * Clears the uses_frame flag. */ void clear_ia32_use_frame(ir_node *node) { - ia32_attr_t *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); attr->data.use_frame = 0; } @@ -658,7 +640,6 @@ void clear_ia32_commutative(ir_node *node) { */ int is_ia32_commutative(const ir_node *node) { ia32_attr_t *attr = get_ia32_attr(node); - return attr->data.is_commutative; } @@ -848,7 +829,7 @@ void set_ia32_pncode(ir_node *node, long code) { unsigned get_ia32_Const_type(const ir_node *node) { ia32_attr_t *attr = get_ia32_attr(node); - assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type"); + assert(is_ia32_Cnst(node) && "Need ia32_Const to get type"); return attr->data.tp; } @@ -859,7 +840,7 @@ unsigned get_ia32_Const_type(const ir_node *node) { void set_ia32_Const_type(ir_node *node, int type) { ia32_attr_t *attr = get_ia32_attr(node); - assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type"); + assert(is_ia32_Cnst(node) && "Need ia32_Const to set type"); assert((type == ia32_Const || type == ia32_SymConst) && "Unsupported ia32_Const type"); attr->data.tp = type; @@ -872,7 +853,7 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) { ia32_attr_t *na = get_ia32_attr(node); ia32_attr_t *ca = get_ia32_attr(cnst); - assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr"); + assert(is_ia32_Cnst(cnst) && "Need ia32_Const to set Immop attr"); na->tv = ca->tv; @@ -892,19 +873,19 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) { void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) { ia32_attr_t *attr = get_ia32_attr(ia32_cnst); - assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr"); + assert(is_ia32_Cnst(ia32_cnst) && "Need ia32_Const to set Const attr"); switch (get_irn_opcode(cnst)) { case iro_Const: - attr->data.tp = ia32_Const; - attr->tv = get_Const_tarval(cnst); - attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv); + attr->data.tp = ia32_Const; + attr->tv = get_Const_tarval(cnst); + attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv); break; case iro_SymConst: - attr->data.tp = ia32_SymConst; - attr->tv = NULL; - attr->sc = copy_str(attr->sc, get_sc_name(cnst)); - attr->cnst = attr->sc; + attr->data.tp = ia32_SymConst; + attr->tv = NULL; + attr->sc = copy_str(attr->sc, get_sc_name(cnst)); + attr->cnst = attr->sc; break; case iro_Unknown: assert(0 && "Unknown Const NYI"); @@ -962,6 +943,13 @@ int is_ia32_St(const ir_node *node) { return is_ia32_Store(node) || is_ia32_fStore(node); } +/** + * Checks if node is a Const or fConst. + */ +int is_ia32_Cnst(const ir_node *node) { + return is_ia32_Const(node) || is_ia32_fConst(node); +} + /** * Returns the name of the OUT register at position pos. */ @@ -1014,7 +1002,7 @@ void alloc_ia32_reg_slots(ir_node *node, int num) { attr->slots = NULL; } - attr->data.n_res; + attr->data.n_res = num; } /** @@ -1039,5 +1027,17 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi * ***************************************************************************************/ +/* default compare operation to compare immediate ops */ +int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) { + if (a->data.tp == b->data.tp) { + if (! a->cnst || ! b->cnst) + return 1; + + return strcmp(a->cnst, b->cnst); + } + + return 1; +} + /* Include the generated constructor functions */ #include "gen_ia32_new_nodes.c.inl" diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index 620c6c9fd..6a0c17438 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -320,6 +320,11 @@ int is_ia32_Ld(const ir_node *node); */ int is_ia32_St(const ir_node *node); +/** + * Checks if node is a Const or fConst. + */ +int is_ia32_Cnst(const ir_node *node); + /** * Allocates num register slots for node. */ diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index a2ee42c03..376b327ee 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -223,26 +223,7 @@ void ia32_place_consts(ir_node *irn, void *env) { ******************************************************************/ static int node_is_comm(const ir_node *irn) { - if (is_ia32_Add(irn) || - is_ia32_fAdd(irn) || - is_ia32_Mul(irn) || - is_ia32_Mulh(irn) || - is_ia32_fMul(irn) || - is_ia32_And(irn) || - is_ia32_fAnd(irn) || - is_ia32_Or(irn) || - is_ia32_fOr(irn) || - is_ia32_Eor(irn) || - is_ia32_fEor(irn) || - is_ia32_Min(irn) || - is_ia32_fMin(irn) || - is_ia32_Max(irn) || - is_ia32_fMax(irn)) - { - return 1; - } - - return 0; + return is_ia32_irn(irn) ? is_ia32_commutative(irn) : 0; } static int ia32_get_irn_n_edges(const ir_node *irn) { @@ -626,7 +607,8 @@ void ia32_optimize_am(ir_node *irn, void *env) { add_ia32_am_offs(irn, get_ia32_am_offs(left)); set_ia32_am_scale(irn, get_ia32_am_scale(left)); set_ia32_am_flavour(irn, get_ia32_am_flavour(left)); - set_ia32_op_type(irn, get_ia32_op_type(left)); + + set_ia32_op_type(irn, is_ia32_St(irn) ? ia32_AddrModeD : ia32_AddrModeS); /* set base and index */ set_irn_n(irn, 0, get_irn_n(left, 0)); diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index dbfa32bb8..b8f35a111 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -95,7 +95,7 @@ $arch = "ia32"; { "name" => "esi", "type" => 2 }, { "name" => "edi", "type" => 2 }, { "name" => "ebp", "type" => 2 }, - { "name" => "esp", "type" => 6 }, + { "name" => "esp", "type" => 4 }, { "name" => "xxx", "type" => 6 }, # we need a dummy register for NoReg and Unknown nodes { "mode" => "mode_P" } ], @@ -150,6 +150,7 @@ $arch = "ia32"; "Add" => { "irn_flags" => "R", "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. add %ia32_emit_binop\t\t\t/* Add(%A1, %A2) -> %D1 */' }, @@ -157,6 +158,7 @@ $arch = "ia32"; "Mul" => { "irn_flags" => "A", "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. imul %ia32_emit_binop\t\t\t/* Mul(%A1, %A2) -> %D1 */' }, @@ -164,6 +166,7 @@ $arch = "ia32"; # Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX "Mulh" => { "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r2" ] }, "emit" => '. imul %ia32_emit_unop\t\t\t/* Mulh(%A1, %A2) -> %D1 */ ' }, @@ -171,6 +174,7 @@ $arch = "ia32"; "And" => { "irn_flags" => "R", "comment" => "construct And: And(a, b) = And(b, a) = a AND b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. and %ia32_emit_binop\t\t\t/* And(%A1, %A2) -> %D1 */' }, @@ -178,6 +182,7 @@ $arch = "ia32"; "Or" => { "irn_flags" => "R", "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. or %ia32_emit_binop\t\t\t/* Or(%A1, %A2) -> %D1 */' }, @@ -185,6 +190,7 @@ $arch = "ia32"; "Eor" => { "irn_flags" => "R", "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. xor %ia32_emit_binop\t\t\t/* Xor(%A1, %A2) -> %D1 */' }, @@ -234,6 +240,7 @@ $arch = "ia32"; "Sub" => { "irn_flags" => "R", "comment" => "construct Sub: Sub(a, b) = a - b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. sub %ia32_emit_binop\t\t\t/* Sub(%A1, %A2) -> %D1 */' }, @@ -255,6 +262,7 @@ $arch = "ia32"; "Shl" => { "irn_flags" => "R", "comment" => "construct Shl: Shl(a, b) = a << b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, "emit" => '. shl %ia32_emit_binop\t\t\t/* Shl(%A1, %A2) -> %D1 */' }, @@ -262,6 +270,7 @@ $arch = "ia32"; "Shr" => { "irn_flags" => "R", "comment" => "construct Shr: Shr(a, b) = a >> b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, "emit" => '. shr %ia32_emit_binop\t\t\t/* Shr(%A1, %A2) -> %D1 */' }, @@ -269,6 +278,7 @@ $arch = "ia32"; "Shrs" => { "irn_flags" => "R", "comment" => "construct Shrs: Shrs(a, b) = a >> b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, "emit" => '. sar %ia32_emit_binop\t\t\t/* Shrs(%A1, %A2) -> %D1 */' }, @@ -276,6 +286,7 @@ $arch = "ia32"; "RotR" => { "irn_flags" => "R", "comment" => "construct RotR: RotR(a, b) = a ROTR b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, "emit" => '. ror %ia32_emit_binop\t\t\t/* RotR(%A1, %A2) -> %D1 */' }, @@ -283,6 +294,7 @@ $arch = "ia32"; "RotL" => { "irn_flags" => "R", "comment" => "construct RotL: RotL(a, b) = a ROTL b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, "emit" => '. rol %ia32_emit_binop\t\t\t/* RotL(%A1, %A2) -> %D1 */' }, @@ -292,6 +304,7 @@ $arch = "ia32"; "Minus" => { "irn_flags" => "R", "comment" => "construct Minus: Minus(a) = -a", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. neg %ia32_emit_unop\t\t\t/* Neg(%A1) -> %D1, (%A1) */' }, @@ -299,6 +312,7 @@ $arch = "ia32"; "Inc" => { "irn_flags" => "R", "comment" => "construct Increment: Inc(a) = a++", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. inc %ia32_emit_unop\t\t\t/* Inc(%S1) -> %D1, (%A1) */' }, @@ -306,6 +320,7 @@ $arch = "ia32"; "Dec" => { "irn_flags" => "R", "comment" => "construct Decrement: Dec(a) = a--", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. dec %ia32_emit_unop\t\t\t/* Dec(%S1) -> %D1, (%A1) */' }, @@ -313,6 +328,7 @@ $arch = "ia32"; "Not" => { "irn_flags" => "R", "comment" => "construct Not: Not(a) = !a", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. not %ia32_emit_unop\t\t\t/* Not(%S1) -> %D1, (%A1) */' }, @@ -327,12 +343,14 @@ $arch = "ia32"; "CondJmp" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] }, }, "SwitchJmp" => { "op_flags" => "L|X|Y", "comment" => "construct switch", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, }, @@ -340,30 +358,9 @@ $arch = "ia32"; "op_flags" => "c", "irn_flags" => "R", "comment" => "represents an integer constant", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "gp" ] }, "emit" => '. mov %D1, %C\t\t\t/* Mov Const into register */', - "cmp_attr" => -' - if (attr_a->data.tp == attr_b->data.tp) { - if (attr_a->data.tp == ia32_SymConst) { - if (attr_a->sc == NULL || attr_b->sc == NULL) - return 1; - else - return strcmp(attr_a->sc, attr_b->sc); - } - else { - if (attr_a->tv == NULL || attr_b->tv == NULL) - return 1; - - if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq) - return 0; - else - return 1; - } - } - else - return 1; -' }, "Cdq" => { @@ -380,6 +377,7 @@ $arch = "ia32"; "irn_flags" => "R", "state" => "exc_pinned", "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] }, "emit" => '. mov %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */' }, @@ -388,15 +386,17 @@ $arch = "ia32"; "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] }, - "emit" => '. mov %ia32_emit_am, %S3\t\t\t/* Store(%A2) -> (%A1) */' + "emit" => '. mov %ia32_emit_binop\t\t\t/* Store(%A3) -> (%A1) */' }, "Lea" => { "irn_flags" => "R", "comment" => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */' + "emit" => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << scale + %O, (%A1, %A2) */' }, #--------------------------------------------------------# @@ -413,6 +413,7 @@ $arch = "ia32"; "fAdd" => { "irn_flags" => "R", "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A1, %A2) -> %D1 */' }, @@ -420,6 +421,7 @@ $arch = "ia32"; "fMul" => { "irn_flags" => "R", "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A1, %A2) -> %D1 */' }, @@ -427,6 +429,7 @@ $arch = "ia32"; "fMax" => { "irn_flags" => "R", "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A1, %A2) -> %D1 */' }, @@ -434,6 +437,7 @@ $arch = "ia32"; "fMin" => { "irn_flags" => "R", "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A1, %A2) -> %D1 */' }, @@ -441,6 +445,7 @@ $arch = "ia32"; "fAnd" => { "irn_flags" => "R", "comment" => "construct SSE And: And(a, b) = a AND b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. andp%M %ia32_emit_binop\t\t\t/* SSE And(%A3, %A4) -> %D1 */' }, @@ -448,6 +453,7 @@ $arch = "ia32"; "fOr" => { "irn_flags" => "R", "comment" => "construct SSE Or: Or(a, b) = a OR b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. orp%M %ia32_emit_binop\t\t\t/* SSE Or(%A3, %A4) -> %D1 */' }, @@ -455,6 +461,7 @@ $arch = "ia32"; "fEor" => { "irn_flags" => "R", "comment" => "construct SSE Eor: Eor(a, b) = a XOR b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. xorp%M %ia32_emit_binop\t\t\t/* SSE Xor(%A3, %A4) -> %D1 */' }, @@ -464,6 +471,7 @@ $arch = "ia32"; "fSub" => { "irn_flags" => "R", "comment" => "construct SSE Sub: Sub(a, b) = a - b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. subs%M %ia32_emit_binop\t\t\t/* SSE Sub(%A1, %A2) -> %D1 */' }, @@ -471,6 +479,7 @@ $arch = "ia32"; "fDiv" => { "irn_flags" => "R", "comment" => "construct SSE Div: Div(a, b) = a / b", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, "emit" => '. divs%M %ia32_emit_binop\t\t\t/* SSE Div(%A1, %A2) -> %D1 */' }, @@ -485,6 +494,7 @@ $arch = "ia32"; "fCondJmp" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump: UCOMIS A, B && JMPxx LABEL", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "none", "none" ] }, }, @@ -492,30 +502,9 @@ $arch = "ia32"; "op_flags" => "c", "irn_flags" => "R", "comment" => "represents a SSE constant", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "fp" ] }, "emit" => '. mov%M %D1, %C\t\t\t/* Load fConst into register */', - "cmp_attr" => -' - if (attr_a->data.tp == attr_b->data.tp) { - if (attr_a->data.tp == ia32_SymConst) { - if (attr_a->sc == NULL || attr_b->sc == NULL) - return 1; - else - return strcmp(attr_a->sc, attr_b->sc); - } - else { - if (attr_a->tv == NULL || attr_b->tv == NULL) - return 1; - - if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq) - return 0; - else - return 1; - } - } - else - return 1; -' }, # Load / Store @@ -525,6 +514,7 @@ $arch = "ia32"; "irn_flags" => "R", "state" => "exc_pinned", "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "fp" ] }, "emit" => '. movs%M %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */' }, @@ -533,6 +523,7 @@ $arch = "ia32"; "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ] }, "emit" => '. movs%M %ia32_emit_am, %S3\t\t\t/* Store(%S3) -> (%A1) */' }, @@ -540,34 +531,18 @@ $arch = "ia32"; # CopyB "CopyB" => { - "op_flags" => "F|H", - "state" => "pinned", - "comment" => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", - "reg_req" => { "in" => [ "edi", "esi", "ecx", "none" ], "out" => [ "none" ] }, + "op_flags" => "F|H", + "state" => "pinned", + "comment" => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", + "reg_req" => { "in" => [ "edi", "esi", "ecx", "none" ], "out" => [ "none" ] }, }, "CopyB_i" => { - "op_flags" => "F|H", - "state" => "pinned", - "comment" => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))", - "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "none" ] }, -}, - -# Call - -"Call" => { - "op_flags" => "L|F", - "state" => "mem_pinned", - "arity" => "variable", - "comment" => "construct Call: Call(...)", - "args" => [ - { "type" => "int", "name" => "n" }, - { "type" => "ir_node **", "name" => "in" } - ], - "rd_constructor" => -" if (!op_ia32_Call) assert(0); - return new_ir_node(db, irg, block, op_ia32_Call, mode_T, n, in); -" + "op_flags" => "F|H", + "state" => "pinned", + "comment" => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))", + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", + "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "none" ] }, }, ); # end of %nodes diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index b73b359a9..10914750d 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -145,19 +145,17 @@ static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) { } -#undef is_cnst -#define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op)) /* determine if one operator is an Imm */ static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) { if (op1) - return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL); - else return is_cnst(op2) ? op2 : NULL; + return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL); + else return is_ia32_Cnst(op2) ? op2 : NULL; } /* determine if one operator is not an Imm */ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) { - return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL); + return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL); } @@ -231,6 +229,10 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, } } + if (is_op_commutative(get_irn_op(env->irn))) { + set_ia32_commutative(new_op); + } + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -1106,6 +1108,8 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { } set_ia32_am_support(new_op, ia32_am_Source); + set_ia32_op_type(new_op, ia32_AddrModeS); + set_ia32_am_flavour(new_op, ia32_B); set_ia32_ls_mode(new_op, get_Load_mode(node)); return new_op; @@ -1125,17 +1129,33 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { static ir_node *gen_Store(ia32_transform_env_t *env) { ir_node *node = env->irn; ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *val = get_Store_value(node); + ir_node *ptr = get_Store_ptr(node); + ir_node *mem = get_Store_mem(node); + ir_node *sval = val; ir_node *new_op; + /* in case of storing a const -> make it an attribute */ + if (is_ia32_Cnst(val)) { + sval = noreg; + } + if (mode_is_float(env->mode)) { - new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); + new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode); } else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); + new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode); + } + + /* stored const is an attribute (saves a register) */ + if (is_ia32_Cnst(val)) { + set_ia32_Immop_attr(new_op, val); } set_ia32_am_support(new_op, ia32_am_Dest); - set_ia32_ls_mode(new_op, get_irn_mode(get_Store_value(node))); + set_ia32_op_type(new_op, ia32_AddrModeD); + set_ia32_am_flavour(new_op, ia32_B); + set_ia32_ls_mode(new_op, get_irn_mode(val)); return new_op; } -- 2.20.1