Defer decision whether to create Test(x, x) instead of Cmp(x, 0) until peephole optim...
authorChristoph Mallon <christoph.mallon@gmx.de>
Tue, 12 Aug 2008 20:56:38 +0000 (20:56 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Tue, 12 Aug 2008 20:56:38 +0000 (20:56 +0000)
[r21134]

ir/be/ia32/ia32_optimize.c
ir/be/ia32/ia32_transform.c

index fc08bf7..d42eb01 100644 (file)
@@ -160,6 +160,62 @@ static ir_node *turn_into_mode_t(ir_node *node)
        return new_node;
 }
 
+/**
+ * Replace Cmp(x, 0) by a Test(x, x)
+ */
+static void peephole_ia32_Cmp(ir_node *const node)
+{
+       ir_node                     *right;
+       ia32_immediate_attr_t const *imm;
+       dbg_info                    *dbgi;
+       ir_graph                    *irg;
+       ir_node                     *block;
+       ir_node                     *noreg;
+       ir_node                     *nomem;
+       ir_node                     *op;
+       ia32_attr_t           const *attr;
+       int                          ins_permuted;
+       int                          cmp_unsigned;
+       ir_node                     *test;
+       arch_register_t       const *reg;
+
+       if (get_ia32_op_type(node) != ia32_Normal)
+               return;
+
+       right = get_irn_n(node, n_ia32_Cmp_right);
+       if (!is_ia32_Immediate(right))
+               return;
+
+       imm = get_ia32_immediate_attr_const(right);
+       if (imm->symconst != NULL || imm->offset != 0)
+               return;
+
+       dbgi         = get_irn_dbg_info(node);
+       irg          = current_ir_graph;
+       block        = get_nodes_block(node);
+       noreg        = ia32_new_NoReg_gp(cg);
+       nomem        = get_irg_no_mem(irg);
+       op           = get_irn_n(node, n_ia32_Cmp_left);
+       attr         = get_irn_generic_attr(node);
+       ins_permuted = attr->data.ins_permuted;
+       cmp_unsigned = attr->data.cmp_unsigned;
+
+       if (is_ia32_Cmp(node)) {
+               test = new_rd_ia32_Test(dbgi, irg, block, noreg, noreg, nomem,
+                                       op, op, ins_permuted, cmp_unsigned);
+       } else {
+               test = new_rd_ia32_Test8Bit(dbgi, irg, block, noreg, noreg, nomem,
+                                           op, op, ins_permuted, cmp_unsigned);
+       }
+       set_ia32_ls_mode(test, get_ia32_ls_mode(node));
+
+       reg = arch_get_irn_register(arch_env, node);
+       arch_set_irn_register(arch_env, test, reg);
+
+       sched_add_before(node, test);
+       be_peephole_exchange(node, test);
+}
+
 /**
  * Peephole optimization for Test instructions.
  * We can remove the Test, if a zero flags was produced which is still
@@ -1046,12 +1102,14 @@ void ia32_peephole_optimization(ia32_code_gen_t *new_cg)
 
        /* register peephole optimisations */
        clear_irp_opcodes_generic_func();
-       register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const);
-       register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
-       register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea);
-       register_peephole_optimisation(op_ia32_Test, peephole_ia32_Test);
+       register_peephole_optimisation(op_ia32_Const,    peephole_ia32_Const);
+       register_peephole_optimisation(op_be_IncSP,      peephole_be_IncSP);
+       register_peephole_optimisation(op_ia32_Lea,      peephole_ia32_Lea);
+       register_peephole_optimisation(op_ia32_Cmp,      peephole_ia32_Cmp);
+       register_peephole_optimisation(op_ia32_Cmp8Bit,  peephole_ia32_Cmp);
+       register_peephole_optimisation(op_ia32_Test,     peephole_ia32_Test);
        register_peephole_optimisation(op_ia32_Test8Bit, peephole_ia32_Test);
-       register_peephole_optimisation(op_be_Return, peephole_ia32_Return);
+       register_peephole_optimisation(op_be_Return,     peephole_ia32_Return);
        if (! ia32_cg_config.use_imul_mem_imm32)
                register_peephole_optimisation(op_ia32_IMul, peephole_ia32_Imul_split);
        if (ia32_cg_config.use_pxor)
index f4301dd..52d3947 100644 (file)
@@ -2723,64 +2723,31 @@ static ir_node *gen_Cmp(ir_node *node)
 
        assert(ia32_mode_needs_gp_reg(cmp_mode));
 
-       /* we prefer the Test instruction where possible except cases where
-        * we can use SourceAM */
+       /* Prefer the Test instruction, when encountering (x & y) ==/!= 0 */
        cmp_unsigned = !mode_is_signed(cmp_mode);
-       if (is_Const_0(right)) {
-               if (is_And(left) &&
-                               get_irn_n_edges(left) == 1 &&
-                               can_fold_test_and(node)) {
-                       /* Test(and_left, and_right) */
-                       ir_node *and_left  = get_And_left(left);
-                       ir_node *and_right = get_And_right(left);
-                       ir_mode *mode      = get_irn_mode(and_left);
-
-                       match_arguments(&am, block, and_left, and_right, NULL,
-                                       match_commutative |
-                                       match_am | match_8bit_am | match_16bit_am |
-                                       match_am_and_immediates | match_immediate |
-                                       match_8bit | match_16bit);
-                       if (get_mode_size_bits(mode) == 8) {
-                               new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
-                                                               addr->index, addr->mem, am.new_op1,
-                                                               am.new_op2, am.ins_permuted,
-                                                               cmp_unsigned);
-                       } else {
-                               new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
-                                                           addr->index, addr->mem, am.new_op1,
-                                                           am.new_op2, am.ins_permuted, cmp_unsigned);
-                       }
+       if (is_Const_0(right)          &&
+           is_And(left)               &&
+           get_irn_n_edges(left) == 1 &&
+           can_fold_test_and(node)) {
+               /* Test(and_left, and_right) */
+               ir_node *and_left  = get_And_left(left);
+               ir_node *and_right = get_And_right(left);
+               ir_mode *mode      = get_irn_mode(and_left);
+
+               match_arguments(&am, block, and_left, and_right, NULL,
+                                                                               match_commutative |
+                                                                               match_am | match_8bit_am | match_16bit_am |
+                                                                               match_am_and_immediates | match_immediate |
+                                                                               match_8bit | match_16bit);
+               if (get_mode_size_bits(mode) == 8) {
+                       new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
+                                                                                                                                                       addr->index, addr->mem, am.new_op1,
+                                                                                                                                                       am.new_op2, am.ins_permuted,
+                                                                                                                                                       cmp_unsigned);
                } else {
-                       match_arguments(&am, block, NULL, left, NULL,
-                                       match_am | match_8bit_am | match_16bit_am |
-                                       match_8bit | match_16bit);
-                       if (am.op_type == ia32_AddrModeS) {
-                               /* Cmp(AM, 0) */
-                               ir_node *imm_zero = try_create_Immediate(right, 0);
-                               if (get_mode_size_bits(cmp_mode) == 8) {
-                                       new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
-                                                                      addr->index, addr->mem, am.new_op2,
-                                                                      imm_zero, am.ins_permuted,
-                                                                      cmp_unsigned);
-                               } else {
-                                       new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
-                                                                  addr->index, addr->mem, am.new_op2,
-                                                                  imm_zero, am.ins_permuted, cmp_unsigned);
-                               }
-                       } else {
-                               /* Test(left, left) */
-                               if (get_mode_size_bits(cmp_mode) == 8) {
-                                       new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
-                                                                       addr->index, addr->mem, am.new_op2,
-                                                                       am.new_op2, am.ins_permuted,
-                                                                       cmp_unsigned);
-                               } else {
-                                       new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
-                                                                   addr->index, addr->mem, am.new_op2,
-                                                                   am.new_op2, am.ins_permuted,
-                                                                   cmp_unsigned);
-                               }
-                       }
+                       new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
+                                                                                                                                       addr->index, addr->mem, am.new_op1,
+                                                                                                                                       am.new_op2, am.ins_permuted, cmp_unsigned);
                }
        } else {
                /* Cmp(left, right) */