OSDN Git Service

PR rtl-optimization/22002
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Nov 2005 00:59:21 +0000 (00:59 +0000)
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Nov 2005 00:59:21 +0000 (00:59 +0000)
* combine.c (distribute_notes): Detect cases where a reg dies
two or more times in a bb, including on the insn we are combining,
and place the death note on the correct range.

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

gcc/ChangeLog
gcc/combine.c

index 433f6d0..188d509 100644 (file)
@@ -1,3 +1,10 @@
+2005-11-15  Alan Modra  <amodra@bigpond.net.au>
+
+       PR rtl-optimization/22002
+       * combine.c (distribute_notes): Detect cases where a reg dies
+       two or more times in a bb, including on the insn we are combining,
+       and place the death note on the correct range.
+
 2005-11-14  Dale Johannesen  <dalej@apple.com>
 
        * expmed.c (store_bit_field):  Add offset unconditionally for
index 82d260d..9f910a7 100644 (file)
@@ -12232,6 +12232,10 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
            {
              basic_block bb = this_basic_block;
 
+             /* You might think you could search back from FROM_INSN
+                rather than from I3, but combine tries to split invalid
+                combined instructions.  This can result in the old I2
+                or I1 moving later in the insn sequence.  */
              for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
                {
                  if (! INSN_P (tem))
@@ -12332,6 +12336,22 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                           || (CALL_P (tem)
                               && find_reg_fusage (tem, USE, XEXP (note, 0))))
                    {
+                     /* This may not be the correct place for the death
+                        note if FROM_INSN is before TEM, and the reg is
+                        set between FROM_INSN and TEM.  The reg might
+                        die two or more times.  An existing death note
+                        means we are looking at the wrong live range.  */
+                     if (from_insn
+                         && INSN_CUID (from_insn) < INSN_CUID (tem)
+                         && find_regno_note (tem, REG_DEAD,
+                                             REGNO (XEXP (note, 0))))
+                       {
+                         tem = from_insn;
+                         if (tem == BB_HEAD (bb))
+                           break;
+                         continue;
+                       }
+
                      place = tem;
 
                      /* If we are doing a 3->2 combination, and we have a