OSDN Git Service

PR preprocessor/6521
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 3b4bb2d..3974e99 100644 (file)
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "real.h"
 #include "toplev.h"
 #include "except.h"
+#include "tree.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -790,7 +791,12 @@ reload (first, global)
              i = REGNO (SET_DEST (set));
              if (i > LAST_VIRTUAL_REGISTER)
                {
-                 if (GET_CODE (x) == MEM)
+                 /* It can happen that a REG_EQUIV note contains a MEM
+                    that is not a legitimate memory operand.  As later
+                    stages of reload assume that all addresses found
+                    in the reg_equiv_* arrays were originally legitimate,
+                    we ignore such REG_EQUIV notes.  */
+                 if (memory_operand (x, VOIDmode))
                    {
                      /* Always unshare the equivalence, so we can
                         substitute into this insn without touching the
@@ -1154,9 +1160,9 @@ reload (first, global)
            {
              rtx reg = regno_reg_rtx[i];
 
+             REG_USERVAR_P (reg) = 0;
              PUT_CODE (reg, MEM);
              XEXP (reg, 0) = addr;
-             REG_USERVAR_P (reg) = 0;
              if (reg_equiv_memory_loc[i])
                MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
              else
@@ -2062,10 +2068,19 @@ alter_reg (i, from_reg)
         memory.  If this is a shared MEM, make a copy.  */
       if (REGNO_DECL (i))
        {
-         if (from_reg != -1 && spill_stack_slot[from_reg] == x)
-           x = copy_rtx (x);
+         rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
+
+         /* We can do this only for the DECLs home pseudo, not for
+            any copies of it, since otherwise when the stack slot
+            is reused, nonoverlapping_memrefs_p might think they
+            cannot overlap.  */
+         if (decl && GET_CODE (decl) == REG && REGNO (decl) == (unsigned) i)
+           {
+             if (from_reg != -1 && spill_stack_slot[from_reg] == x)
+               x = copy_rtx (x);
 
-         set_mem_expr (x, REGNO_DECL (i));
+             set_mem_expr (x, REGNO_DECL (i));
+           }
        }
 
       /* Save the stack slot for later.  */
@@ -2558,7 +2573,7 @@ eliminate_regs (x, mem_mode, insn)
                   )
                  || x_size == new_size)
              )
-           return adjust_address_nv (x, GET_MODE (x), SUBREG_BYTE (x));
+           return adjust_address_nv (new, GET_MODE (x), SUBREG_BYTE (x));
          else
            return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
        }
@@ -5560,6 +5575,7 @@ choose_reload_regs (chain)
                                  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
                              /* Don't clobber the frame pointer.  */
                              || (i == HARD_FRAME_POINTER_REGNUM
+                                 && frame_pointer_needed
                                  && rld[r].out)
                              /* Don't really use the inherited spill reg
                                 if we need it wider than we've got it.  */
@@ -5730,7 +5746,9 @@ choose_reload_regs (chain)
 
              /* If we found an equivalent reg, say no code need be generated
                 to load it, and use it as our reload reg.  */
-             if (equiv != 0 && regno != HARD_FRAME_POINTER_REGNUM)
+             if (equiv != 0 
+                 && (regno != HARD_FRAME_POINTER_REGNUM 
+                     || !frame_pointer_needed))
                {
                  int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
                  int k;
@@ -8019,6 +8037,7 @@ static void
 reload_cse_delete_noop_set (insn, value)
      rtx insn, value;
 {
+  bool purge = BLOCK_FOR_INSN (insn)->end == insn;
   if (value)
     {
       PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
@@ -8027,6 +8046,8 @@ reload_cse_delete_noop_set (insn, value)
     }
   else
     delete_insn (insn);
+  if (purge)
+    purge_dead_edges (BLOCK_FOR_INSN (insn));
 }
 
 /* See whether a single set SET is a noop.  */
@@ -8058,7 +8079,8 @@ reload_cse_simplify (insn)
       if (!count && reload_cse_noop_set_p (body))
        {
          rtx value = SET_DEST (body);
-         if (! REG_FUNCTION_VALUE_P (SET_DEST (body)))
+         if (GET_CODE (body) == REG
+             && ! REG_FUNCTION_VALUE_P (SET_DEST (body)))
            value = 0;
          reload_cse_delete_noop_set (insn, value);
          return;
@@ -9509,8 +9531,19 @@ fixup_abnormal_edges ()
              next = NEXT_INSN (insn);
              if (INSN_P (insn))
                {
-                 insert_insn_on_edge (PATTERN (insn), e);
+                 rtx seq;
+
                  delete_insn (insn);
+
+                 /* We're not deleting it, we're moving it.  */
+                 INSN_DELETED_P (insn) = 0;
+
+                 /* Emit a sequence, rather than scarfing the pattern, so
+                    that we don't lose REG_NOTES etc.  */
+                 /* ??? Could copy the test from gen_sequence, but don't
+                    think it's worth the bother.  */
+                 seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
+                 insert_insn_on_edge (seq, e);
                }
              insn = next;
            }