re PR rtl-optimization/65805 (Chromium gets miscompiled)
authorVladimir Makarov <vmakarov@redhat.com>
Sun, 19 Apr 2015 23:48:24 +0000 (23:48 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Sun, 19 Apr 2015 23:48:24 +0000 (23:48 +0000)
2015-04-19  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/65805
* lra-eliminations.c (lra_eliminate_regs_1): Add new assert.
Don't use difference of offset and previous offset if
update_sp_offset is non-zero.
(eliminate_regs_in_insn): Ditto.
* lra-spills.c (remove_pseudos): Exchange 4th and 6th args in
lra_eliminate_regs_1 call.
* lra-constraints.c (get_equiv_with_elimination): Ditto.

From-SVN: r222223

gcc/ChangeLog
gcc/lra-constraints.c
gcc/lra-eliminations.c
gcc/lra-spills.c

index dacdc11916d81f18a466e92e05270bb8f6bfcb23..77fc4f9f2117bb544820d73cba3e76bcbb402522 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-19  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/65805
+       * lra-eliminations.c (lra_eliminate_regs_1): Add new assert.
+       Don't use difference of offset and previous offset if
+       update_sp_offset is non-zero.
+       (eliminate_regs_in_insn): Ditto.
+       * lra-spills.c (remove_pseudos): Exchange 4th and 6th args in
+       lra_eliminate_regs_1 call.
+       * lra-constraints.c (get_equiv_with_elimination): Ditto.
+
 2015-04-18  Trevor Saunders  <tsaunders@mozilla.com>
 
        * hash-table.h: Remove version of hash_table that stored value_type *.
index 90f351b9a0f5e7970e5ffd0504e806d78179c5b7..497d8db2d1f33fb1aa70cde1d56d2a27f42b8112 100644 (file)
@@ -533,7 +533,7 @@ get_equiv_with_elimination (rtx x, rtx_insn *insn)
   if (x == res || CONSTANT_P (res))
     return res;
   return lra_eliminate_regs_1 (insn, res, GET_MODE (res),
-                              0, false, false, true);
+                              false, false, 0, true);
 }
 
 /* Set up curr_operand_mode.  */
index 64eec4a003c81db7815fcd3f9e2dca66a99daaad..f7c8e402467a95fb434f166df2f61ff99fb95ef3 100644 (file)
@@ -318,7 +318,9 @@ get_elimination (rtx reg)
    substitution if UPDATE_P, or the full offset if FULL_P, or
    otherwise zero.  If FULL_P, we also use the SP offsets for
    elimination to SP.  If UPDATE_P, use UPDATE_SP_OFFSET for updating
-   offsets of register elimnable to SP.
+   offsets of register elimnable to SP.  If UPDATE_SP_OFFSET is
+   non-zero, don't use difference of the offset and the previous
+   offset.
 
    MEM_MODE is the mode of an enclosing MEM.  We need this to know how
    much to adjust a register for, e.g., PRE_DEC.  Also, if we are
@@ -341,7 +343,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
   const char *fmt;
   int copied = 0;
 
-  gcc_assert (!update_p || !full_p);
+  lra_assert (!update_p || !full_p);
+  lra_assert (update_sp_offset == 0 || (!subst_p && update_p && !full_p));
   if (! current_function_decl)
     return x;
 
@@ -366,11 +369,14 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
        {
          rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
 
-         if (update_p)
-           return plus_constant (Pmode, to,
-                                 ep->offset - ep->previous_offset
-                                 + (ep->to_rtx == stack_pointer_rtx
-                                    ? update_sp_offset : 0));
+         if (update_sp_offset != 0)
+           {
+             if (ep->to_rtx == stack_pointer_rtx)
+               return plus_constant (Pmode, to, update_sp_offset);
+             return to;
+           }
+         else if (update_p)
+           return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
          else if (full_p)
            return plus_constant (Pmode, to,
                                  ep->offset
@@ -395,16 +401,15 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
 
              if (! update_p && ! full_p)
                return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
-
-             offset = (update_p
-                       ? ep->offset - ep->previous_offset
-                       + (ep->to_rtx == stack_pointer_rtx
-                          ? update_sp_offset : 0)
-                       : ep->offset);
+             
+             if (update_sp_offset != 0)
+               offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
+             else
+               offset = (update_p
+                         ? ep->offset - ep->previous_offset : ep->offset);
              if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
                offset -= lra_get_insn_recog_data (insn)->sp_offset;
-             if (CONST_INT_P (XEXP (x, 1))
-                 && INTVAL (XEXP (x, 1)) == -offset)
+             if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset)
                return to;
              else
                return gen_rtx_PLUS (Pmode, to,
@@ -451,12 +456,18 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
        {
          rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
 
-         if (update_p)
+         if (update_sp_offset != 0)
+           {
+             if (ep->to_rtx == stack_pointer_rtx)
+               return plus_constant (Pmode,
+                                     gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
+                                     update_sp_offset * INTVAL (XEXP (x, 1)));
+             return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
+           }
+         else if (update_p)
            return plus_constant (Pmode,
                                  gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
-                                 (ep->offset - ep->previous_offset
-                                  + (ep->to_rtx == stack_pointer_rtx
-                                     ? update_sp_offset : 0))
+                                 (ep->offset - ep->previous_offset)
                                  * INTVAL (XEXP (x, 1)));
          else if (full_p)
            {
@@ -889,11 +900,12 @@ remove_reg_equal_offset_note (rtx insn, rtx what)
 
    If REPLACE_P is false, just update the offsets while keeping the
    base register the same.  If FIRST_P, use the sp offset for
-   elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.
-   Attach the note about used elimination for insns setting frame
-   pointer to update elimination easy (without parsing already
-   generated elimination insns to find offset previously used) in
-   future.  */
+   elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
+   UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
+   and the previous offset.  Attach the note about used elimination
+   for insns setting frame pointer to update elimination easy (without
+   parsing already generated elimination insns to find offset
+   previously used) in future.  */
 
 void
 eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
@@ -940,6 +952,10 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
                rtx src = SET_SRC (old_set);
                rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
                
+               /* We should never process such insn with non-zero
+                  UPDATE_SP_OFFSET.  */
+               lra_assert (update_sp_offset == 0);
+               
                if (off != NULL_RTX
                    || src == ep->to_rtx
                    || (GET_CODE (src) == PLUS
@@ -1026,7 +1042,8 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
 
          if (! replace_p)
            {
-             offset += (ep->offset - ep->previous_offset);
+             if (update_sp_offset == 0)
+               offset += (ep->offset - ep->previous_offset);
              if (ep->to_rtx == stack_pointer_rtx)
                {
                  if (first_p)
index 184735135dc5911ef8445b6eef9af15a0376d82f..ed678d5edb45212c1c82eb8e3f2d0edb775ecc87 100644 (file)
@@ -461,7 +461,7 @@ remove_pseudos (rtx *loc, rtx_insn *insn)
        {
          rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem,
                                        GET_MODE (pseudo_slots[i].mem),
-                                       0, false, false, true);
+                                       false, false, 0, true);
          *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x);
        }
       return;