BugFix: new_op must be used instead of op
[libfirm] / ir / be / arm / arm_transform.c
index 17f65be..ec1bcfd 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "../benode_t.h"
 #include "../beirg_t.h"
+#include "../beutil.h"
 #include "../betranshlp.h"
 #include "bearch_arm_t.h"
 
@@ -131,10 +132,9 @@ static void gen_vals_from_word(unsigned int value, vals *result)
 /**
  * Creates a arm_Const node.
  */
-static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
-       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
-       dbg_info *dbg  = get_irn_dbg_info(irn);
-       ir_mode  *mode = get_irn_mode(irn);
+static ir_node *create_const_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) {
+       ir_mode *mode  = mode_Iu;
+       tarval   *tv   = new_tarval_from_long(value, mode);
        ir_node *res;
 
        if (mode_needs_gp_reg(mode))
@@ -148,10 +148,9 @@ static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *bloc
 /**
  * Creates a arm_Const_Neg node.
  */
-static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
-       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
-       dbg_info *dbg  = get_irn_dbg_info(irn);
-       ir_mode  *mode = get_irn_mode(irn);
+static ir_node *create_const_neg_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) {
+       ir_mode *mode = mode_Iu;
+       tarval  *tv   = new_tarval_from_long(value, mode);
        ir_node *res;
 
        if (mode_needs_gp_reg(mode))
@@ -184,35 +183,31 @@ unsigned int arm_decode_imm_w_shift(tarval *tv) {
 /**
  * Creates a possible DAG for an constant.
  */
-static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) {
+static ir_node *create_const_graph_value(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, unsigned int value) {
        ir_node *result;
        vals v, vn;
        int cnt;
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
+       ir_mode *mode = mode_Iu;
 
        gen_vals_from_word(value, &v);
        gen_vals_from_word(~value, &vn);
 
-       if (mode_needs_gp_reg(mode))
-               mode = mode_Iu;
-
        if (vn.ops < v.ops) {
                /* remove bits */
-               result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
+               result = create_const_neg_node(abi, dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
 
                for (cnt = 1; cnt < vn.ops; ++cnt) {
-                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
+                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode);
                        ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
                        result = bic_i_node;
                }
        }
        else {
                /* add bits */
-               result = create_const_node(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
+               result = create_const_node(abi, dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
 
                for (cnt = 1; cnt < v.ops; ++cnt) {
-                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
+                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode);
                        ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
                        result = orr_i_node;
                }
@@ -236,25 +231,27 @@ static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *blo
                tv = tarval_convert_to(tv, mode_Iu);
        }
        value = get_tarval_long(tv);
-       return create_const_graph_value(abi, irn, block, value);
+       return create_const_graph_value(abi, get_irn_dbg_info(irn), block, value);
 }
 
-static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
-       ir_node *block = get_nodes_block(irn);
+/**
+ * Create an And that will mask all upper bits
+ */
+static ir_node *gen_zero_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
        unsigned mask_bits = (1 << result_bits) - 1;
-       ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-       return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
+       ir_node *mask_node = create_const_graph_value(abi, dbg, block, mask_bits);
+       return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, NULL);
 }
 
-static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
-       ir_node *block = get_nodes_block(irn);
+/**
+ * Generate code for a sign extension.
+ */
+static ir_node *gen_sign_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
+       ir_graph *irg   = current_ir_graph;
        int shift_width = 32 - result_bits;
-       ir_graph *irg = current_ir_graph;
-       ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-       ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
-       ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
+       ir_node *shift_const_node = create_const_graph_value(abi, dbg, block, shift_width);
+       ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu);
+       ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu);
        return rshift_node;
 }
 
@@ -272,9 +269,6 @@ static ir_node *gen_Conv(ir_node *node) {
        ir_mode  *dst_mode = get_irn_mode(node);
        dbg_info *dbg      = get_irn_dbg_info(node);
 
-       if (mode_needs_gp_reg(dst_mode))
-               dst_mode = mode_Iu;
-
        if (src_mode == dst_mode)
                return new_op;
 
@@ -309,64 +303,38 @@ static ir_node *gen_Conv(ir_node *node) {
        else { /* complete in gp registers */
                int src_bits = get_mode_size_bits(src_mode);
                int dst_bits = get_mode_size_bits(dst_mode);
-               int src_sign = get_mode_sign(src_mode);
-               int dst_sign = get_mode_sign(dst_mode);
+               int min_bits;
+               ir_mode *min_mode;
 
-               if (src_bits == dst_bits) {
-                       /* kill 32 -> 32 convs */
-                       if (src_bits == 32) {
+               if (is_Load(skip_Proj(op))) {
+                       if (src_bits == dst_bits) {
+                               /* kill unneccessary conv */
                                return new_op;
-                       } else if (dst_bits < 32) {
-                       // 16 -> 16
-                               // unsigned -> unsigned
-                                       // NOP
-                               // unsigned -> signed
-                                       // sign extension (31:16)=(15)
-                               // signed -> unsigned
-                                       // zero extension (31:16)=0
-                               // signed -> signed
-                                       // NOP
-                               if (src_sign && !dst_sign) {
-                                       return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
-                               } else {
-                                       return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
-                               }
-                       } else {
-                               panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits);
-                               return NULL;
                        }
+                       /* after a load, the bit size is already converted */
+                       src_bits = 32;
                }
-               else if (src_bits < dst_bits) {
-                       // 16 -> 32
-                               // unsigned -> unsigned
-                                       // NOP
-                               // unsigned -> signed
-                                       // NOP
-                               // signed -> unsigned
-                                       // sign extension (31:16)=(15)
-                               // signed -> signed
-                                       // sign extension (31:16)=(15)
-                       if (src_sign) {
-                               return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
+
+               if (src_bits == dst_bits) {
+                       /* kill unneccessary conv */
+                       return new_op;
+               } else if (dst_bits <= 32 && src_bits <= 32) {
+                       if (src_bits < dst_bits) {
+                               min_bits = src_bits;
+                               min_mode = src_mode;
                        } else {
-                               return new_op;
+                               min_bits = dst_bits;
+                               min_mode = dst_mode;
                        }
-               }
-               else {
-                       // 32 -> 16
-                               // unsigned -> unsigned
-                                       // maskieren (31:16)=0
-                               // unsigned -> signed
-                                       // maskieren (31:16)=0
-                               // signed -> unsigned
-                                       // maskieren (31:16)=0
-                               // signed -> signed
-                                       // sign extension (erledigt auch maskieren) (31:16)=(15)
-                       if (src_sign && dst_sign) {
-                               return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
+                       if (mode_is_signed(min_mode)) {
+                               return gen_sign_extension(env_cg->birg->abi, dbg, block, new_op, min_bits);
                        } else {
-                               return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
+                               return gen_zero_extension(env_cg->birg->abi, dbg, block, new_op, min_bits);
                        }
+               } else {
+                       panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode,
+                               src_bits, dst_bits);
+                       return NULL;
                }
        }
 }
@@ -422,6 +390,7 @@ static ir_node *gen_Add(ir_node *node) {
                }
        } else {
                assert(mode_is_numP(mode));
+               mode = mode_Iu;
 
                if (is_arm_Mov_i(new_op1))
                        return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
@@ -484,12 +453,15 @@ static ir_node *gen_Mul(ir_node *node) {
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
                        panic("VFP not supported yet\n");
+                       return NULL;
                }
                else {
                        panic("Softfloat not supported yet\n");
                        return NULL;
                }
        }
+       assert(mode_is_numP(mode));
+       mode = mode_Iu;
        return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
 }
 
@@ -530,7 +502,7 @@ static ir_node *gen_Quot(ir_node *node) {
        ir_node  *op2     = get_ ## op ## _right(node); \
        ir_node  *new_op2 = be_transform_node(op2); \
        ir_graph *irg     = current_ir_graph; \
-       ir_mode  *mode    = get_irn_mode(node); \
+       ir_mode  *mode    = mode_Iu; \
        dbg_info *dbg     = get_irn_dbg_info(node); \
        int      v; \
        arm_shift_modifier mod; \
@@ -615,6 +587,7 @@ static ir_node *gen_Sub(ir_node *node) {
        }
        else {
                assert(mode_is_numP(mode) && "unknown mode for Sub");
+               mode = mode_Iu;
 
                if (is_arm_Mov_i(new_op1))
                        return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
@@ -649,7 +622,7 @@ static ir_node *gen_Shl(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shl_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       ir_mode  *mode    = mode_Iu;
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
@@ -669,7 +642,7 @@ static ir_node *gen_Shr(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shr_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       ir_mode  *mode    = mode_Iu;
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
@@ -689,11 +662,11 @@ static ir_node *gen_Shrs(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shrs_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       ir_mode  *mode    = mode_Iu;
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
-               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(op2));
+               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(new_op2));
        }
        return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
@@ -709,6 +682,7 @@ static ir_node *gen_Not(ir_node *node) {
        ir_node  *new_op  = be_transform_node(op);
        dbg_info *dbg     = get_irn_dbg_info(node);
        tarval   *tv      = NULL;
+       ir_mode  *mode    = mode_Iu;
        arm_shift_modifier mod = ARM_SHF_NONE;
        int      v        = is_shifter_operand(new_op, &mod);
 
@@ -716,7 +690,7 @@ static ir_node *gen_Not(ir_node *node) {
                new_op = get_irn_n(new_op, 0);
                tv = new_tarval_from_long(v, mode_Iu);
        }
-       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, get_irn_mode(node), mod, tv);
+       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, tv);
 }
 
 /**
@@ -727,7 +701,7 @@ static ir_node *gen_Not(ir_node *node) {
  */
 static ir_node *gen_Abs(ir_node *node) {
        ir_node  *block   = be_transform_node(get_nodes_block(node));
-       ir_node  *op      = get_Not_op(node);
+       ir_node  *op      = get_Abs_op(node);
        ir_node  *new_op  = be_transform_node(op);
        dbg_info *dbg     = get_irn_dbg_info(node);
        ir_mode  *mode    = get_irn_mode(node);
@@ -744,6 +718,8 @@ static ir_node *gen_Abs(ir_node *node) {
                        panic("Softfloat not supported yet\n");
                }
        }
+       assert(mode_is_numP(mode));
+       mode = mode_Iu;
        return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
 }
 
@@ -771,6 +747,8 @@ static ir_node *gen_Minus(ir_node *node) {
                        panic("Softfloat not supported yet\n");
                }
        }
+       assert(mode_is_numP(mode));
+       mode = mode_Iu;
        return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
 }
 
@@ -810,9 +788,12 @@ static ir_node *gen_Load(ir_node *node) {
                        switch (get_mode_size_bits(mode)) {
                        case 8:
                                new_load = new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 16:
                                new_load = new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 32:
+                               new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
                                panic("mode size not supported\n");
@@ -822,17 +803,27 @@ static ir_node *gen_Load(ir_node *node) {
                        switch (get_mode_size_bits(mode)) {
                        case 8:
                                new_load = new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 16:
                                new_load = new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 32:
+                               new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
                                panic("mode size not supported\n");
                        }
                }
-               new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
        }
        set_irn_pinned(new_load, get_irn_pinned(node));
+
+       /* check for special case: the loaded value might not be used */
+       if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
+               /* add a result proj and a Keep to produce a pseudo use */
+               ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res);
+               be_new_Keep(arch_get_irn_reg_class(env_cg->arch_env, proj, -1), irg, block, 1, &proj);
+       }
+
        return new_load;
 }
 
@@ -935,7 +926,7 @@ static ir_node *gen_Cond(ir_node *node) {
                }
 
 
-               const_graph = create_const_graph_value(env_cg->birg->abi, node, block, translation);
+               const_graph = create_const_graph_value(env_cg->birg->abi, dbg, block, translation);
                sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL);
                return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
        }
@@ -1002,7 +993,7 @@ static ir_node *gen_Const(ir_node *node) {
  */
 static ir_node *gen_SymConst(ir_node *node) {
        ir_node  *block = be_transform_node(get_nodes_block(node));
-       ir_mode  *mode  = get_irn_mode(node);
+       ir_mode  *mode  = mode_Iu;
        dbg_info *dbg   = get_irn_dbg_info(node);
        ir_node  *res;
 
@@ -1120,8 +1111,8 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
        int       offset  = get_entity_offset(ent);
        ir_node   *op     = be_get_FrameAddr_frame(node);
        ir_node   *new_op = be_transform_node(op);
-       ir_mode   *mode   = get_irn_mode(node);
        dbg_info  *dbg    = get_irn_dbg_info(node);
+       ir_mode   *mode   = mode_Iu;
        ir_node   *cnst;
 
        if (be_is_IncSP(op)) {
@@ -1129,7 +1120,7 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
                   is relative. Both must be merged */
                offset += get_sp_expand_offset(op);
        }
-       cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset);
+       cnst = create_const_graph_value(env_cg->birg->abi, dbg, block, (unsigned)offset);
        if (is_arm_Mov_i(cnst))
                return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst));
        return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL);
@@ -1384,6 +1375,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
  * Transform the Projs from a Cmp.
  */
 static ir_node *gen_Proj_Cmp(ir_node *node) {
+       (void) node;
        panic("Psi NYI\n");
 }
 
@@ -1464,8 +1456,9 @@ static ir_node *gen_Proj(ir_node *node) {
  * is an "ignore" node.
  */
 static ir_node *gen_Unknown(ir_node *node) {
+       (void) node;
+       /*
        ir_mode *mode = get_irn_mode(node);
-/*
        if (mode_is_float(mode)) {
                if (USE_FPA(env_cg->isa))
                        return arm_new_Unknown_fpa(env_cg);
@@ -1548,7 +1541,6 @@ static void arm_register_transformers(void) {
 
 #define GEN(a)     set_transformer(op_##a, gen_##a)
 #define BAD(a)     set_transformer(op_##a, bad_transform)
-#define IGN(a)
 
        GEN(Add);
        GEN(Sub);
@@ -1585,9 +1577,6 @@ static void arm_register_transformers(void) {
        GEN(Proj);
        GEN(Phi);
 
-       IGN(Block);
-       IGN(End);
-
        GEN(Const);
        GEN(SymConst);
 
@@ -1630,7 +1619,6 @@ static void arm_register_transformers(void) {
        if (op_Mulh)
                BAD(Mulh);      /* unsupported yet */
 
-#undef IGN
 #undef GEN
 #undef BAD
 }
@@ -1640,6 +1628,7 @@ static void arm_register_transformers(void) {
  */
 static void arm_pretransform_node(void *arch_cg) {
        arm_code_gen_t *cg = arch_cg;
+       (void) cg;
 }
 
 /**