- Improved addressmode optimisation for conv nodes
[libfirm] / ir / be / ia32 / ia32_transform.c
index 972b0c3..6b603ef 100644 (file)
@@ -421,7 +421,7 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node
                tv = get_ia32_Immop_tarval(imm_op);
 
                if (tv) {
-                       tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
+                       tv = tarval_mod(tv, new_tarval_from_long(32, get_tarval_mode(tv)));
                        set_ia32_Immop_tarval(imm_op, tv);
                }
                else {
@@ -515,7 +515,7 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node
        DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
 
        /* try to optimize to inc/dec  */
-       if ((env->cg->opt & IA32_OPT_INCDEC) && (get_ia32_op_type(const_op) == ia32_Const)) {
+       if ((env->cg->opt & IA32_OPT_INCDEC) && tv && (get_ia32_op_type(const_op) == ia32_Const)) {
                /* optimize tarvals */
                class_tv    = classify_tarval(tv);
                class_negtv = classify_tarval(tarval_neg(tv));
@@ -839,7 +839,7 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node
        DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
 
        /* try to optimize to inc/dec  */
-       if ((env->cg->opt & IA32_OPT_INCDEC) && tv) {
+       if ((env->cg->opt & IA32_OPT_INCDEC) && tv && (get_ia32_op_type(const_op) == ia32_Const)) {
                /* optimize tarvals */
                class_tv    = classify_tarval(tv);
                class_negtv = classify_tarval(tarval_neg(tv));
@@ -1016,7 +1016,8 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
                edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_ia32_Cdq_EDX);
        }
        else {
-               edx_node = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode_Iu);
+               edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
+               add_irn_dep(edx_node, be_abi_get_start_barrier(env->cg->birg->abi));
                set_ia32_Const_type(edx_node, ia32_Const);
                set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
        }
@@ -1427,6 +1428,16 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
 
        ia32_collect_Projs(env->irn, projs, pn_Load_max);
 
+       /*
+               check for special case: the loaded value might not be used (optimized, volatile, ...)
+               we add a Proj + Keep for volatile loads and ignore all other cases
+       */
+       if (! get_proj_for_pn(node, pn_Load_res) && get_Load_volatility(node) == volatility_is_volatile) {
+               /* add a result proj and a Keep to produce a pseudo use */
+               ir_node *proj = new_r_Proj(env->irg, env->block, node, mode, pn_ia32_Load_res);
+               be_new_Keep(arch_get_irn_reg_class(env->cg->arch_env, proj, -1), env->irg, env->block, 1, &proj);
+       }
+
        /* address might be a constant (symconst or absolute address) */
        if (is_ia32_Const(ptr)) {
                lptr   = noreg;
@@ -1462,6 +1473,9 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
                        add_ia32_am_offs(new_op, get_ia32_cnst(ptr));
                        am_flav = ia32_am_O;
                }
+               /* add dependency to barrier, if we are in start block */
+               if (get_irg_start_block(env->irg) == env->block)
+                       add_irn_dep(new_op, be_abi_get_start_barrier(env->cg->birg->abi));
        }
 
        set_ia32_am_support(new_op, ia32_am_Source);
@@ -1469,16 +1483,6 @@ static ir_node *gen_Load(ia32_transform_env_t *env) {
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
 
-       /*
-               check for special case: the loaded value might not be used (optimized, volatile, ...)
-               we add a Proj + Keep for volatile loads and ignore all other cases
-       */
-       if (! get_proj_for_pn(node, pn_Load_res) && get_Load_volatility(node) == volatility_is_volatile) {
-               /* add a result proj and a Keep to produce a pseudo use */
-               ir_node *proj = new_r_Proj(env->irg, env->block, new_op, mode, pn_ia32_Load_res);
-               be_new_Keep(arch_get_irn_reg_class(env->cg->arch_env, proj, -1), env->irg, env->block, 1, &proj);
-       }
-
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
 
        return new_op;
@@ -1749,7 +1753,8 @@ static ir_node *gen_CopyB(ia32_transform_env_t *env) {
                rem = size & 0x3; /* size % 4 */
                size >>= 2;
 
-               res = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode_Is);
+               res = new_rd_ia32_Const(dbg, irg, block, mode_Is);
+               add_irn_dep(res, be_abi_get_start_barrier(env->cg->birg->abi));
                set_ia32_op_type(res, ia32_Const);
                set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
 
@@ -2221,7 +2226,8 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) {
                set_ia32_tgt_mode(new_op, tgt_mode);
                set_ia32_src_mode(new_op, src_mode);
 
-               set_ia32_am_support(new_op, ia32_am_Source);
+               if(tgt_bits >= src_bits)
+                       set_ia32_am_support(new_op, ia32_am_Source);
 
                new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, pn);
 
@@ -2846,11 +2852,24 @@ static ir_node *gen_ia32_l_MulS(ia32_transform_env_t *env) {
 
        ir_node *new_op = gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_MulS);
        ir_node *muls   = get_Proj_pred(new_op);
+       ir_node *proj;
 
        /* MulS cannot have AM for destination */
        if (get_ia32_am_support(muls) != ia32_am_None)
                set_ia32_am_support(muls, ia32_am_Source);
 
+       /* check if EAX and EDX proj exist, add missing one */
+       proj = get_proj_for_pn(env->irn, pn_ia32_MulS_EAX);
+       if (! proj) {
+               proj = new_r_Proj(env->irg, env->block, muls, get_ia32_res_mode(env->irn), pn_ia32_MulS_EAX);
+               be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, &proj);
+       }
+       proj = get_proj_for_pn(env->irn, pn_ia32_MulS_EDX);
+       if (! proj) {
+               proj = new_r_Proj(env->irg, env->block, muls, get_ia32_res_mode(env->irn), pn_ia32_MulS_EDX);
+               be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, &proj);
+       }
+
        return muls;
 }