More missing config.h
[libfirm] / ir / be / ia32 / ia32_transform.c
index 972b0c3..b2b79ca 100644 (file)
@@ -258,7 +258,6 @@ const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
 
        lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
        obstack_1grow(isa->name_obst, 0);
-       isa->name_obst_size += obstack_object_size(isa->name_obst);
        return obstack_finish(isa->name_obst);
 }
 #endif /* NDEBUG */
@@ -421,7 +420,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 +514,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 +838,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 +1015,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 +1427,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 +1472,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 +1482,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 +1752,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 +2225,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);
 
@@ -2423,7 +2428,7 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) {
        if (mode_is_float(mode)) {
                /* store st(0) onto stack */
                ir_node *frame = get_irg_frame(env->irg);
-               ir_node *fstp  = new_rd_ia32_GetST0(env->dbg, env->irg, env->block, frame, call_mem);
+               ir_node *fstp  = new_rd_ia32_GetST0(env->dbg, env->irg, env->block, frame, get_irg_no_mem(env->irg));
                ir_node *mproj = new_r_Proj(env->irg, env->block, fstp, mode_M, pn_ia32_GetST0_M);
                entity  *ent   = frame_alloc_area(get_irg_frame_type(env->irg), get_mode_size_bytes(mode), 16, 0);
                ir_node *sse_load, *p, *bad, *keep;
@@ -2445,10 +2450,19 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) {
                set_ia32_frame_ent(sse_load, ent);
                set_ia32_am_flavour(sse_load, ia32_B);
                set_ia32_am_support(sse_load, ia32_am_Source);
+               mproj    = new_r_Proj(env->irg, env->block, sse_load, mode_M, pn_ia32_xLoad_M);
                sse_load = new_r_Proj(env->irg, env->block, sse_load, mode, pn_ia32_xLoad_res);
 
                /* reroute all users of the result proj to the sse load */
                edges_reroute(call_res, sse_load, env->irg);
+               edges_reroute_kind(call_res, sse_load,  EDGE_KIND_DEP, env->irg);
+
+               /* reroute all users of the old call memory to the sse load memory */
+               edges_reroute(call_mem, mproj, env->irg);
+               edges_reroute_kind(call_mem, mproj, EDGE_KIND_DEP, env->irg);
+
+               /* now, we can set the old call mem as input of GetST0 */
+               set_irn_n(fstp, 1, call_mem);
 
                /* now: create new Keep whith all former ins and one additional in - the result Proj */
 
@@ -2490,7 +2504,7 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) {
 static ir_node *gen_be_Return(ia32_transform_env_t *env) {
        ir_node *ret_val = get_irn_n(env->irn, be_pos_Return_val);
        ir_node *ret_mem = get_irn_n(env->irn, be_pos_Return_mem);
-       entity *ent      = get_irg_entity(get_irn_irg(ret_val));
+       entity  *ent     = get_irg_entity(get_irn_irg(ret_val));
        ir_type *tp      = get_entity_type(ent);
 
        if (be_Return_get_n_rets(env->irn) < 1 || ! ret_val || ! USE_SSE2(env->cg))
@@ -2823,6 +2837,7 @@ GEN_LOWERED_OP(Sub)
 GEN_LOWERED_OP(Mul)
 GEN_LOWERED_OP(Eor)
 GEN_LOWERED_x87_OP(vfdiv)
+GEN_LOWERED_x87_OP(vfprem)
 GEN_LOWERED_x87_OP(vfmul)
 GEN_LOWERED_x87_OP(vfsub)
 
@@ -2846,11 +2861,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;
 }
 
@@ -2955,6 +2983,7 @@ static ir_node *gen_ia32_l_X87toSSE(ia32_transform_env_t *env) {
                set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
                set_ia32_am_support(res, ia32_am_Dest);
                set_ia32_am_flavour(res, ia32_B);
+               set_ia32_op_type(res, ia32_AddrModeD);
                res = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_vfst_M);
 
                /* Load MEM -> SSE */
@@ -2964,6 +2993,7 @@ static ir_node *gen_ia32_l_X87toSSE(ia32_transform_env_t *env) {
                set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
                set_ia32_am_support(res, ia32_am_Source);
                set_ia32_am_flavour(res, ia32_B);
+               set_ia32_op_type(res, ia32_AddrModeS);
                res = new_rd_Proj(env->dbg, env->irg, env->block, res, get_ia32_ls_mode(env->irn), pn_ia32_xLoad_res);
        }
        else {
@@ -2982,32 +3012,48 @@ static ir_node *gen_ia32_l_X87toSSE(ia32_transform_env_t *env) {
  * In case SSE Unit is used, the node is transformed into a xStore + vfld.
  */
 static ir_node *gen_ia32_l_SSEtoX87(ia32_transform_env_t *env) {
-       ia32_code_gen_t *cg  = env->cg;
-       ir_node         *res = NULL;
-       ir_node         *ptr = get_irn_n(env->irn, 0);
-       ir_node         *val = get_irn_n(env->irn, 1);
-       ir_node         *mem = get_irn_n(env->irn, 2);
+       ia32_code_gen_t *cg     = env->cg;
+       ir_node         *res    = NULL;
+       ir_node         *ptr    = get_irn_n(env->irn, 0);
+       ir_node         *val    = get_irn_n(env->irn, 1);
+       ir_node         *mem    = get_irn_n(env->irn, 2);
+       entity          *fent   = get_ia32_frame_ent(env->irn);
+       ir_mode         *lsmode = get_ia32_ls_mode(env->irn);
+       int             offs    = 0;
 
        if (USE_SSE2(cg)) {
                ir_node *noreg = ia32_new_NoReg_gp(cg);
 
                /* Store SSE -> MEM */
-               res = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
-               set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
-               set_ia32_use_frame(res);
-               set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
-               set_ia32_am_support(res, ia32_am_Dest);
-               set_ia32_am_flavour(res, ia32_B);
-               res = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_xStore_M);
+               if (is_ia32_xLoad(skip_Proj(val))) {
+                       ir_node *ld = skip_Proj(val);
+
+                       /* we can vfld the value directly into the fpu */
+                       fent = get_ia32_frame_ent(ld);
+                       ptr  = get_irn_n(ld, 0);
+                       offs = get_ia32_am_offs_int(ld);
+               }
+               else {
+                       res = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
+                       set_ia32_frame_ent(res, fent);
+                       set_ia32_use_frame(res);
+                       set_ia32_ls_mode(res, lsmode);
+                       set_ia32_am_support(res, ia32_am_Dest);
+                       set_ia32_am_flavour(res, ia32_B);
+                       set_ia32_op_type(res, ia32_AddrModeD);
+                       mem = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_xStore_M);
+               }
 
                /* Load MEM -> x87 */
                res = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
-               set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
+               set_ia32_frame_ent(res, fent);
                set_ia32_use_frame(res);
-               set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
+               set_ia32_ls_mode(res, lsmode);
+               add_ia32_am_offs_int(res, offs);
                set_ia32_am_support(res, ia32_am_Source);
                set_ia32_am_flavour(res, ia32_B);
-               res = new_rd_Proj(env->dbg, env->irg, env->block, res, get_ia32_ls_mode(env->irn), pn_ia32_vfld_res);
+               set_ia32_op_type(res, ia32_AddrModeS);
+               res = new_rd_Proj(env->dbg, env->irg, env->block, res, lsmode, pn_ia32_vfld_res);
        }
        else {
                /* SSE unit is not used -> skip this node. */
@@ -3099,6 +3145,7 @@ void ia32_register_transformers(void) {
        GEN(ia32_l_ShlD);
        GEN(ia32_l_ShrD);
        GEN(ia32_l_vfdiv);
+       GEN(ia32_l_vfprem);
        GEN(ia32_l_vfmul);
        GEN(ia32_l_vfsub);
        GEN(ia32_l_vfild);