re PR target/28146 (-O2 produces invalid code on s390-linux-gnu: gcc-4.1.2 20060608)
authorAlexandre Oliva <aoliva@redhat.com>
Thu, 17 Aug 2006 08:55:02 +0000 (08:55 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 17 Aug 2006 08:55:02 +0000 (08:55 +0000)
PR target/28146
* reload.h (reg_equiv_alt_mem_list): New declaration.
* reload1.c (reg_equiv_alt_mem_list): New definition.
(reload): Initialize it and release it.
(delete_output_reload): Use it.
* reload.c (push_reg_equiv_alt_mem): New function.
(find_reloads_toplev): Call it.
(find_reloads_address, find_reloads_address_1): Likewise.
(find_reloads_subreg_address): Likewise.

From-SVN: r116215

gcc/ChangeLog
gcc/reload.c
gcc/reload.h
gcc/reload1.c

index 240bddb..9794ce2 100644 (file)
@@ -1,3 +1,15 @@
+2006-08-17  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR target/28146
+       * reload.h (reg_equiv_alt_mem_list): New declaration.
+       * reload1.c (reg_equiv_alt_mem_list): New definition.
+       (reload): Initialize it and release it.
+       (delete_output_reload): Use it.
+       * reload.c (push_reg_equiv_alt_mem): New function.
+       (find_reloads_toplev): Call it.
+       (find_reloads_address, find_reloads_address_1): Likewise.
+       (find_reloads_subreg_address): Likewise.
+
 2006-08-17  Maxim Kuvyrkov  <mkuvyrkov@ispras.ru>
 
        PR rtl-optimization/28489
index c8c48b1..e1a4abc 100644 (file)
@@ -283,6 +283,23 @@ static int find_inc_amount (rtx, rtx);
 static int refers_to_mem_for_reload_p (rtx);
 static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
                                         rtx, rtx *);
+
+/* Add NEW to reg_equiv_alt_mem_list[REGNO] if it's not present in the
+   list yet.  */
+
+static void
+push_reg_equiv_alt_mem (int regno, rtx mem)
+{
+  rtx it;
+
+  for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+    if (rtx_equal_p (XEXP (it, 0), mem))
+      return;
+
+  reg_equiv_alt_mem_list [regno]
+    = alloc_EXPR_LIST (REG_EQUIV, mem,
+                      reg_equiv_alt_mem_list [regno]);
+}
 \f
 /* Determine if any secondary reloads are needed for loading (if IN_P is
    nonzero) or storing (if IN_P is zero) X to or from a reload register of
@@ -4553,6 +4570,8 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
              x = mem;
              i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
                                        opnum, type, ind_levels, insn);
+             if (x != mem)
+               push_reg_equiv_alt_mem (regno, x);
              if (address_reloaded)
                *address_reloaded = i;
            }
@@ -4761,9 +4780,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
              tem = make_memloc (ad, regno);
              if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
                {
+                 rtx orig = tem;
+
                  find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
                                        &XEXP (tem, 0), opnum,
                                        ADDR_TYPE (type), ind_levels, insn);
+                 if (tem != orig)
+                   push_reg_equiv_alt_mem (regno, tem);
                }
              /* We can avoid a reload if the register's equivalent memory
                 expression is valid as an indirect memory address.
@@ -5545,6 +5568,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
            if (reg_equiv_address[regno]
                || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
              {
+               rtx orig = tem;
+
                /* First reload the memory location's address.
                    We can't use ADDR_TYPE (type) here, because we need to
                    write back the value after reading it, hence we actually
@@ -5554,6 +5579,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                                      RELOAD_OTHER,
                                      ind_levels, insn);
 
+               if (tem != orig)
+                 push_reg_equiv_alt_mem (regno, tem);
+
                /* Then reload the memory location into a base
                   register.  */
                reloadnum = push_reload (tem, tem, &XEXP (x, 0),
@@ -5609,6 +5637,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              if (reg_equiv_address[regno]
                  || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
                {
+                 rtx orig = tem;
+
                  /* First reload the memory location's address.
                     We can't use ADDR_TYPE (type) here, because we need to
                     write back the value after reading it, hence we actually
@@ -5616,6 +5646,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                  find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
                                        &XEXP (tem, 0), opnum, type,
                                        ind_levels, insn);
+                 if (tem != orig)
+                   push_reg_equiv_alt_mem (regno, tem);
                  /* Put this inside a new increment-expression.  */
                  x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
                  /* Proceed to reload that, as if it contained a register.  */
@@ -5806,6 +5838,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
                                      &XEXP (x, 0), opnum, ADDR_TYPE (type),
                                      ind_levels, insn);
+               if (x != tem)
+                 push_reg_equiv_alt_mem (regno, x);
              }
          }
 
@@ -5993,6 +6027,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
              unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
              int offset;
+             rtx orig = tem;
 
              /* For big-endian paradoxical subregs, SUBREG_BYTE does not
                 hold the correct (negative) byte offset.  */
@@ -6028,6 +6063,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
                                    &XEXP (tem, 0), opnum, type,
                                    ind_levels, insn);
+             /* ??? Do we need to handle nonzero offsets somehow?  */
+             if (!offset && tem != orig)
+               push_reg_equiv_alt_mem (regno, tem);
 
              /* If this is not a toplevel operand, find_reloads doesn't see
                 this substitution.  We have to emit a USE of the pseudo so
index fbb315e..6de5e84 100644 (file)
@@ -161,6 +161,7 @@ extern rtx *reg_equiv_invariant;
 extern rtx *reg_equiv_memory_loc;
 extern rtx *reg_equiv_address;
 extern rtx *reg_equiv_mem;
+extern rtx *reg_equiv_alt_mem_list;
 
 /* Element N is the list of insns that initialized reg N from its equivalent
    constant or memory slot.  */
index 210b007..8ce042f 100644 (file)
@@ -123,6 +123,10 @@ rtx *reg_equiv_address;
    or zero if pseudo reg N is not equivalent to a memory slot.  */
 rtx *reg_equiv_mem;
 
+/* Element N is an EXPR_LIST of REG_EQUIVs containing MEMs with
+   alternate representations of the location of pseudo reg N.  */
+rtx *reg_equiv_alt_mem_list;
+
 /* Widest width in which each pseudo reg is referred to (via subreg).  */
 static unsigned int *reg_max_ref_width;
 
@@ -703,6 +707,7 @@ reload (rtx first, int global)
   reg_equiv_constant = XCNEWVEC (rtx, max_regno);
   reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
   reg_equiv_mem = XCNEWVEC (rtx, max_regno);
+  reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
   reg_equiv_address = XCNEWVEC (rtx, max_regno);
   reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
   reg_old_renumber = XCNEWVEC (short, max_regno);
@@ -1260,6 +1265,11 @@ reload (rtx first, int global)
   if (offsets_at)
     free (offsets_at);
 
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (reg_equiv_alt_mem_list[i])
+      free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
+  free (reg_equiv_alt_mem_list);
+
   free (reg_equiv_mem);
   reg_equiv_init = 0;
   free (reg_equiv_address);
@@ -7849,6 +7859,11 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
     n_occurrences += count_occurrences (PATTERN (insn),
                                        eliminate_regs (substed, 0,
                                                        NULL_RTX), 0);
+  for (i1 = reg_equiv_alt_mem_list [REGNO (reg)]; i1; i1 = XEXP (i1, 1))
+    {
+      gcc_assert (!rtx_equal_p (XEXP (i1, 0), substed));
+      n_occurrences += count_occurrences (PATTERN (insn), XEXP (i1, 0), 0);
+    }
   if (n_occurrences > n_inherited)
     return;