rtlanal.c (multiple_sets): New function.
authorJeffrey A Law <law@cygnus.com>
Sat, 12 Dec 1998 23:03:54 +0000 (23:03 +0000)
committerJeff Law <law@gcc.gnu.org>
Sat, 12 Dec 1998 23:03:54 +0000 (16:03 -0700)
        * rtlanal.c (multiple_sets): New function.
        * rtl.h (multiple_sets): Declare it.
        * local-alloc.c (wipe_dead_reg): Use it.
        * global.c (global_conflicts): Likewise.
Should fix the m68k bootstrap problems.

From-SVN: r24283

gcc/ChangeLog
gcc/global.c
gcc/local-alloc.c
gcc/rtl.h
gcc/rtlanal.c

index f2a101bda07dcbbe97657cb87ba0431c1bb4a7dc..b0e12f6249f1fe022e5a86bcac663d1a85219d1e 100644 (file)
@@ -1,3 +1,10 @@
+Sat Dec 12 23:39:10 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * rtlanal.c (multiple_sets): New function.
+       * rtl.h (multiple_sets): Declare it.
+       * local-alloc.c (wipe_dead_reg): Use it.
+       * global.c (global_conflicts): Likewise.
+
 Sat Dec 12 22:13:02 1998  Mark Mitchell  <mark@markmitchell.com>
 
        * global.c (record_conflicts): Don't use an array of shorts to
index 67201726e3cee1f1804d91a7779b41c3cfcaa6ba..06277ee5365ff4e99dc11efde04acc38beb0f52d 100644 (file)
@@ -739,9 +739,16 @@ global_conflicts ()
 
              /* If INSN has multiple outputs, then any reg that dies here
                 and is used inside of an output
-                must conflict with the other outputs.  */
-
-             if (GET_CODE (PATTERN (insn)) == PARALLEL && !single_set (insn))
+                must conflict with the other outputs.
+
+                It is unsafe to use !single_set here since it will ignore an
+                unused output.  Just because an output is unused does not mean
+                the compiler can assume the side effect will not occur.
+                Consider if REG appears in the address of an output and we
+                reload the output.  If we allocate REG to the same hard
+                register as an unused output we could set the hard register
+                before the output reload insn.  */
+             if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
                for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
                  if (REG_NOTE_KIND (link) == REG_DEAD)
                    {
index f7d12d2e1e085676ce5be1aeaaea85e9f262569a..85cb8af555b44c8ec40873a3f8cf971293e1b15d 100644 (file)
@@ -1876,9 +1876,16 @@ wipe_dead_reg (reg, output_p)
   /* If this insn has multiple results,
      and the dead reg is used in one of the results,
      extend its life to after this insn,
-     so it won't get allocated together with any other result of this insn.  */
+     so it won't get allocated together with any other result of this insn. 
+
+     It is unsafe to use !single_set here since it will ignore an unused
+     output.  Just because an output is unused does not mean the compiler
+     can assume the side effect will not occur.   Consider if REG appears
+     in the address of an output and we reload the output.  If we allocate
+     REG to the same hard register as an unused output we could set the hard
+     register before the output reload insn.  */
   if (GET_CODE (PATTERN (this_insn)) == PARALLEL
-      && !single_set (this_insn))
+      && multiple_sets (this_insn))
     {
       int i;
       for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--)
index 940de7305e1a63dbb7bd798ff1ab501c6e229fd1..95ddbd1617c234b6ee9079b3a6d8e3b4248ab170 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -988,6 +988,7 @@ extern int no_labels_between_p              PROTO((rtx, rtx));
 extern int modified_in_p               PROTO((rtx, rtx));
 extern int reg_set_p                   PROTO((rtx, rtx));
 extern rtx single_set                  PROTO((rtx));
+extern rtx multiple_sets               PROTO((rtx));
 extern rtx find_last_value             PROTO((rtx, rtx *, rtx));
 extern int refers_to_regno_p           PROTO((int, int, rtx, rtx *));
 extern int reg_overlap_mentioned_p     PROTO((rtx, rtx));
index 0abe2447165412c0f118b8e25a13baea1be38c75..f298ab2f5efb7d64b895719dcc0ebddf906189ed 100644 (file)
@@ -690,6 +690,38 @@ single_set (insn)
   
   return 0;
 }
+
+/* Given an INSN, return nonzero if it has more than one SET, else return
+   zero.  */
+
+rtx
+multiple_sets (insn)
+     rtx insn;
+{
+  rtx found;
+  int i;
+  
+  /* INSN must be an insn.  */
+  if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+    return 0;
+
+  /* Only a PARALLEL can have multiple SETs.  */
+  if (GET_CODE (PATTERN (insn)) == PARALLEL)
+    {
+      for (i = 0, found = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+       if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
+         {
+           /* If we have already found a SET, then return now.  */
+           if (found)
+             return 1;
+           else
+             found = 1;
+         }
+    }
+  
+  /* Either zero or one SET.  */
+  return 0;
+}
 \f
 /* Return the last thing that X was assigned from before *PINSN.  Verify that
    the object is not modified up to VALID_TO.  If it was, if we hit