added function to retrieve irn ops
[libfirm] / ir / be / ia32 / ia32_transform.c
index 9755eb9..52ee5ea 100644 (file)
@@ -150,6 +150,24 @@ static ir_node *gen_sse_conv_int2float(ia32_code_gen_t *cg, dbg_info *dbg, ir_gr
        return new_rd_Proj(dbg, irg, block, conv, tgt_mode, pn_ia32_Conv_I2FP_res);
 }
 
+/**
+* SSE convert of an float node into a double node.
+*/
+static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbg, ir_graph *irg, ir_node *block,
+                                                                          ir_node *in, ir_node *old_node)
+{
+       ir_node *noreg = ia32_new_NoReg_gp(cg);
+       ir_node *nomem = new_rd_NoMem(irg);
+
+       ir_node *conv = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, in, nomem);
+       set_ia32_src_mode(conv, mode_F);
+       set_ia32_tgt_mode(conv, mode_D);
+       set_ia32_am_support(conv, ia32_am_Source);
+       SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
+
+       return new_rd_Proj(dbg, irg, block, conv, mode_D, pn_ia32_Conv_FP2FP_res);
+}
+
 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
 static ident *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
        static const struct {
@@ -1401,7 +1419,7 @@ static ir_node *gen_Store(ia32_transform_env_t *env) {
        ir_node *ptr     = get_Store_ptr(node);
        ir_node *sptr    = ptr;
        ir_node *mem     = get_Store_mem(node);
-       ir_mode *mode    = get_irn_link(node);
+       ir_mode *mode    = get_irn_mode(val);
        ir_node *sval    = val;
        int      is_imm  = 0;
        ir_node *new_op;
@@ -1629,9 +1647,9 @@ static ir_node *gen_CopyB(ia32_transform_env_t *env) {
        int      rem;
        ir_node  *in[3], *tmp;
 
-       /* If we have to copy more than 16 bytes, we use REP MOVSx and */
+       /* If we have to copy more than 32 bytes, we use REP MOVSx and */
        /* then we need the size explicitly in ECX.                    */
-       if (size >= 16 * 4) {
+       if (size >= 32 * 4) {
                rem = size & 0x3; /* size % 4 */
                size >>= 2;
 
@@ -1998,6 +2016,7 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) {
        int      src_bits  = get_mode_size_bits(src_mode);
        int      tgt_bits  = get_mode_size_bits(tgt_mode);
        int      pn        = -1;
+       int      kill      = 0;
        ir_node  *block    = env->block;
        ir_node  *new_op   = NULL;
        ir_node  *noreg    = ia32_new_NoReg_gp(env->cg);
@@ -2021,7 +2040,13 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) {
                        }
                        else {
                                DB((mod, LEVEL_1, "killed Conv(float, float) ..."));
-                               edges_reroute(env->irn, op, irg);
+                               /*
+                                       remark: we create a intermediate conv here, so modes will be spread correctly
+                                       these convs will be killed later
+                               */
+                               new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem);
+                               pn     = pn_ia32_Conv_FP2FP_res;
+                               kill   = 1;
                        }
                }
                else {
@@ -2071,7 +2096,13 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) {
                        /* ... to int */
                        if (get_mode_size_bits(src_mode) == tgt_bits) {
                                DB((mod, LEVEL_1, "omitting equal size Conv(%+F, %+F) ...", src_mode, tgt_mode));
-                               edges_reroute(env->irn, op, irg);
+                               /*
+                                       remark: we create a intermediate conv here, so modes will be spread correctly
+                                       these convs will be killed later
+                               */
+                               new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem);
+                               pn     = pn_ia32_Conv_I2I_res;
+                               kill   = 1;
                        }
                        else {
                                DB((mod, LEVEL_1, "create Conv(int, int) ...", src_mode, tgt_mode));
@@ -2095,6 +2126,9 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) {
                set_ia32_am_support(new_op, ia32_am_Source);
 
                new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, pn);
+
+               if (kill)
+                       nodeset_insert(env->cg->kill_conv, new_op);
        }
 
        return new_op;
@@ -2151,7 +2185,7 @@ static ir_node *gen_be_StackParam(ia32_transform_env_t *env) {
        ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
        ir_node *mem    = new_rd_NoMem(env->irg);
        ir_node *ptr    = get_irn_n(node, 0);
-       entity  *ent    = be_get_frame_entity(node);
+       entity  *ent    = arch_get_frame_entity(env->cg->arch_env, node);
        ir_mode *mode   = env->mode;
 
        /* choose the block where to place the load */
@@ -2175,6 +2209,7 @@ static ir_node *gen_be_StackParam(ia32_transform_env_t *env) {
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_B);
        set_ia32_ls_mode(new_op, mode);
+       set_ia32_flags(new_op, get_ia32_flags(new_op) | arch_irn_flags_rematerializable);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
 
@@ -2192,7 +2227,7 @@ static ir_node *gen_be_FrameAddr(ia32_transform_env_t *env) {
        ir_node *nomem  = new_rd_NoMem(env->irg);
 
        new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem);
-       set_ia32_frame_ent(new_op, be_get_frame_entity(node));
+       set_ia32_frame_ent(new_op, arch_get_frame_entity(env->cg->arch_env, node));
        set_ia32_am_support(new_op, ia32_am_Full);
        set_ia32_use_frame(new_op);
        set_ia32_immop_type(new_op, ia32_ImmConst);
@@ -2212,7 +2247,7 @@ static ir_node *gen_be_FrameLoad(ia32_transform_env_t *env) {
        ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
        ir_node *mem    = get_irn_n(node, 0);
        ir_node *ptr    = get_irn_n(node, 1);
-       entity  *ent    = be_get_frame_entity(node);
+       entity  *ent    = arch_get_frame_entity(env->cg->arch_env, node);
        ir_mode *mode   = get_type_mode(get_entity_type(ent));
 
        if (mode_is_float(mode)) {
@@ -2249,7 +2284,7 @@ static ir_node *gen_be_FrameStore(ia32_transform_env_t *env) {
        ir_node *mem    = get_irn_n(node, 0);
        ir_node *ptr    = get_irn_n(node, 1);
        ir_node *val    = get_irn_n(node, 2);
-       entity  *ent    = be_get_frame_entity(node);
+       entity  *ent    = arch_get_frame_entity(env->cg->arch_env, node);
        ir_mode *mode   = get_irn_mode(val);
 
        if (mode_is_float(mode)) {
@@ -2426,6 +2461,8 @@ static ir_node *gen_be_AddSP(ia32_transform_env_t *env) {
                }
        }
 
+       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
+
        return new_op;
 }
 
@@ -2977,12 +3014,12 @@ void ia32_transform_node(ir_node *node, void *env) {
                ia32_transform_env_t  tenv;
                transform_func *transform = (transform_func *)op->ops.generic;
 
-               tenv.block    = get_nodes_block(node);
-               tenv.dbg      = get_irn_dbg_info(node);
-               tenv.irg      = current_ir_graph;
-               tenv.irn      = node;
-               tenv.mode     = get_irn_mode(node);
-               tenv.cg       = cg;
+               tenv.block = get_nodes_block(node);
+               tenv.dbg   = get_irn_dbg_info(node);
+               tenv.irg   = current_ir_graph;
+               tenv.irn   = node;
+               tenv.mode  = get_irn_mode(node);
+               tenv.cg    = cg;
                DEBUG_ONLY(tenv.mod = cg->mod;)
 
                asm_node = (*transform)(&tenv);
@@ -3033,11 +3070,16 @@ static void transform_psi_cond(ir_node *cond, ir_mode *mode, ia32_code_gen_t *cg
                                /* Psi is float, we need a floating point compare */
 
                                if (USE_SSE2(cg)) {
+                                       ir_mode *m = get_irn_mode(cmp_a);
                                        /* SSE FPU */
-                                       if (! mode_is_float(get_irn_mode(cmp_a))) {
+                                       if (! mode_is_float(m)) {
                                                cmp_a = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_a, cmp_a, mode);
                                                cmp_b = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_b, cmp_b, mode);
-                                               pnc  |= 8;
+                                       }
+                                       else if (m == mode_F) {
+                                               /* we convert cmp values always to double, to get correct bitmask with cmpsd */
+                                               cmp_a = gen_sse_conv_f2d(cg, dbg, irg, block, cmp_a, cmp_a);
+                                               cmp_b = gen_sse_conv_f2d(cg, dbg, irg, block, cmp_b, cmp_b);
                                        }
 
                                        new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);