This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Unrepresentable subregs and hard_regno_nregs


At <http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00245.html> I discussed 
how certain subregs for E500 double had the number of registers involved 
incorrectly computed (e.g. (subreg:DI (reg:DF)) (a DFmode register 
interpreted as DImode) takes 1 register, whereas a normal DImode value 
would take 2, and if hard_regno_nregs is used with DImode it's wrongly 
concluded that the subreg takes 2).

The problem arises where hard_regno_nregs is used to determine the 
registers involved in a subreg, *and* the mode involved is the mode of the 
subreg.  If the mode is that of the inner hard reg, there is no problem 
(the result may be a larger range of registers than necessary, but the 
code in such a case presumably expects this), and many hard_regno_nregs 
uses are only for REGs and not SUBREGs and so the problem doesn't arise 
for those either.

In that message I included a partial patch to combine subreg_regno_offset 
and subreg_offset_representable_p into a single function subreg_get_info 
that gathers relevant information about a subreg.  Here is a revised 
version of that patch, for mainline, that adds a further wrapper function 
subreg_nregs to replace the problematic hard_regno_nregs computations for 
subregs.

Comments?  OK to commit?  Should the various places I made call 
subreg_nregs be further revised to call subreg_get_info directly, rather 
than first calling subreg_regno{,_offset} and then subreg_nregs, or should 
that be done in a separate patch?  (The same cleanup to avoid duplicate 
work would also apply to existing places that call 
subreg_offset_representable_p before calling one of the other functions.)

Tested with no regressions with a cross to powerpc-none-linux-gnuspe 
--enable-e500_double, and bootstrapped with no regressions on 
i686-pc-linux-gnu.  There are no changes to the powerpc-none-linux-gnuspe 
results caused by this patch on its own; as noted in my previous message, 
this is however needed by changes to add IBM long double support for E500 
which brings in more of the problem subregs.  I'll send the IBM long 
double support patch separately.

2006-12-19  Joseph Myers  <joseph@codesourcery.com>

	* rtlanal.c (struct subreg_info, subreg_get_info, subreg_nregs):
	New.
	(subreg_regno_offset, subreg_offset_representable_p): Change to
	wrappers about subreg_get_info.
	(refers_to_regno_p, reg_overlap_mentioned_p): Use subreg_nregs.
	* rtl.h (subreg_nregs): Declare.
	* doc/tm.texi (HARD_REGNO_NREGS_HAS_PADDING): Update to refer to
	subreg_get_info.
	* caller-save.c (mark_set_regs, add_stored_regs): Use
	subreg_nregs.
	* df-scan.c (df_ref_record): Use subreg_nregs.
	* flow.c (mark_set_1): Use subreg_nregs.
	* postreload.c (move2add_note_store): Use subreg_nregs.
	* reload.c (decompose, refers_to_regno_for_reload_p,
	reg_overlap_mentioned_for_reload_p): Use subreg_nregs.
	* resource.c (update_live_status, mark_referenced_resources,
	mark_set_resources): Use subreg_nregs.

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 120006)
+++ gcc/doc/tm.texi	(working copy)
@@ -1985,7 +1985,7 @@
 nonzero.
 
 This macros only needs to be defined if there are cases where
-@code{subreg_regno_offset} and @code{subreg_offset_representable_p}
+@code{subreg_get_info}
 would otherwise wrongly determine that a @code{subreg} can be
 represented by an offset to the register number, when in fact such a
 @code{subreg} would contain some of the padding not stored in
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	(revision 120006)
+++ gcc/postreload.c	(working copy)
@@ -1429,6 +1429,7 @@
 move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int regno = 0;
+  unsigned int nregs = 0;
   unsigned int i;
   enum machine_mode mode = GET_MODE (dst);
 
@@ -1438,6 +1439,7 @@
 				   GET_MODE (SUBREG_REG (dst)),
 				   SUBREG_BYTE (dst),
 				   GET_MODE (dst));
+      nregs = subreg_nregs (dst);
       dst = SUBREG_REG (dst);
     }
 
@@ -1455,9 +1457,11 @@
     return;
 
   regno += REGNO (dst);
+  if (!nregs)
+    nregs = hard_regno_nregs[regno][mode];
 
   if (SCALAR_INT_MODE_P (GET_MODE (dst))
-      && hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET
+      && nregs == 1 && GET_CODE (set) == SET
       && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
       && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
     {
@@ -1557,7 +1561,7 @@
     }
   else
     {
-      unsigned int endregno = regno + hard_regno_nregs[regno][mode];
+      unsigned int endregno = regno + nregs;
 
       for (i = regno; i < endregno; i++)
 	/* Reset the information about this register.  */
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	(revision 120006)
+++ gcc/reload.c	(working copy)
@@ -2414,7 +2414,7 @@
 	return decompose (SUBREG_REG (x));
       else
 	/* A hard reg.  */
-	val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+	val.end = val.start + subreg_nregs (x);
       break;
 
     case SCRATCH:
@@ -6381,7 +6381,7 @@
 	  unsigned int inner_regno = subreg_regno (x);
 	  unsigned int inner_endregno
 	    = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
-			     ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
+			     ? subreg_nregs (x) : 1);
 
 	  return endregno > inner_regno && regno < inner_endregno;
 	}
@@ -6479,6 +6479,10 @@
 				      GET_MODE (SUBREG_REG (x)),
 				      SUBREG_BYTE (x),
 				      GET_MODE (x));
+      endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+			  ? subreg_nregs (x) : 1);
+
+      return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
     }
   else if (REG_P (x))
     {
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(revision 120006)
+++ gcc/rtlanal.c	(working copy)
@@ -38,6 +38,18 @@
 #include "regs.h"
 #include "function.h"
 
+/* Information about a subreg of a hard register.  */
+struct subreg_info
+{
+  /* Offset of first hard register involved in the subreg.  */
+  int offset;
+  /* Number of hard registers involved in the subreg.  */
+  int nregs;
+  /* Whether this subreg can be represented as a hard reg with the new
+     mode.  */
+  bool representable_p;
+};
+
 /* Forward declarations */
 static void set_of_1 (rtx, rtx, void *);
 static bool covers_regno_p (rtx, unsigned int);
@@ -45,6 +57,9 @@
 static int rtx_referenced_p_1 (rtx *, void *);
 static int computed_jump_p_1 (rtx);
 static void parms_set (rtx, rtx, void *);
+static void subreg_get_info (unsigned int, enum machine_mode,
+			     unsigned int, enum machine_mode,
+			     struct subreg_info *);
 
 static unsigned HOST_WIDE_INT cached_nonzero_bits (rtx, enum machine_mode,
                                                    rtx, enum machine_mode,
@@ -1170,7 +1185,7 @@
 	  unsigned int inner_regno = subreg_regno (x);
 	  unsigned int inner_endregno
 	    = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
-			     ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
+			     ? subreg_nregs (x) : 1);
 
 	  return endregno > inner_regno && regno < inner_endregno;
 	}
@@ -1260,13 +1275,15 @@
       regno = REGNO (SUBREG_REG (x));
       if (regno < FIRST_PSEUDO_REGISTER)
 	regno = subreg_regno (x);
+      endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+			  ? subreg_nregs (x) : 1);
       goto do_reg;
 
     case REG:
       regno = REGNO (x);
-    do_reg:
       endregno = regno + (regno < FIRST_PSEUDO_REGISTER
 			  ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
+    do_reg:
       return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
 
     case MEM:
@@ -2910,69 +2927,27 @@
 		       SUBREG_BYTE (x));
 }
 
-/* This function returns the regno offset of a subreg expression.
+/* Fill in information about a subreg of a hard register.
    xregno - A regno of an inner hard subreg_reg (or what will become one).
    xmode  - The mode of xregno.
    offset - The byte offset.
    ymode  - The mode of a top level SUBREG (or what may become one).
-   RETURN - The regno offset which would be used.  */
-unsigned int
-subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
-		     unsigned int offset, enum machine_mode ymode)
+   info   - Pointer to structure to fill in.  */
+static void
+subreg_get_info (unsigned int xregno, enum machine_mode xmode,
+		 unsigned int offset, enum machine_mode ymode,
+		 struct subreg_info *info)
 {
   int nregs_xmode, nregs_ymode;
   int mode_multiple, nregs_multiple;
-  int y_offset;
+  int offset_adj, y_offset, y_offset_adj;
+  int regsize_xmode, regsize_ymode;
+  bool rknown;
 
   gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
 
-  /* Adjust nregs_xmode to allow for 'holes'.  */
-  if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
-    nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
-  else
-    nregs_xmode = hard_regno_nregs[xregno][xmode];
-    
-  nregs_ymode = hard_regno_nregs[xregno][ymode];
+  rknown = false;
 
-  /* If this is a big endian paradoxical subreg, which uses more actual
-     hard registers than the original register, we must return a negative
-     offset so that we find the proper highpart of the register.  */
-  if (offset == 0
-      && nregs_ymode > nregs_xmode
-      && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
-	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
-    return nregs_xmode - nregs_ymode;
-
-  if (offset == 0 || nregs_xmode == nregs_ymode)
-    return 0;
-
-  /* Size of ymode must not be greater than the size of xmode.  */
-  mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
-  gcc_assert (mode_multiple != 0);
-
-  y_offset = offset / GET_MODE_SIZE (ymode);
-  nregs_multiple =  nregs_xmode / nregs_ymode;
-  return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
-}
-
-/* This function returns true when the offset is representable via
-   subreg_offset in the given regno.
-   xregno - A regno of an inner hard subreg_reg (or what will become one).
-   xmode  - The mode of xregno.
-   offset - The byte offset.
-   ymode  - The mode of a top level SUBREG (or what may become one).
-   RETURN - Whether the offset is representable.  */
-bool
-subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
-			       unsigned int offset, enum machine_mode ymode)
-{
-  int nregs_xmode, nregs_ymode;
-  int mode_multiple, nregs_multiple;
-  int y_offset;
-  int regsize_xmode, regsize_ymode;
-
-  gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
-
   /* If there are holes in a non-scalar mode in registers, we expect
      that it is made up of its units concatenated together.  */
   if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
@@ -3005,7 +2980,10 @@
 	  && (offset / GET_MODE_SIZE (xmode_unit)
 	      != ((offset + GET_MODE_SIZE (ymode) - 1)
 		  / GET_MODE_SIZE (xmode_unit))))
-	return false;
+	{
+	  info->representable_p = false;
+	  rknown = true;
+	}
     }
   else
     nregs_xmode = hard_regno_nregs[xregno][xmode];
@@ -3013,24 +2991,57 @@
   nregs_ymode = hard_regno_nregs[xregno][ymode];
 
   /* Paradoxical subregs are otherwise valid.  */
-  if (offset == 0
-      && nregs_ymode > nregs_xmode
-      && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
-	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
-    return true;
+  if (!rknown
+      && offset == 0
+      && GET_MODE_SIZE (ymode) > GET_MODE_SIZE (xmode))
+    {
+      info->representable_p = true;
+      /* If this is a big endian paradoxical subreg, which uses more
+	 actual hard registers than the original register, we must
+	 return a negative offset so that we find the proper highpart
+	 of the register.  */
+      if (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)
+	info->offset = nregs_xmode - nregs_ymode;
+      else
+	info->offset = 0;
+      info->nregs = nregs_ymode;
+      return;
+    }
 
   /* If registers store different numbers of bits in the different
      modes, we cannot generally form this subreg.  */
-  regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
-  regsize_ymode = GET_MODE_SIZE (ymode) / nregs_ymode;
-  if (regsize_xmode > regsize_ymode && nregs_ymode > 1)
-    return false;
-  if (regsize_ymode > regsize_xmode && nregs_xmode > 1)
-    return false;
+  if (!HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode)
+      && !HARD_REGNO_NREGS_HAS_PADDING (xregno, ymode))
+    {
+      regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
+      gcc_assert (regsize_xmode * nregs_xmode == GET_MODE_SIZE (xmode));
+      regsize_ymode = GET_MODE_SIZE (ymode) / nregs_ymode;
+      gcc_assert (regsize_ymode * nregs_ymode == GET_MODE_SIZE (ymode));
+      if (!rknown && regsize_xmode > regsize_ymode && nregs_ymode > 1)
+	{
+	  info->representable_p = false;
+	  info->nregs
+	    = (GET_MODE_SIZE (ymode) + regsize_xmode - 1) / regsize_xmode;
+	  info->offset = offset / regsize_xmode;
+	  return;
+	}
+      if (!rknown && regsize_ymode > regsize_xmode && nregs_xmode > 1)
+	{
+	  info->representable_p = false;
+	  info->nregs
+	    = (GET_MODE_SIZE (ymode) + regsize_xmode - 1) / regsize_xmode;
+	  info->offset = offset / regsize_xmode;
+	  return;
+	}
+    }
 
   /* Lowpart subregs are otherwise valid.  */
-  if (offset == subreg_lowpart_offset (ymode, xmode))
-    return true;
+  if (!rknown && offset == subreg_lowpart_offset (ymode, xmode))
+    {
+      info->representable_p = true;
+      rknown = true;
+    }
 
   /* This should always pass, otherwise we don't know how to verify
      the constraint.  These conditions may be relaxed but
@@ -3041,24 +3052,63 @@
   /* The XMODE value can be seen as a vector of NREGS_XMODE
      values.  The subreg must represent a lowpart of given field.
      Compute what field it is.  */
-  offset -= subreg_lowpart_offset (ymode,
-				   mode_for_size (GET_MODE_BITSIZE (xmode)
-						  / nregs_xmode,
-						  MODE_INT, 0));
+  offset_adj = offset;
+  offset_adj -= subreg_lowpart_offset (ymode,
+				       mode_for_size (GET_MODE_BITSIZE (xmode)
+						      / nregs_xmode,
+						      MODE_INT, 0));
 
   /* Size of ymode must not be greater than the size of xmode.  */
   mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
   gcc_assert (mode_multiple != 0);
 
   y_offset = offset / GET_MODE_SIZE (ymode);
-  nregs_multiple =  nregs_xmode / nregs_ymode;
+  y_offset_adj = offset_adj / GET_MODE_SIZE (ymode);
+  nregs_multiple = nregs_xmode / nregs_ymode;
 
-  gcc_assert ((offset % GET_MODE_SIZE (ymode)) == 0);
+  gcc_assert ((offset_adj % GET_MODE_SIZE (ymode)) == 0);
   gcc_assert ((mode_multiple % nregs_multiple) == 0);
 
-  return (!(y_offset % (mode_multiple / nregs_multiple)));
+  if (!rknown)
+    {
+      info->representable_p = (!(y_offset_adj % (mode_multiple / nregs_multiple)));
+      rknown = true;
+    }
+  info->offset = (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
+  info->nregs = nregs_ymode;
 }
 
+/* This function returns the regno offset of a subreg expression.
+   xregno - A regno of an inner hard subreg_reg (or what will become one).
+   xmode  - The mode of xregno.
+   offset - The byte offset.
+   ymode  - The mode of a top level SUBREG (or what may become one).
+   RETURN - The regno offset which would be used.  */
+unsigned int
+subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
+		     unsigned int offset, enum machine_mode ymode)
+{
+  struct subreg_info info;
+  subreg_get_info (xregno, xmode, offset, ymode, &info);
+  return info.offset;
+}
+
+/* This function returns true when the offset is representable via
+   subreg_offset in the given regno.
+   xregno - A regno of an inner hard subreg_reg (or what will become one).
+   xmode  - The mode of xregno.
+   offset - The byte offset.
+   ymode  - The mode of a top level SUBREG (or what may become one).
+   RETURN - Whether the offset is representable.  */
+bool
+subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
+			       unsigned int offset, enum machine_mode ymode)
+{
+  struct subreg_info info;
+  subreg_get_info (xregno, xmode, offset, ymode, &info);
+  return info.representable_p;
+}
+
 /* Return the final regno that a subreg expression refers to.  */
 unsigned int
 subreg_regno (rtx x)
@@ -3074,6 +3124,21 @@
   return ret;
 
 }
+
+/* Return the number of registers that a subreg expression refers
+   to.  */
+unsigned int
+subreg_nregs (rtx x)
+{
+  struct subreg_info info;
+  rtx subreg = SUBREG_REG (x);
+  int regno = REGNO (subreg);
+
+  subreg_get_info (regno, GET_MODE (subreg), SUBREG_BYTE (x), GET_MODE (x),
+		   &info);
+  return info.nregs;
+}
+
 struct parms_set_data
 {
   int nregs;
Index: gcc/flow.c
===================================================================
--- gcc/flow.c	(revision 120006)
+++ gcc/flow.c	(working copy)
@@ -2791,8 +2791,7 @@
 	      regno_first += subreg_regno_offset (regno_first, inner_mode,
 						  SUBREG_BYTE (reg),
 						  outer_mode);
-	      regno_last = (regno_first
-			    + hard_regno_nregs[regno_first][outer_mode] - 1);
+	      regno_last = (regno_first + subreg_nregs (reg) - 1);
 
 	      /* Since we've just adjusted the register number ranges, make
 		 sure REG matches.  Otherwise some_was_live will be clear
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	(revision 120006)
+++ gcc/df-scan.c	(working copy)
@@ -1083,15 +1083,14 @@
       if (!(dflow->flags & DF_HARD_REGS))
 	return;
 
-      /* GET_MODE (reg) is correct here.  We do not want to go into a SUBREG
-         for the mode, because we only want to add references to regs, which
-	 are really referenced.  E.g., a (subreg:SI (reg:DI 0) 0) does _not_
-	 reference the whole reg 0 in DI mode (which would also include
-	 reg 1, at least, if 0 and 1 are SImode registers).  */
-      endregno = hard_regno_nregs[regno][GET_MODE (reg)];
       if (GET_CODE (reg) == SUBREG)
-        regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
-				      SUBREG_BYTE (reg), GET_MODE (reg));
+	{
+	  regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
+					SUBREG_BYTE (reg), GET_MODE (reg));
+	  endregno = subreg_nregs (reg);
+	}
+      else
+	endregno = hard_regno_nregs[regno][GET_MODE (reg)];
       endregno += regno;
 
       /*  If this is a multiword hardreg, we create some extra datastructures that 
Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	(revision 120006)
+++ gcc/caller-save.c	(working copy)
@@ -508,15 +508,17 @@
       if (!REG_P (inner) || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
 	return;
       regno = subreg_regno (reg);
+      endregno = regno + subreg_nregs (reg);
     }
   else if (REG_P (reg)
 	   && REGNO (reg) < FIRST_PSEUDO_REGISTER)
-    regno = REGNO (reg);
+    {
+      regno = REGNO (reg);
+      endregno = regno + hard_regno_nregs[regno][mode];
+    }
   else
     return;
 
-  endregno = regno + hard_regno_nregs[regno][mode];
-
   for (i = regno; i < endregno; i++)
     SET_HARD_REG_BIT (*this_insn_sets, i);
 }
@@ -542,14 +544,18 @@
 				    SUBREG_BYTE (reg),
 				    GET_MODE (reg));
       reg = SUBREG_REG (reg);
+      regno = REGNO (reg) + offset;
+      endregno = regno + subreg_nregs (reg);
     }
+  else
+    {
+      if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+	return;
 
-  if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
-    return;
+      regno = REGNO (reg) + offset;
+      endregno = regno + hard_regno_nregs[regno][mode];
+    }
 
-  regno = REGNO (reg) + offset;
-  endregno = regno + hard_regno_nregs[regno][mode];
-
   for (i = regno; i < endregno; i++)
     SET_REGNO_REG_SET ((regset) data, i);
 }
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 120006)
+++ gcc/rtl.h	(working copy)
@@ -1041,6 +1041,7 @@
 extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
 					   unsigned int, enum machine_mode);
 extern unsigned int subreg_regno (rtx);
+extern unsigned int subreg_nregs (rtx);
 extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
 extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
 extern bool constant_pool_constant_p (rtx);
Index: gcc/resource.c
===================================================================
--- gcc/resource.c	(revision 120006)
+++ gcc/resource.c	(working copy)
@@ -99,12 +99,18 @@
     return;
 
   if (GET_CODE (dest) == SUBREG)
-    first_regno = subreg_regno (dest);
+    {
+      first_regno = subreg_regno (dest);
+      last_regno = first_regno + subreg_nregs (dest);
+
+    }
   else
-    first_regno = REGNO (dest);
+    {
+      first_regno = REGNO (dest);
+      last_regno
+	= first_regno + hard_regno_nregs[first_regno][GET_MODE (dest)];
+    }
 
-  last_regno = first_regno + hard_regno_nregs[first_regno][GET_MODE (dest)];
-
   if (GET_CODE (x) == CLOBBER)
     for (i = first_regno; i < last_regno; i++)
       CLEAR_HARD_REG_BIT (current_live_regs, i);
@@ -229,8 +235,7 @@
       else
 	{
 	  unsigned int regno = subreg_regno (x);
-	  unsigned int last_regno
-	    = regno + hard_regno_nregs[regno][GET_MODE (x)];
+	  unsigned int last_regno = regno + subreg_nregs (x);
 
 	  gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
 	  for (r = regno; r < last_regno; r++)
@@ -763,8 +768,7 @@
 	  else
 	    {
 	      unsigned int regno = subreg_regno (x);
-	      unsigned int last_regno
-		= regno + hard_regno_nregs[regno][GET_MODE (x)];
+	      unsigned int last_regno = regno + subreg_nregs (x);
 
 	      gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
 	      for (r = regno; r < last_regno; r++)

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]