OSDN Git Service

PR rtl-optimization/29329
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Jan 2007 22:32:39 +0000 (22:32 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Jan 2007 22:32:39 +0000 (22:32 +0000)
* combine.c (replaced_rhs_insn): Rename to i2mod.
(replaced_rhs_value): Rename to i2mod_new_rhs.
(i2mod_old_rhs): New global variable.
(combine_instructions): Adjust for above change.  Save a copy of
the old RHS into i2mod_old_rhs when the contents of a REG_EQUAL
note are substituted in the second instruction.
(distribute_notes) <REG_DEAD>: Adjust for above change.  Do not
ditch the note if it pertains to the second eliminated register
and this register is mentioned in i2mod_old_rhs.

Revert:
2006-09-12  Eric Botcazou  <ebotcazou@libertysurf.fr>

* combine.c (distribute_notes) <REG_DEAD>: Do not consider SETs past
the insn to which the note was originally attached.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121037 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20070121.c [new file with mode: 0644]

index a201681..da8bbf5 100644 (file)
@@ -1,3 +1,22 @@
+2007-01-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR rtl-optimization/29329
+       * combine.c (replaced_rhs_insn): Rename to i2mod.
+       (replaced_rhs_value): Rename to i2mod_new_rhs.
+       (i2mod_old_rhs): New global variable.
+       (combine_instructions): Adjust for above change.  Save a copy of
+       the old RHS into i2mod_old_rhs when the contents of a REG_EQUAL
+       note are substituted in the second instruction.
+       (distribute_notes) <REG_DEAD>: Adjust for above change.  Do not
+       ditch the note if it pertains to the second eliminated register
+       and this register is mentioned in i2mod_old_rhs.
+
+       Revert:
+       2006-09-12  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * combine.c (distribute_notes) <REG_DEAD>: Do not consider SETs past
+       the insn to which the note was originally attached.
+
 2007-01-21  Jan Hubicka  <jh@suse.cz>
 
        * ipa-inline.c (inlining_mode): Comment, move up.
index 32117be..aa1e2ce 100644 (file)
@@ -123,16 +123,22 @@ static int combine_successes;
 
 static int total_attempts, total_merges, total_extras, total_successes;
 
-/* Sometimes combine tries to replace the right hand side of an insn
-   with the value of a REG_EQUAL note.  This is the insn that has been
-   so modified, or null if none.  */
+/* combine_instructions may try to replace the right hand side of the
+   second instruction with the value of an associated REG_EQUAL note
+   before throwing it at try_combine.  That is problematic when there
+   is a REG_DEAD note for a register used in the old right hand side
+   and can cause distribute_notes to do wrong things.  This is the
+   second instruction if it has been so modified, null otherwise.  */
 
-static rtx replaced_rhs_insn;
+static rtx i2mod;
 
-/* When REPLACED_RHS_INSN is nonnull, this is a copy of the new right
-   hand side.  */
+/* When I2MOD is nonnull, this is a copy of the old right hand side.  */
 
-static rtx replaced_rhs_value;
+static rtx i2mod_old_rhs;
+
+/* When I2MOD is nonnull, this is a copy of the new right hand side.  */
+
+static rtx i2mod_new_rhs;
 \f
 /* Vector mapping INSN_UIDs to cuids.
    The cuids are like uids but increase monotonically always.
@@ -932,11 +938,12 @@ combine_instructions (rtx f, unsigned int nregs)
                         be deleted or recognized by try_combine.  */
                      rtx orig = SET_SRC (set);
                      SET_SRC (set) = note;
-                     replaced_rhs_insn = temp;
-                     replaced_rhs_value = copy_rtx (note);
-                     next = try_combine (insn, temp, NULL_RTX,
+                     i2mod = temp;
+                     i2mod_old_rhs = copy_rtx (orig);
+                     i2mod_new_rhs = copy_rtx (note);
+                     next = try_combine (insn, i2mod, NULL_RTX,
                                          &new_direct_jump_p);
-                     replaced_rhs_insn = NULL;
+                     i2mod = NULL_RTX;
                      if (next)
                        goto retry;
                      SET_SRC (set) = orig;
@@ -12140,8 +12147,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
             use of A and put the death note there.  */
 
          if (from_insn
-             && from_insn == replaced_rhs_insn
-             && !reg_overlap_mentioned_p (XEXP (note, 0), replaced_rhs_value))
+             && from_insn == i2mod
+             && !reg_overlap_mentioned_p (XEXP (note, 0), i2mod_new_rhs))
            tem = from_insn;
          else
            {
@@ -12154,7 +12161,10 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
              else if (i2 != 0 && next_nonnote_insn (i2) == i3
                       && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
                place = i2;
-             else if (rtx_equal_p (XEXP (note, 0), elim_i2)
+             else if ((rtx_equal_p (XEXP (note, 0), elim_i2)
+                       && !(i2mod
+                            && reg_overlap_mentioned_p (XEXP (note, 0),
+                                                        i2mod_old_rhs)))
                       || rtx_equal_p (XEXP (note, 0), elim_i1))
                break;
              tem = i3;
@@ -12173,14 +12183,12 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                      continue;
                    }
 
-                 /* If TEM is a (reaching) definition of the use to which the
-                    note was attached, see if that is all TEM is doing.  If so,
-                    delete TEM.  Otherwise, make this into a REG_UNUSED note
-                    instead.  Don't delete sets to global register vars.  */
-                 if ((!from_insn
-                      || INSN_CUID (tem) < INSN_CUID (from_insn))
-                     && (REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
-                         || !global_regs[REGNO (XEXP (note, 0))])
+                 /* If the register is being set at TEM, see if that is all
+                    TEM is doing.  If so, delete TEM.  Otherwise, make this
+                    into a REG_UNUSED note instead. Don't delete sets to
+                    global register vars.  */
+                 if ((REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
+                      || !global_regs[REGNO (XEXP (note, 0))])
                      && reg_set_p (XEXP (note, 0), PATTERN (tem)))
                    {
                      rtx set = single_set (tem);
index e92e40b..ff69cda 100644 (file)
@@ -1,3 +1,7 @@
+2007-01-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.c-torture/compile/20070121.c: New test.
+
 2007-01-21  Thomas Koenig  <Thomas.Koenig@online.de>
 
        PR libfortran/30525
diff --git a/gcc/testsuite/gcc.c-torture/compile/20070121.c b/gcc/testsuite/gcc.c-torture/compile/20070121.c
new file mode 100644 (file)
index 0000000..88af8bf
--- /dev/null
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/29329 */
+/* Origin: Debian GCC Maintainers <debian-gcc@lists.debian.org> */
+/* Testcase by: Andrew Pinski <pinskia@gmail.com> */
+
+struct node234_Tag
+{
+  int t1;
+  int kids[4];
+  void *elems[3];
+};
+
+void *add234_internal(struct node234_Tag *n, int ei)
+{
+  int j;
+  for (j = ei; j < 2 && n->elems[j+1];)
+    j++;
+  n->kids[j+1] = 0;
+}