From 503617365f85975763b86b1398d4d9efc2d825ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Tue, 14 Mar 2006 13:51:54 +0000 Subject: [PATCH] added new attribute res_mode added conversions --- ir/be/ia32/bearch_ia32.c | 5 +- ir/be/ia32/ia32_emitter.c | 93 +++++++++++++++++++++++++++++++++++- ir/be/ia32/ia32_map_regs.c | 4 +- ir/be/ia32/ia32_new_nodes.c | 18 ++++++- ir/be/ia32/ia32_new_nodes.h | 10 ++++ ir/be/ia32/ia32_nodes_attr.h | 1 + ir/be/ia32/ia32_spec.pl | 12 ++--- ir/be/ia32/ia32_transform.c | 50 +++++++++---------- 8 files changed, 157 insertions(+), 36 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 37e7cd9f2..ccfb8296f 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -152,7 +152,10 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re } static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) { - int pos = 0; + int pos = 0; + const ia32_irn_ops_t *ops = self; + + DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn)); if (is_Proj(irn)) { pos = ia32_translate_proj_pos(irn); diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 089c69095..49115d32f 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1,3 +1,9 @@ +/** + * This file implements the node emitter. + * + * $Id$ + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -13,6 +19,7 @@ #include "irop_t.h" #include "irargs_t.h" #include "irprog_t.h" +#include "iredges_t.h" #include "../besched.h" #include "../benode_t.h" @@ -322,7 +329,11 @@ static int ia32_get_mode_suffix(lc_appendable_t *app, const lc_arg_occ_t *occ, const lc_arg_value_t *arg) { ir_node *X = arg->v_ptr; - ir_mode *mode = is_ia32_Lea(X) ? get_irn_mode(X) : get_ia32_ls_mode(X); + ir_mode *mode = get_irn_mode(X); + + if (mode == mode_T) { + mode = is_ia32_AddrModeS(X) || is_ia32_AddrModeD(X) ? get_ia32_ls_mode(X) : get_ia32_res_mode(X); + } if (!X) return lc_arg_append(app, occ, "(null)", 6); @@ -718,6 +729,9 @@ void emit_Proj(const ir_node *irn, emit_env_t *env) { * |_| |___/ **********************************/ +/** + * Emit movsb/w instructions to make mov count divideable by 4 + */ static void emit_CopyB_prolog(FILE *F, int rem, int size) { fprintf(F, "\t/* memcopy %d bytes*/\n", size); fprintf(F, "\tcld\t\t\t\t/* copy direction forward*/\n"); @@ -736,6 +750,9 @@ static void emit_CopyB_prolog(FILE *F, int rem, int size) { } } +/** + * Emit rep movsd instruction for memcopy. + */ 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); @@ -747,6 +764,9 @@ void emit_ia32_CopyB(const ir_node *irn, emit_env_t *emit_env) { fprintf(F, "\trep movsd\t\t\t\t/* memcopy */\n"); } +/** + * Emits unrolled memcopy. + */ 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); @@ -762,6 +782,59 @@ void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) { +/*************************** + * _____ + * / ____| + * | | ___ _ ____ __ + * | | / _ \| '_ \ \ / / + * | |___| (_) | | | \ V / + * \_____\___/|_| |_|\_/ + * + ***************************/ + +/** + * Emit code for conversions (I, FP), (FP, I) and (FP, FP). + */ +static void emit_ia32_Conv(const ir_node *irn, emit_env_t *emit_env) { + FILE *F = emit_env->out; + const lc_arg_env_t *env = ia32_get_arg_env(); + char *from, *to, buf[64]; + ir_mode *src_mode, *tgt_mode; + + src_mode = is_ia32_AddrModeS(irn) ? get_ia32_ls_mode(irn) : get_irn_mode(get_irn_n(irn, 2)); + tgt_mode = get_ia32_res_mode(irn); + + from = mode_is_float(src_mode) ? (get_mode_size_bits(src_mode) == 32 ? "ss" : "sd") : "si"; + to = mode_is_float(tgt_mode) ? (get_mode_size_bits(tgt_mode) == 32 ? "ss" : "sd") : "si"; + + switch(get_ia32_op_type(irn)) { + case ia32_Normal: + lc_esnprintf(env, buf, sizeof(buf), "%1D, %3S", irn, irn); + break; + case ia32_AddrModeS: + lc_esnprintf(env, buf, sizeof(buf), "%1D, %s", irn, ia32_emit_am(irn)); + break; + default: + assert(0 && "unsupported op type for Conv"); + } + + lc_efprintf(env, F, "\tcvt%s2%s %s\t\t\t/* %+F(%+F, %+F) */\n", from, to, buf, irn, src_mode, tgt_mode); +} + +void emit_ia32_Conv_I2FP(const ir_node *irn, emit_env_t *emit_env) { + emit_ia32_Conv(irn, emit_env); +} + +void emit_ia32_Conv_FP2I(const ir_node *irn, emit_env_t *emit_env) { + emit_ia32_Conv(irn, emit_env); +} + +void emit_ia32_Conv_FP2FP(const ir_node *irn, emit_env_t *emit_env) { + emit_ia32_Conv(irn, emit_env); +} + + + /******************************************* * _ _ * | | | | @@ -772,6 +845,9 @@ void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) { * *******************************************/ +/** + * Emits a backend call + */ void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) { FILE *F = emit_env->out; entity *ent = be_Call_get_entity(irn); @@ -788,6 +864,9 @@ void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) { ir_fprintf(F, "\t\t\t/* %+F (be_Call) */\n", irn); } +/** + * Emits code to increase stack pointer. + */ 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); @@ -802,18 +881,27 @@ void emit_be_IncSP(const ir_node *irn, emit_env_t *emit_env) { } } +/** + * Emits code to set stack pointer. + */ void emit_be_SetSP(const ir_node *irn, emit_env_t *emit_env) { FILE *F = emit_env->out; lc_efprintf(ia32_get_arg_env(), F, "\tmov %1D, %3S\t\t\t/* restore SP */\n", irn, irn); } +/** + * Emits code for Copy. + */ void emit_be_Copy(const ir_node *irn, emit_env_t *emit_env) { FILE *F = emit_env->out; lc_efprintf(ia32_get_arg_env(), F, "\tmov %1D, %1S\t\t\t/* %+F */\n", irn, irn, irn); } +/** + * Emits code for exchange. + */ void emit_be_Perm(const ir_node *irn, emit_env_t *emit_env) { FILE *F = emit_env->out; @@ -851,6 +939,9 @@ static void ia32_register_emitters(void) { IA32_EMIT(SwitchJmp); IA32_EMIT(CopyB); IA32_EMIT(CopyB_i); + IA32_EMIT(Conv_I2FP); + IA32_EMIT(Conv_FP2I); + IA32_EMIT(Conv_FP2FP); /* benode emitter */ BE_EMIT(Call); diff --git a/ir/be/ia32/ia32_map_regs.c b/ir/be/ia32/ia32_map_regs.c index 16051a0aa..7067c1faf 100644 --- a/ir/be/ia32/ia32_map_regs.c +++ b/ir/be/ia32/ia32_map_regs.c @@ -201,12 +201,12 @@ long ia32_translate_proj_pos(const ir_node *proj) { ir_node *pred = get_Proj_pred(proj); long nr = get_Proj_proj(proj); - if (is_ia32_Load(pred)) { + if (is_ia32_Ld(pred)) { if (nr == pn_Load_res) return 0; assert(0 && "unsupported Proj(Load) number"); } - else if (is_ia32_Store(pred)) { + else if (is_ia32_St(pred)) { return 0; } else if (is_ia32_CondJmp(pred)) { diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 48eac44aa..973e79c2a 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -655,6 +655,22 @@ void set_ia32_ls_mode(ir_node *node, ir_mode *mode) { attr->ls_mode = mode; } +/** + * Gets the mode of the result. + */ +ir_mode *get_ia32_res_mode(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return attr->res_mode; +} + +/** + * Sets the mode of the result. + */ +void set_ia32_res_mode(ir_node *node, ir_mode *mode) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->res_mode = mode; +} + /** * Gets the frame entity assigned to this node; */ @@ -1045,7 +1061,7 @@ 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) + if (! (a->cnst && b->cnst)) return 1; return strcmp(a->cnst, b->cnst); diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index fe1473a0c..37bc51c71 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -154,6 +154,16 @@ ir_mode *get_ia32_ls_mode(const ir_node *node); */ void set_ia32_ls_mode(ir_node *node, ir_mode *mode); +/** + * Gets the mode of the result. + */ +ir_mode *get_ia32_res_mode(const ir_node *node); + +/** + * Sets the mode of the result. + */ +void set_ia32_res_mode(ir_node *node, ir_mode *mode); + /** * Gets the frame entity assigned to this node; */ diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index f214486ef..336c7ec85 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -79,6 +79,7 @@ typedef struct _ia32_attr_t { char *cnst; /**< points to the string representation of the constant value (either tv or sc) */ ir_mode *ls_mode; /**< the mode of the stored/loaded value */ + ir_mode *res_mode; /**< the mode of the result */ entity *frame_ent; /**< the frame entity attached to this node */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 67c4f0496..b08b162bf 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -551,24 +551,22 @@ $arch = "ia32"; # Conversions -"Conv_I2I" => { - "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3", "none" ] }, - "comment" => "construct Conv Int -> Int" -}, - "Conv_I2FP" => { "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "fp", "none" ] }, + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "comment" => "construct Conv Int -> Floating Point" }, "Conv_FP2I" => { "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "gp", "none" ] }, + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "comment" => "construct Conv Floating Point -> Int" }, "Conv_FP2FP" => { - "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "in_r3", "none" ] }, - "comment" => "construct Conv Floating Point -> Floating Point" + "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "fp", "none" ] }, + "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", + "comment" => "construct Conv Floating Point -> Floating Point", }, ); # end of %nodes diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 23e3c247b..25e0c1f14 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -268,6 +268,8 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, mode); + if (is_op_commutative(get_irn_op(env->irn))) { set_ia32_commutative(new_op); } @@ -345,6 +347,8 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, mode); + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -383,6 +387,8 @@ static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_ set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, mode); + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -503,6 +509,8 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, mode); + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -648,6 +656,9 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { else { new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode); set_ia32_am_support(new_op, ia32_am_None); +#ifndef NDEBUG + set_ia32_orig_node(new_op, get_old_node_name(env)); +#endif /* NDEBUG */ } return new_op; @@ -795,6 +806,8 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, mode); + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -847,7 +860,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu)); } - res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode); + res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode_T); set_ia32_flavour(res, dm_flav); set_ia32_n_res(res, 2); @@ -873,6 +886,8 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir set_ia32_orig_node(res, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(res, mode_Is); + return res; } @@ -1075,6 +1090,8 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, env->mode); + new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0); } else { @@ -1139,6 +1156,8 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { set_ia32_orig_node(res, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(res, mode); + res = new_rd_Proj(dbg, irg, block, res, mode, 0); } else { @@ -1146,6 +1165,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { #ifndef NDEBUG set_ia32_orig_node(res, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(res, mode); p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX); p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX); @@ -1154,6 +1174,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { #ifndef NDEBUG set_ia32_orig_node(res, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(res, mode); res = new_rd_Proj(dbg, irg, block, res, mode, 0); @@ -1161,6 +1182,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { #ifndef NDEBUG set_ia32_orig_node(res, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(res, mode); res = new_rd_Proj(dbg, irg, block, res, mode, 0); } @@ -1374,29 +1396,6 @@ static ir_node *gen_Mux(ia32_transform_env_t *env) { } -#if 0 -/** - * Checks of we can omit the Int -> Int Conv - */ -static int ignore_int_conv(ir_mode *src_mode, ir_mode *tgt_mode) { - int ignore = 0; - int src_sign = mode_is_signed(src_mode); - int tgt_sign = mode_is_signed(tgt_mode); - int src_bits = get_mode_size_bits(src_mode); - int tgt_bits = get_mode_size_bits(tgt_mode); - - /* ignore Convs small -> big if same signedness */ - ignore = (src_sign == tgt_sign) && (src_bits < tgt_bits) ? 1 : ignore; - - /* ignore Bool -> Int Conv */ - ignore = (src_mode == mode_b) ? 1 : ignore; - - /* ignore Int -> Int Convs if same bitsize */ - ignore = (src_bits == tgt_bits) ? 1 : ignore; - - return ignore; -} -#endif /* if 0 */ /** * Transforms a Conv node. @@ -1452,6 +1451,9 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) { #ifndef NDEBUG set_ia32_orig_node(new_op, get_old_node_name(env)); #endif /* NDEBUG */ + set_ia32_res_mode(new_op, tgt_mode); + + set_ia32_am_support(new_op, ia32_am_Source); new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, 0); } -- 2.20.1