Merge ia32_am_type_t and ia32_am_arity_t, because (type == ia32_am_None) == (arity...
[libfirm] / ir / be / ia32 / ia32_transform.c
index 82a91c4..6c33567 100644 (file)
@@ -48,6 +48,7 @@
 #include "irdom.h"
 #include "archop.h"
 #include "error.h"
+#include "array_t.h"
 #include "height.h"
 
 #include "../benode_t.h"
@@ -432,44 +433,6 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
        return ent_cache[kct];
 }
 
-static int prevents_AM(ir_node *const block, ir_node *const am_candidate,
-                       ir_node *const other)
-{
-       if (get_nodes_block(other) != block)
-               return 0;
-
-       if (is_Sync(other)) {
-               int i;
-
-               for (i = get_Sync_n_preds(other) - 1; i >= 0; --i) {
-                       ir_node *const pred = get_Sync_pred(other, i);
-
-                       if (get_nodes_block(pred) != block)
-                               continue;
-
-                       /* Do not block ourselves from getting eaten */
-                       if (is_Proj(pred) && get_Proj_pred(pred) == am_candidate)
-                               continue;
-
-                       if (!heights_reachable_in_block(heights, pred, am_candidate))
-                               continue;
-
-                       return 1;
-               }
-
-               return 0;
-       } else {
-               /* Do not block ourselves from getting eaten */
-               if (is_Proj(other) && get_Proj_pred(other) == am_candidate)
-                       return 0;
-
-               if (!heights_reachable_in_block(heights, other, am_candidate))
-                       return 0;
-
-               return 1;
-       }
-}
-
 /**
  * return true if the node is a Proj(Load) and could be used in source address
  * mode for another node. Will return only true if the @p other node is not
@@ -774,20 +737,19 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                }
                am->op_type = ia32_AddrModeS;
        } else {
+               am->op_type = ia32_Normal;
+
                if (flags & match_try_am) {
                        am->new_op1 = NULL;
                        am->new_op2 = NULL;
-                       am->op_type = ia32_Normal;
                        return;
                }
 
                new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
                if (new_op2 == NULL)
                        new_op2 = be_transform_node(op2);
-               am->op_type = ia32_Normal;
-               am->ls_mode = get_irn_mode(op2);
-               if (flags & match_mode_neutral)
-                       am->ls_mode = mode_Iu;
+               am->ls_mode =
+                       (flags & match_mode_neutral ? mode_Iu : get_irn_mode(op2));
        }
        if (addr->base == NULL)
                addr->base = noreg_gp;
@@ -801,6 +763,12 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
        am->commutative = commutative;
 }
 
+static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node)
+{
+       mark_irn_visited(old_node);
+       be_set_transformed_node(old_node, new_node);
+}
+
 static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
 {
        ir_mode  *mode;
@@ -813,8 +781,7 @@ static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
        mode = get_irn_mode(node);
        load = get_Proj_pred(am->mem_proj);
 
-       mark_irn_visited(load);
-       be_set_transformed_node(load, node);
+       set_transformed_and_mark(load, node);
 
        if (mode != mode_T) {
                set_irn_mode(node, mode_T);
@@ -852,7 +819,7 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
        set_am_attributes(new_node, &am);
        /* we can't use source address mode anymore when using immediates */
        if (is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
-               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+               set_ia32_am_support(new_node, ia32_am_none);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
        new_node = fix_mem_proj(new_node, &am);
@@ -902,7 +869,7 @@ static ir_node *gen_binop_flags(ir_node *node, construct_binop_flags_func *func,
        set_am_attributes(new_node, &am);
        /* we can't use source address mode anymore when using immediates */
        if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
-               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+               set_ia32_am_support(new_node, ia32_am_none);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
        new_node = fix_mem_proj(new_node, &am);
@@ -1242,7 +1209,7 @@ static ir_node *gen_Mulh(ir_node *node)
        set_am_attributes(new_node, &am);
        /* we can't use source address mode anymore when using immediates */
        if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
-               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+               set_ia32_am_support(new_node, ia32_am_none);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
        assert(get_irn_mode(new_node) == mode_T);
@@ -2024,12 +1991,6 @@ static int use_dest_am(ir_node *block, ir_node *node, ir_node *mem,
        return 1;
 }
 
-static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node)
-{
-       mark_irn_visited(old_node);
-       be_set_transformed_node(old_node, new_node);
-}
-
 static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2,
                               ir_node *mem, ir_node *ptr, ir_mode *mode,
                               construct_binop_dest_func *func,
@@ -2738,6 +2699,9 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
        if (get_mode_size_bits(mode) >= 32)
                return true;
 
+       if (is_Proj(transformed_node))
+               return upper_bits_clean(get_Proj_pred(transformed_node), mode);
+
        if (is_ia32_Conv_I2I(transformed_node)
                        || is_ia32_Conv_I2I8Bit(transformed_node)) {
                ir_mode *smaller_mode = get_ia32_ls_mode(transformed_node);
@@ -2759,6 +2723,7 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
                                return true;
                        }
                }
+               return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Shr_val), mode);
        }
 
        if (is_ia32_And(transformed_node) && !mode_is_signed(mode)) {
@@ -2772,8 +2737,11 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
                                return true;
                        }
                }
+               /* TODO recurse? */
        }
 
+       /* TODO recurse on Or, Xor, ... if appropriate? */
+
        if (is_ia32_Immediate(transformed_node)
                        || is_ia32_Const(transformed_node)) {
                const ia32_immediate_attr_t *attr
@@ -2829,13 +2797,12 @@ static ir_node *gen_Cmp(ir_node *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);
 
                /* matze: code here used mode instead of cmd_mode, I think it is always
                 * the same as cmp_mode, but I leave this here to see if this is really
                 * true...
                 */
-               assert(mode == cmp_mode);
+               assert(get_irn_mode(and_left) == cmp_mode);
 
                match_arguments(&am, block, and_left, and_right, NULL,
                                                                                match_commutative |
@@ -2844,8 +2811,8 @@ static ir_node *gen_Cmp(ir_node *node)
                                                                                match_8bit | match_16bit);
 
                /* use 32bit compare mode if possible since the opcode is smaller */
-               if (upper_bits_clean(am.new_op1, cmp_mode)
-                               && upper_bits_clean(am.new_op2, cmp_mode)) {
+               if (upper_bits_clean(am.new_op1, cmp_mode) &&
+                   upper_bits_clean(am.new_op2, cmp_mode)) {
                        cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu;
                }
 
@@ -2867,8 +2834,8 @@ static ir_node *gen_Cmp(ir_node *node)
                                match_16bit_am | match_am_and_immediates |
                                match_immediate | match_8bit | match_16bit);
                /* use 32bit compare mode if possible since the opcode is smaller */
-               if (upper_bits_clean(am.new_op1, cmp_mode)
-                               && upper_bits_clean(am.new_op2, cmp_mode)) {
+               if (upper_bits_clean(am.new_op1, cmp_mode) &&
+                   upper_bits_clean(am.new_op2, cmp_mode)) {
                        cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu;
                }
 
@@ -3596,8 +3563,7 @@ static ir_node *gen_be_Return(ir_node *node) {
                                  arity, in);
        copy_node_attr(barrier, new_barrier);
        be_duplicate_deps(barrier, new_barrier);
-       be_set_transformed_node(barrier, new_barrier);
-       mark_irn_visited(barrier);
+       set_transformed_and_mark(barrier, new_barrier);
 
        /* transform normally */
        return be_duplicate_node(node);
@@ -4021,8 +3987,7 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) {
                return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_SubSP_M);
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("No idea how to transform proj->AddSP");
 }
 
 /**
@@ -4045,8 +4010,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
                return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_AddSP_M);
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("No idea how to transform proj->SubSP");
 }
 
 /**
@@ -4144,8 +4108,7 @@ static ir_node *gen_Proj_Load(ir_node *node) {
                return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, 1);
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("No idea how to transform proj");
 }
 
 /**
@@ -4157,7 +4120,6 @@ static ir_node *gen_Proj_DivMod(ir_node *node) {
        ir_node  *new_pred = be_transform_node(pred);
        ir_graph *irg      = current_ir_graph;
        dbg_info *dbgi     = get_irn_dbg_info(node);
-       ir_mode  *mode     = get_irn_mode(node);
        long     proj      = get_Proj_proj(node);
 
        assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
@@ -4212,8 +4174,7 @@ static ir_node *gen_Proj_DivMod(ir_node *node) {
                break;
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, mode);
+       panic("No idea how to transform proj->DivMod");
 }
 
 /**
@@ -4225,7 +4186,6 @@ static ir_node *gen_Proj_CopyB(ir_node *node) {
        ir_node  *new_pred = be_transform_node(pred);
        ir_graph *irg      = current_ir_graph;
        dbg_info *dbgi     = get_irn_dbg_info(node);
-       ir_mode  *mode     = get_irn_mode(node);
        long     proj      = get_Proj_proj(node);
 
        switch(proj) {
@@ -4240,8 +4200,7 @@ static ir_node *gen_Proj_CopyB(ir_node *node) {
                break;
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, mode);
+       panic("No idea how to transform proj->CopyB");
 }
 
 /**
@@ -4253,7 +4212,6 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
        ir_node  *new_pred = be_transform_node(pred);
        ir_graph *irg      = current_ir_graph;
        dbg_info *dbgi     = get_irn_dbg_info(node);
-       ir_mode  *mode     = get_irn_mode(node);
        long     proj      = get_Proj_proj(node);
 
        switch(proj) {
@@ -4277,8 +4235,7 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
                break;
        }
 
-       assert(0);
-       return new_rd_Unknown(irg, mode);
+       panic("No idea how to transform proj->Quot");
 }
 
 static ir_node *gen_be_Call(ir_node *node) {
@@ -4458,8 +4415,7 @@ static ir_node *gen_Proj(ir_node *node) {
                if (proj == pn_Store_M) {
                        return be_transform_node(pred);
                } else {
-                       assert(0);
-                       return new_r_Bad(current_ir_graph);
+                       panic("No idea how to transform proj->Store");
                }
        case iro_Load:
                return gen_Proj_Load(node);