fix bad proj optimisation, fix loads missing the result proj
authorMatthias Braun <matze@braunis.de>
Mon, 11 Jun 2007 23:01:50 +0000 (23:01 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 11 Jun 2007 23:01:50 +0000 (23:01 +0000)
[r14421]

ir/be/ia32/ia32_optimize.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index 600fb26..fb72b6e 100644 (file)
@@ -1253,6 +1253,23 @@ static void optimize_load_conv(ia32_code_gen_t *cg, ir_node *node)
        if(get_mode_size_bits(conv_mode) < get_mode_size_bits(load_mode))
                return;
 
+       if(get_mode_sign(conv_mode) != get_mode_sign(load_mode)) {
+               /* change the load if it has only 1 user */
+               if(get_irn_n_edges(pred) == 1) {
+                       ir_mode *newmode;
+                       if(get_mode_sign(conv_mode)) {
+                               newmode = find_signed_mode(load_mode);
+                       } else {
+                               newmode = find_unsigned_mode(load_mode);
+                       }
+                       assert(newmode != NULL);
+                       set_ia32_ls_mode(predpred, newmode);
+               } else {
+                       /* otherwise we have to keep the conv */
+                       return;
+               }
+       }
+
        /* kill the conv */
        exchange(node, pred);
 }
@@ -1266,7 +1283,8 @@ static void optimize_conv_conv(ia32_code_gen_t *cg, ir_node *node)
        if (!is_ia32_Conv_I2I(node) && !is_ia32_Conv_I2I8Bit(node))
                return;
 
-       pred = get_irn_n(node, 2);
+       assert(n_ia32_Conv_I2I_val == n_ia32_Conv_I2I8Bit_val);
+       pred = get_irn_n(node, n_ia32_Conv_I2I_val);
        if(!is_ia32_Conv_I2I(pred) && !is_ia32_Conv_I2I8Bit(pred))
                return;
 
@@ -1277,6 +1295,11 @@ static void optimize_conv_conv(ia32_code_gen_t *cg, ir_node *node)
        if(get_mode_size_bits(conv_mode) < get_mode_size_bits(pred_mode))
                return;
 
+       /* we can't eliminate an upconv signed->unsigned  */
+       if (get_mode_size_bits(conv_mode) != get_mode_size_bits(pred_mode) &&
+               !get_mode_sign(conv_mode) && get_mode_sign(pred_mode))
+               return;
+
        /* kill the conv */
        exchange(node, pred);
 }
index b1d0af6..9cc0454 100644 (file)
@@ -1273,12 +1273,14 @@ CopyB_i => {
 Conv_I2I => {
        reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] },
        units    => [ "GP" ],
+       ins      => [ "base", "index", "val", "mem" ],
        mode     => $mode_gp,
        modified_flags => $status_flags
 },
 
 Conv_I2I8Bit => {
        reg_req  => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] },
+       ins      => [ "base", "index", "val", "mem" ],
        units    => [ "GP" ],
        mode     => $mode_gp,
        modified_flags => $status_flags
index 1bf0084..a30b333 100644 (file)
@@ -1610,6 +1610,7 @@ static ir_node *gen_Load(ir_node *node) {
        dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_node  *noreg   = ia32_new_NoReg_gp(env.cg);
        ir_mode  *mode    = get_Load_mode(node);
+       ir_mode  *res_mode;
        ir_node  *lptr    = new_ptr;
        int      is_imm   = 0;
        ir_node  *new_op;
@@ -1618,17 +1619,6 @@ static ir_node *gen_Load(ir_node *node) {
 
        ia32_collect_Projs(node, 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 (! be_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(irg, block, node, mode_Iu, pn_ia32_Load_res);
-               be_new_Keep(arch_get_irn_reg_class(env.cg->arch_env, proj, -1), irg, block, 1, &proj);
-       }
-
        /* address might be a constant (symconst or absolute address) */
        if (is_ia32_Const(new_ptr)) {
                lptr   = noreg;
@@ -1638,12 +1628,25 @@ static ir_node *gen_Load(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env.cg);
                if (USE_SSE2(env.cg)) {
-                       new_op = new_rd_ia32_xLoad(dbgi, irg, block, lptr, noreg, new_mem);
+                       new_op  = new_rd_ia32_xLoad(dbgi, irg, block, lptr, noreg, new_mem);
+                       res_mode = mode_xmm;
                } else {
-                       new_op = new_rd_ia32_vfld(dbgi, irg, block, lptr, noreg, new_mem);
+                       new_op   = new_rd_ia32_vfld(dbgi, irg, block, lptr, noreg, new_mem);
+                       res_mode = mode_vfp;
                }
        } else {
-               new_op = new_rd_ia32_Load(dbgi, irg, block, lptr, noreg, new_mem);
+               new_op   = new_rd_ia32_Load(dbgi, irg, block, lptr, noreg, new_mem);
+               res_mode = mode_Iu;
+       }
+
+       /*
+               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_op, mode_Iu,
+                                          pn_ia32_Load_res);
+               be_new_Keep(arch_get_irn_reg_class(env.cg->arch_env, proj, -1), irg, block, 1, &proj);
        }
 
        /* base is a constant address */