From c3e482fad9e0c60a21f00cf143812f014888da04 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Mon, 27 Mar 2006 10:41:47 +0000 Subject: [PATCH] fixed immediate operation handling --- ir/be/ia32/ia32_emitter.c | 16 +++++++- ir/be/ia32/ia32_new_nodes.c | 1 + ir/be/ia32/ia32_optimize.c | 9 ++++- ir/be/ia32/ia32_transform.c | 74 +++++++++++++++++++++++++++++-------- 4 files changed, 81 insertions(+), 19 deletions(-) diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 594e36452..f456a8995 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -305,7 +305,13 @@ char *ia32_emit_binop(const ir_node *n, ia32_emit_env_t *env) { } break; case ia32_AddrModeS: - lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S, %s", n, ia32_emit_am(n, env)); + if (is_ia32_ImmConst(n) || is_ia32_ImmSymConst(n)) { + assert(! PRODUCES_RESULT(n) && "Source AM with Const must not produce result"); + snprintf(buf, SNPRINTF_BUF_LEN, "%s, %s", get_ia32_cnst(n), ia32_emit_am(n, env)); + } + else { + lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S, %s", n, ia32_emit_am(n, env)); + } break; case ia32_AddrModeD: if (is_ia32_ImmConst(n) || is_ia32_ImmSymConst(n)) { @@ -421,7 +427,13 @@ char *ia32_emit_am(const ir_node *n, ia32_emit_env_t *env) { } if (am_flav & ia32_O) { - obstack_printf(obst, get_ia32_am_offs(n)); + s = get_ia32_am_offs(n); + + /* omit exlicit + if there was no base or index */ + if (! had_output && s[0] == '+') + s++; + + obstack_printf(obst, s); } obstack_printf(obst, "] "); diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 247a69317..06177f18d 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -483,6 +483,7 @@ char *get_ia32_am_offs(const ir_node *node) { memcpy(&res[1], obstack_base(attr->am_offs), size); res[size + 1] = '\0'; } + return res; } diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index 125eda5d6..17d0fdf46 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -555,13 +555,20 @@ static int load_store_addr_is_equal(const ir_node *load, const ir_node *store, int is_equal = (addr_b == get_irn_n(load, 0)) && (addr_i == get_irn_n(load, 1)); entity *lent = get_ia32_frame_ent(load); entity *sent = get_ia32_frame_ent(store); + char *loffs = get_ia32_am_offs(load); + char *soffs = get_ia32_am_offs(store); /* are both entities set and equal? */ - is_equal = lent && sent && (lent == sent); + if (lent || sent) + is_equal = lent && sent && (lent == sent); /* are the load and the store of the same mode? */ is_equal = get_ia32_ls_mode(load) == get_ia32_ls_mode(store); + /* are offsets set and equal */ + if (loffs || soffs) + is_equal = loffs && soffs && strcmp(loffs, soffs) == 0; + return is_equal; } diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 040db6779..64349dcb4 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1177,21 +1177,36 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { * @return the created ia32 Load node */ static ir_node *gen_Load(ia32_transform_env_t *env) { - ir_node *node = env->irn; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_mode *mode = get_Load_mode(node); + ir_node *node = env->irn; + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *ptr = get_Load_ptr(node); + ir_mode *mode = get_Load_mode(node); + const char *offs = NULL; ir_node *new_op; + ia32_am_flavour_t am_flav = ia32_B; + + /* address might be a constant (symconst or absolute address) */ + if (is_ia32_Const(ptr)) { + offs = get_ia32_cnst(ptr); + ptr = noreg; + } if (mode_is_float(mode)) { - new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); + new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, get_Load_mem(node), env->mode); } else { - new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); + new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, get_Load_mem(node), env->mode); + } + + /* base is an constant address */ + if (offs) { + add_ia32_am_offs(new_op, offs); + am_flav = ia32_O; } 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_am_flavour(new_op, am_flav); set_ia32_ls_mode(new_op, mode); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); @@ -1211,20 +1226,40 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { * @return the created ia32 Store node */ 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_mode *mode = get_irn_mode(val); - ir_node *sval = val; + 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_mode *mode = get_irn_mode(val); + ir_node *sval = val; + const char *offs = NULL; ir_node *new_op; + ia32_am_flavour_t am_flav = ia32_B; + ia32_immop_type_t immop = ia32_ImmNone; /* in case of storing a const (but not a symconst) -> make it an attribute */ - if (is_ia32_Const(val)) { + if (is_ia32_Cnst(val)) { + switch (get_ia32_op_type(val)) { + case ia32_Const: + immop = ia32_ImmConst; + break; + case ia32_SymConst: + immop = ia32_ImmSymConst; + break; + default: + assert(0 && "unsupported Const type"); + } + sval = noreg; } + /* address might be a constant (symconst or absolute address) */ + if (is_ia32_Const(ptr)) { + offs = get_ia32_cnst(ptr); + ptr = noreg; + } + if (mode_is_float(mode)) { new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, mode_T); } @@ -1236,14 +1271,21 @@ static ir_node *gen_Store(ia32_transform_env_t *env) { } /* stored const is an attribute (saves a register) */ - if (is_ia32_Const(val)) { + if (is_ia32_Cnst(val)) { set_ia32_Immop_attr(new_op, val); } + /* base is an constant address */ + if (offs) { + add_ia32_am_offs(new_op, offs); + am_flav = ia32_O; + } + set_ia32_am_support(new_op, ia32_am_Dest); set_ia32_op_type(new_op, ia32_AddrModeD); - set_ia32_am_flavour(new_op, ia32_B); + set_ia32_am_flavour(new_op, am_flav); set_ia32_ls_mode(new_op, get_irn_mode(val)); + set_ia32_immop_type(new_op, immop); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); -- 2.20.1