From cd6eef2dd7fd5486a29dd906090b1d0b80fe2b8f Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 3 Aug 2007 09:39:09 +0000 Subject: [PATCH] replace Shrs(Shl) with Conv where possible, fix conv_conv optimisation bug [r15445] --- ir/be/ia32/ia32_optimize.c | 30 +++++++++++++++++++---- ir/be/ia32/ia32_spec.pl | 20 +++++++++------ ir/be/ia32/ia32_transform.c | 49 ++++++++++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index ada43dc0c..2dbaac666 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -30,6 +30,7 @@ #include "irnode.h" #include "irprog_t.h" #include "ircons.h" +#include "irtools.h" #include "firm_types.h" #include "iredges.h" #include "tv.h" @@ -1181,13 +1182,32 @@ static void optimize_conv_conv(ir_node *node) if(get_mode_size_bits(conv_mode) < get_mode_size_bits(pred_mode)) return; - /* we can't eliminate an upconv signed->unsigned */ - if (get_mode_size_bits(conv_mode) != get_mode_size_bits(pred_mode) && - !get_mode_sign(conv_mode) && get_mode_sign(pred_mode)) - return; + ir_fprintf(stderr, "Optimize: c1:%+F c2:%+F\n", pred_mode, conv_mode); + + /* adjust for signedness */ + ir_node *result_conv; + if(get_mode_sign(conv_mode) != get_mode_sign(pred_mode)) { + ir_mode *mode; + if(mode_is_signed(conv_mode)) { + mode = find_signed_mode(pred_mode); + } else { + mode = find_unsigned_mode(pred_mode); + } + + result_conv = exact_copy(pred); + set_ia32_ls_mode(result_conv, mode); + } else { + result_conv = pred; + } + + ir_fprintf(stderr, "Replaced with %+F\n", get_ia32_ls_mode(result_conv)); /* kill the conv */ - exchange(node, pred); + exchange(node, result_conv); + + if(get_irn_n_edges(pred) == 0) { + be_kill_node(pred); + } } static void optimize_node(ir_node *node, void *env) diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 414711b36..7d35ea4a7 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -1297,18 +1297,22 @@ CopyB_i => { # Conversions Conv_I2I => { - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] }, - units => [ "GP" ], - ins => [ "base", "index", "val", "mem" ], - mode => $mode_gp, + reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] }, + units => [ "GP" ], + ins => [ "base", "index", "val", "mem" ], + attr => "ir_mode *smaller_mode", + init_attr => "attr->ls_mode = smaller_mode;", + mode => $mode_gp, modified_flags => $status_flags }, Conv_I2I8Bit => { - reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] }, - ins => [ "base", "index", "val", "mem" ], - units => [ "GP" ], - mode => $mode_gp, + reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] }, + ins => [ "base", "index", "val", "mem" ], + units => [ "GP" ], + attr => "ir_mode *smaller_mode", + init_attr => "attr->ls_mode = smaller_mode;", + mode => $mode_gp, modified_flags => $status_flags }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 54e580168..f32cdebc5 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1248,7 +1248,8 @@ static ir_node *gen_Shr(ir_node *node) { static ir_node *gen_Shrs(ir_node *node) { ir_node *left = get_Shrs_left(node); ir_node *right = get_Shrs_right(node); - if(is_Const(right) && get_irn_mode(left) == mode_Is) { + ir_mode *mode = get_irn_mode(node); + if(is_Const(right) && mode == mode_Is) { tarval *tv = get_Const_tarval(right); long val = get_tarval_long(tv); if(val == 31) { @@ -1264,6 +1265,40 @@ static ir_node *gen_Shrs(ir_node *node) { return new_rd_ia32_Cltd(dbgi, irg, block, new_op, pval); } } +#if 1 + /* 8 or 16 bit sign extension? */ + if(is_Const(right) && is_Shl(left) && mode == mode_Is) { + ir_node *shl_left = get_Shl_left(left); + ir_node *shl_right = get_Shl_right(left); + if(is_Const(shl_right)) { + tarval *tv1 = get_Const_tarval(right); + tarval *tv2 = get_Const_tarval(shl_right); + if(tv1 == tv2 && tarval_is_long(tv1)) { + long val = get_tarval_long(tv1); + if(val == 16 || val == 24) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op = be_transform_node(shl_left); + ir_mode *src_mode; + ir_node *res; + + if(val == 24) { + src_mode = mode_Bs; + } else { + assert(val == 16); + src_mode = mode_Hs; + } + res = create_I2I_Conv(src_mode, mode_Is, dbgi, block, + new_op); + SET_IA32_ORIG_NODE(res, + ia32_get_old_node_name(env_cg, node)); + + return res; + } + } + } + } +#endif return gen_shift_binop(node, left, right, new_rd_ia32_Sar); } @@ -2172,14 +2207,12 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) { /* first convert to 32 bit if necessary */ src_bits = get_mode_size_bits(src_mode); if (src_bits == 8) { - new_op = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, block, noreg, noreg, new_op, nomem); + new_op = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, block, noreg, noreg, new_op, nomem, src_mode); set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary); - set_ia32_ls_mode(new_op, src_mode); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); } else if (src_bits < 32) { - new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem); + new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem, src_mode); set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary); - set_ia32_ls_mode(new_op, src_mode); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); } @@ -2231,12 +2264,10 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode, DB((dbg, LEVEL_1, "create Conv(int, int) ...", src_mode, tgt_mode)); if (smaller_bits == 8) { res = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, noreg, noreg, - new_op, nomem); - set_ia32_ls_mode(res, smaller_mode); + new_op, nomem, smaller_mode); } else { res = new_rd_ia32_Conv_I2I(dbgi, irg, new_block, noreg, noreg, new_op, - nomem); - set_ia32_ls_mode(res, smaller_mode); + nomem, smaller_mode); } set_ia32_am_support(res, ia32_am_Source, ia32_am_unary); -- 2.20.1