The problem was that we had some optimzations added to the reload_cse_move2add
pass that would attempt transformations with multi-hard-register registers,
without keeping track of the validity of the values in all hard registers
involved.

The attached patch fixes this by updating reg_set_luid for all hard regs
involved in a set, and requiring identical reg_set_luid values for all
hard regs involved when using a value.

bootstrapped/regtested on i686-pc-linux-gnu
2013-05-14  Joern Rennecke <joern.renne...@embecosm.com>

        PR rtl-optimization/56833
        * postreload.c (move2add_use_add2_insn): Update reg_set_luid
        for all affected hard registers.
        (move2add_use_add3_insn): Likewise.  Check that all source hard
        regs have been set by the same set.
        (reload_cse_move2add): Before concluding that we have a pre-existing
        value, check that all destination hard registers have been set by the
        same set.

Index: postreload.c
===================================================================
--- postreload.c        (revision 198927)
+++ postreload.c        (working copy)
@@ -1749,7 +1749,10 @@ move2add_use_add2_insn (rtx reg, rtx sym
            }
        }
     }
-  reg_set_luid[regno] = move2add_luid;
+  int i = hard_regno_nregs[regno][GET_MODE (reg)] -1;
+  do
+    reg_set_luid[regno + i] = move2add_luid;
+  while (--i >= 0);
   reg_base_reg[regno] = -1;
   reg_mode[regno] = GET_MODE (reg);
   reg_symbol_ref[regno] = sym;
@@ -1793,6 +1796,14 @@ move2add_use_add3_insn (rtx reg, rtx sym
        && reg_symbol_ref[i] != NULL_RTX
        && rtx_equal_p (sym, reg_symbol_ref[i]))
       {
+       int j;
+
+       for (j = hard_regno_nregs[i][reg_mode[i]] - 1;
+            j > 0 && reg_set_luid[i+j] == reg_set_luid[i];)
+         j--;
+       if (j != 0)
+         continue;
+
        rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[i],
                                    GET_MODE (reg));
        /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
@@ -1835,7 +1846,10 @@ move2add_use_add3_insn (rtx reg, rtx sym
       if (validate_change (insn, &SET_SRC (pat), tem, 0))
        changed = true;
     }
-  reg_set_luid[regno] = move2add_luid;
+  i = hard_regno_nregs[regno][GET_MODE (reg)] -1;
+  do
+    reg_set_luid[regno + i] = move2add_luid;
+  while (--i >= 0);
   reg_base_reg[regno] = -1;
   reg_mode[regno] = GET_MODE (reg);
   reg_symbol_ref[regno] = sym;
@@ -1890,7 +1904,10 @@ reload_cse_move2add (rtx first)
 
          /* Check if we have valid information on the contents of this
             register in the mode of REG.  */
-         if (reg_set_luid[regno] > move2add_last_label_luid
+         for (i = hard_regno_nregs[regno][GET_MODE (reg)] - 1;
+              i > 0 && reg_set_luid[regno + i] == reg_set_luid[regno];)
+           i--;
+         if (i == 0 && reg_set_luid[regno] > move2add_last_label_luid
              && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
               && dbg_cnt (cse2_move2add))
            {
@@ -2021,7 +2038,10 @@ reload_cse_move2add (rtx first)
 
              /* If the reg already contains the value which is sum of
                 sym and some constant value, we can use an add2 insn.  */
-             if (reg_set_luid[regno] > move2add_last_label_luid
+             for (i = hard_regno_nregs[regno][GET_MODE (reg)] - 1;
+                  i > 0 && reg_set_luid[regno + i] == reg_set_luid[regno];)
+               i--;
+             if (i == 0 && reg_set_luid[regno] > move2add_last_label_luid
                  && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
                  && reg_base_reg[regno] < 0
                  && reg_symbol_ref[regno] != NULL_RTX

Reply via email to