OSDN Git Service

Add new test - do not warn about (non-)redundant friend declaration.
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 2f64c2d..dbf99d6 100644 (file)
@@ -28,8 +28,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "obstack.h"
 #include "insn-config.h"
-#include "insn-flags.h"
-#include "insn-codes.h"
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
@@ -456,6 +454,7 @@ static void move2add_note_store             PARAMS ((rtx, rtx, void *));
 #ifdef AUTO_INC_DEC
 static void add_auto_inc_notes         PARAMS ((rtx, rtx));
 #endif
+static void copy_eh_notes              PARAMS ((rtx, rtx));
 static HOST_WIDE_INT sext_for_mode     PARAMS ((enum machine_mode,
                                                 HOST_WIDE_INT));
 static void failed_reload              PARAMS ((rtx, int));
@@ -680,7 +679,7 @@ reload (first, global)
 
   /* The two pointers used to track the true location of the memory used
      for label offsets.  */
-  char *real_known_ptr = NULL_PTR;
+  char *real_known_ptr = NULL;
   int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
 
   /* Make sure even insns with volatile mem refs are recognizable.  */
@@ -692,7 +691,7 @@ reload (first, global)
 
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
-  emit_note (NULL_PTR, NOTE_INSN_DELETED);
+  emit_note (NULL, NOTE_INSN_DELETED);
 
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
@@ -2511,7 +2510,7 @@ eliminate_regs (x, mem_mode, insn)
       return x;
 
     case SUBREG:
-      /* Similar to above processing, but preserve SUBREG_WORD.
+      /* Similar to above processing, but preserve SUBREG_BYTE.
         Convert (subreg (mem)) to (mem) if not paradoxical.
         Also, if we have a non-paradoxical (subreg (pseudo)) and the
         pseudo didn't get a hard reg, we must replace this with the
@@ -2528,7 +2527,7 @@ eliminate_regs (x, mem_mode, insn)
       else
        new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
 
-      if (new != XEXP (x, 0))
+      if (new != SUBREG_REG (x))
        {
          int x_size = GET_MODE_SIZE (GET_MODE (x));
          int new_size = GET_MODE_SIZE (GET_MODE (new));
@@ -2549,20 +2548,15 @@ eliminate_regs (x, mem_mode, insn)
                  || (x_size == new_size))
              )
            {
-             int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+             int offset = SUBREG_BYTE (x);
              enum machine_mode mode = GET_MODE (x);
 
-             if (BYTES_BIG_ENDIAN)
-               offset += (MIN (UNITS_PER_WORD,
-                               GET_MODE_SIZE (GET_MODE (new)))
-                          - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
-
              PUT_MODE (new, mode);
              XEXP (new, 0) = plus_constant (XEXP (new, 0), offset);
              return new;
            }
          else
-           return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_WORD (x));
+           return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
        }
 
       return x;
@@ -2588,6 +2582,12 @@ eliminate_regs (x, mem_mode, insn)
        return x;
 
     case USE:
+      /* Handle insn_list USE that a call to a pure function may generate.  */
+      new = eliminate_regs (XEXP (x, 0), 0, insn);
+      if (new != XEXP (x, 0))
+       return gen_rtx_USE (GET_MODE (x), new);
+      return x;
+
     case CLOBBER:
     case ASM_OPERANDS:
     case SET:
@@ -4084,10 +4084,14 @@ forget_old_reloads_1 (x, ignored, data)
   unsigned int nr;
   int offset = 0;
 
-  /* note_stores does give us subregs of hard regs.  */
+  /* note_stores does give us subregs of hard regs,
+     subreg_regno_offset will abort if it is not a hard reg.  */
   while (GET_CODE (x) == SUBREG)
     {
-      offset += SUBREG_WORD (x);
+      offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+                                    GET_MODE (SUBREG_REG (x)),
+                                    SUBREG_BYTE (x),
+                                    GET_MODE (x));
       x = SUBREG_REG (x);
     }
 
@@ -5397,7 +5401,7 @@ choose_reload_regs (chain)
 
          if (inheritance)
            {
-             int word = 0;
+             int byte = 0;
              register int regno = -1;
              enum machine_mode mode = VOIDmode;
 
@@ -5416,10 +5420,10 @@ choose_reload_regs (chain)
              else if (GET_CODE (rld[r].in_reg) == SUBREG
                       && GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
                {
-                 word = SUBREG_WORD (rld[r].in_reg);
+                 byte = SUBREG_BYTE (rld[r].in_reg);
                  regno = REGNO (SUBREG_REG (rld[r].in_reg));
                  if (regno < FIRST_PSEUDO_REGISTER)
-                   regno += word;
+                   regno = subreg_regno (rld[r].in_reg);
                  mode = GET_MODE (rld[r].in_reg);
                }
 #ifdef AUTO_INC_DEC
@@ -5440,7 +5444,7 @@ choose_reload_regs (chain)
                 that can invalidate an inherited reload of part of a pseudoreg.  */
              else if (GET_CODE (rld[r].in) == SUBREG
                       && GET_CODE (SUBREG_REG (rld[r].in)) == REG)
-               regno = REGNO (SUBREG_REG (rld[r].in)) + SUBREG_WORD (rld[r].in);
+               regno = subreg_regno (rld[r].in);
 #endif
 
              if (regno >= 0 && reg_last_reload_reg[regno] != 0)
@@ -5449,15 +5453,15 @@ choose_reload_regs (chain)
                  rtx last_reg = reg_last_reload_reg[regno];
                  enum machine_mode need_mode;
 
-                 i = REGNO (last_reg) + word;
+                 i = REGNO (last_reg);
+                 i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
                  last_class = REGNO_REG_CLASS (i);
 
-                 if (word == 0)
+                 if (byte == 0)
                    need_mode = mode;
                  else
                    need_mode
-                     = smallest_mode_for_size (GET_MODE_SIZE (mode)
-                                               + word * UNITS_PER_WORD,
+                     = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
                                                GET_MODE_CLASS (mode));
 
                  if (
@@ -5614,7 +5618,7 @@ choose_reload_regs (chain)
            {
              register rtx equiv
                = find_equiv_reg (search_equiv, insn, rld[r].class,
-                                 -1, NULL_PTR, 0, rld[r].mode);
+                                 -1, NULL, 0, rld[r].mode);
              int regno = 0;
 
              if (equiv != 0)
@@ -5627,7 +5631,7 @@ choose_reload_regs (chain)
                         Make a new REG since this might be used in an
                         address and not all machines support SUBREGs
                         there.  */
-                     regno = REGNO (SUBREG_REG (equiv)) + SUBREG_WORD (equiv);
+                     regno = subreg_regno (equiv);
                      equiv = gen_rtx_REG (rld[r].mode, regno);
                    }
                  else
@@ -6161,7 +6165,7 @@ emit_input_reload_insns (chain, rl, old, j)
     oldequiv
       = find_equiv_reg (old, insn,
                        rld[rl->secondary_in_reload].class,
-                       -1, NULL_PTR, 0, mode);
+                       -1, NULL, 0, mode);
 #endif
 
   /* If reloading from memory, see if there is a register
@@ -6177,8 +6181,7 @@ emit_input_reload_insns (chain, rl, old, j)
          || (GET_CODE (old) == REG
              && REGNO (old) >= FIRST_PSEUDO_REGISTER
              && reg_renumber[REGNO (old)] < 0)))
-    oldequiv = find_equiv_reg (old, insn, ALL_REGS,
-                              -1, NULL_PTR, 0, mode);
+    oldequiv = find_equiv_reg (old, insn, ALL_REGS, -1, NULL, 0, mode);
 
   if (oldequiv)
     {
@@ -6257,7 +6260,7 @@ emit_input_reload_insns (chain, rl, old, j)
     oldequiv = SUBREG_REG (oldequiv);
   if (GET_MODE (oldequiv) != VOIDmode
       && mode != GET_MODE (oldequiv))
-    oldequiv = gen_rtx_SUBREG (mode, oldequiv, 0);
+    oldequiv = gen_lowpart_SUBREG (mode, oldequiv);
 
   /* Switch to the right place to emit the reload insns.  */
   switch (rl->when_needed)
@@ -6569,10 +6572,13 @@ emit_input_reload_insns (chain, rl, old, j)
                  rl->when_needed);
     }
 
+  if (flag_non_call_exceptions)
+    copy_eh_notes (insn, get_insns ());
+
   /* End this sequence.  */
   *where = get_insns ();
   end_sequence ();
-
+                                
   /* Update reload_override_in so that delete_address_reloads_1
      can see the actual register usage.  */
   if (oldequiv_reg)
@@ -6787,6 +6793,9 @@ emit_output_reload_insns (chain, rl, j)
   else
     output_reload_insns[rl->opnum] = get_insns ();
 
+  if (flag_non_call_exceptions)
+    copy_eh_notes (insn, get_insns ());
+
   end_sequence ();
 }
 
@@ -8279,9 +8288,13 @@ reload_cse_simplify_set (set, insn)
              && GET_CODE (SET_SRC (set)) != REG))
        {
 #ifdef LOAD_EXTEND_OP
-         rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
-         ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
-         validate_change (insn, &SET_DEST (set), wide_dest, 1);
+         if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
+             && extend_op != NIL)
+           {
+             rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
+             ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
+             validate_change (insn, &SET_DEST (set), wide_dest, 1);
+           }
 #endif
 
          validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1);
@@ -8877,7 +8890,10 @@ reload_combine_note_store (dst, set, data)
 
   if (GET_CODE (dst) == SUBREG)
     {
-      regno = SUBREG_WORD (dst);
+      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
+                                  GET_MODE (SUBREG_REG (dst)),
+                                  SUBREG_BYTE (dst),
+                                  GET_MODE (dst));
       dst = SUBREG_REG (dst);
     }
   if (GET_CODE (dst) != REG)
@@ -9268,7 +9284,10 @@ move2add_note_store (dst, set, data)
 
   if (GET_CODE (dst) == SUBREG)
     {
-      regno = SUBREG_WORD (dst);
+      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
+                                  GET_MODE (SUBREG_REG (dst)),
+                                  SUBREG_BYTE (dst),
+                                  GET_MODE (dst));
       dst = SUBREG_REG (dst);
     }
 
@@ -9425,3 +9444,23 @@ add_auto_inc_notes (insn, x)
     }
 }
 #endif
+
+/* Copy EH notes from an insn to its reloads.  */
+static void
+copy_eh_notes (insn, x)
+     rtx insn;
+     rtx x;
+{
+  rtx eh_note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+  if (eh_note)
+    {
+      for (; x != 0; x = NEXT_INSN (x))
+       {
+         if (may_trap_p (PATTERN (x)))
+           REG_NOTES (x) 
+             = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
+                                  REG_NOTES (x));
+       }
+    }
+}
+