sgallagh / rpms / gcc

Forked from rpms/gcc 3 years ago
Clone
ec5ba4b
2006-12-21  Jakub Jelinek  <jakub@redhat.com>
ec5ba4b
ec5ba4b
	Revert:
ec5ba4b
	2006-12-16  Joseph Myers  <joseph@codesourcery.com>
ec5ba4b
		    David Edelsohn  <edelsohn@gnu.org>
ec5ba4b
	PR target/24036
ec5ba4b
	* doc/tm.texi (HARD_REGNO_NREGS_HAS_PADDING,
ec5ba4b
	HARD_REGNO_NREGS_WITH_PADDING): Document new target macros.
ec5ba4b
	* defaults.h (HARD_REGNO_NREGS_HAS_PADDING,
ec5ba4b
	HARD_REGNO_NREGS_WITH_PADDING): Define.
ec5ba4b
	* config/i386/i386.h (HARD_REGNO_NREGS_HAS_PADDING,
ec5ba4b
	HARD_REGNO_NREGS_WITH_PADDING): Define.
ec5ba4b
	* rtlanal.c (subreg_regno_offset, subreg_offset_representable_p):
ec5ba4b
	Use new macros to detect modes with holes; do not look at integer
ec5ba4b
	units.
ec5ba4b
	(subreg_offset_representable_p): Check for and disallow cases
ec5ba4b
	where the modes use different numbers of bits from registers.
ec5ba4b
	* config/rs6000/rs6000.c (rs6000_emit_move): Handle TFmode
ec5ba4b
	constant for soft-float.
ec5ba4b
	(rs6000_hard_regno_nregs): Use UNITS_PER_FP_WORD for e500 GPRs
ec5ba4b
	containing doubles.
ec5ba4b
	(rs6000_split_multireg_move): Use DFmode reg_mode for TFmode moves
ec5ba4b
	in E500 double case.
ec5ba4b
	* config/rs6000/rs6000.md (movtf): Allow soft-float.
ec5ba4b
	(movtf_softfloat): New.
ec5ba4b
ec5ba4b
--- gcc/doc/tm.texi	(revision 119967)
ec5ba4b
+++ gcc/doc/tm.texi	(revision 119966)
ec5ba4b
@@ -1937,33 +1937,6 @@ definition of this macro is
ec5ba4b
 @end smallexample
ec5ba4b
 @end defmac
ec5ba4b
 
ec5ba4b
-@defmac HARD_REGNO_NREGS_HAS_PADDING (@var{regno}, @var{mode})
ec5ba4b
-A C expression that is nonzero if a value of mode @var{mode}, stored
ec5ba4b
-in memory, ends with padding that causes it to take up more space than
ec5ba4b
-in registers starting at register number @var{regno} (as determined by
ec5ba4b
-multiplying GCC's notion of the size of the register when containing
ec5ba4b
-this mode by the number of registers returned by
ec5ba4b
-@code{HARD_REGNO_NREGS}).  By default this is zero.
ec5ba4b
-
ec5ba4b
-For example, if a floating-point value is stored in three 32-bit
ec5ba4b
-registers but takes up 128 bits in memory, then this would be
ec5ba4b
-nonzero.
ec5ba4b
-
ec5ba4b
-This macros only needs to be defined if there are cases where
ec5ba4b
-@code{subreg_regno_offset} and @code{subreg_offset_representable_p}
ec5ba4b
-would otherwise wrongly determine that a @code{subreg} can be
ec5ba4b
-represented by an offset to the register number, when in fact such a
ec5ba4b
-@code{subreg} would contain some of the padding not stored in
ec5ba4b
-registers and so not be representable.
ec5ba4b
-@end defmac
ec5ba4b
-
ec5ba4b
-@defmac HARD_REGNO_NREGS_WITH_PADDING (@var{regno}, @var{mode})
ec5ba4b
-For values of @var{regno} and @var{mode} for which
ec5ba4b
-@code{HARD_REGNO_NREGS_HAS_PADDING} returns nonzero, a C expression
ec5ba4b
-returning the greater number of registers required to hold the value
ec5ba4b
-including any padding.  In the example above, the value would be four.
ec5ba4b
-@end defmac
ec5ba4b
-
ec5ba4b
 @defmac REGMODE_NATURAL_SIZE (@var{mode})
ec5ba4b
 Define this macro if the natural size of registers that hold values
ec5ba4b
 of mode @var{mode} is not the word size.  It is a C expression that
ec5ba4b
--- gcc/defaults.h	(revision 119967)
ec5ba4b
+++ gcc/defaults.h	(revision 119966)
ec5ba4b
@@ -867,9 +867,4 @@ Software Foundation, 51 Franklin Street,
ec5ba4b
 #define INCOMING_FRAME_SP_OFFSET 0
ec5ba4b
 #endif
ec5ba4b
 
ec5ba4b
-#ifndef HARD_REGNO_NREGS_HAS_PADDING
ec5ba4b
-#define HARD_REGNO_NREGS_HAS_PADDING(REGNO, MODE) 0
ec5ba4b
-#define HARD_REGNO_NREGS_WITH_PADDING(REGNO, MODE) -1
ec5ba4b
-#endif
ec5ba4b
-
ec5ba4b
 #endif  /* ! GCC_DEFAULTS_H */
ec5ba4b
--- gcc/rtlanal.c	(revision 119967)
ec5ba4b
+++ gcc/rtlanal.c	(revision 119966)
ec5ba4b
@@ -3138,15 +3138,34 @@ unsigned int
ec5ba4b
 subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
ec5ba4b
 		     unsigned int offset, enum machine_mode ymode)
ec5ba4b
 {
ec5ba4b
-  int nregs_xmode, nregs_ymode;
ec5ba4b
+  int nregs_xmode, nregs_ymode, nregs_xmode_unit_int;
ec5ba4b
   int mode_multiple, nregs_multiple;
ec5ba4b
   int y_offset;
ec5ba4b
+  enum machine_mode xmode_unit, xmode_unit_int;
ec5ba4b
 
ec5ba4b
   gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
ec5ba4b
 
ec5ba4b
+  if (GET_MODE_INNER (xmode) == VOIDmode)
ec5ba4b
+    xmode_unit = xmode;
ec5ba4b
+  else
ec5ba4b
+    xmode_unit = GET_MODE_INNER (xmode);
ec5ba4b
+  
ec5ba4b
+  if (FLOAT_MODE_P (xmode_unit))
ec5ba4b
+    {
ec5ba4b
+      xmode_unit_int = int_mode_for_mode (xmode_unit);
ec5ba4b
+      if (xmode_unit_int == BLKmode)
ec5ba4b
+	/* It's probably bad to be here; a port should have an integer mode
ec5ba4b
+	   that's the same size as anything of which it takes a SUBREG.  */
ec5ba4b
+	xmode_unit_int = xmode_unit;
ec5ba4b
+    }
ec5ba4b
+  else
ec5ba4b
+    xmode_unit_int = xmode_unit;
ec5ba4b
+
ec5ba4b
+  nregs_xmode_unit_int = hard_regno_nregs[xregno][xmode_unit_int];
ec5ba4b
+
ec5ba4b
   /* Adjust nregs_xmode to allow for 'holes'.  */
ec5ba4b
-  if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
ec5ba4b
-    nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
ec5ba4b
+  if (nregs_xmode_unit_int != hard_regno_nregs[xregno][xmode_unit])
ec5ba4b
+    nregs_xmode = nregs_xmode_unit_int * GET_MODE_NUNITS (xmode);
ec5ba4b
   else
ec5ba4b
     nregs_xmode = hard_regno_nregs[xregno][xmode];
ec5ba4b
     
ec5ba4b
@@ -3184,31 +3203,38 @@ bool
ec5ba4b
 subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
ec5ba4b
 			       unsigned int offset, enum machine_mode ymode)
ec5ba4b
 {
ec5ba4b
-  int nregs_xmode, nregs_ymode;
ec5ba4b
+  int nregs_xmode, nregs_ymode, nregs_xmode_unit, nregs_xmode_unit_int;
ec5ba4b
   int mode_multiple, nregs_multiple;
ec5ba4b
   int y_offset;
ec5ba4b
-  int regsize_xmode, regsize_ymode;
ec5ba4b
+  enum machine_mode xmode_unit, xmode_unit_int;
ec5ba4b
 
ec5ba4b
   gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
ec5ba4b
 
ec5ba4b
+  if (GET_MODE_INNER (xmode) == VOIDmode)
ec5ba4b
+    xmode_unit = xmode;
ec5ba4b
+  else
ec5ba4b
+    xmode_unit = GET_MODE_INNER (xmode);
ec5ba4b
+  
ec5ba4b
+  if (FLOAT_MODE_P (xmode_unit))
ec5ba4b
+    {
ec5ba4b
+      xmode_unit_int = int_mode_for_mode (xmode_unit);
ec5ba4b
+      if (xmode_unit_int == BLKmode)
ec5ba4b
+	/* It's probably bad to be here; a port should have an integer mode
ec5ba4b
+	   that's the same size as anything of which it takes a SUBREG.  */
ec5ba4b
+	xmode_unit_int = xmode_unit;
ec5ba4b
+    }
ec5ba4b
+  else
ec5ba4b
+    xmode_unit_int = xmode_unit;
ec5ba4b
+
ec5ba4b
+  nregs_xmode_unit = hard_regno_nregs[xregno][xmode_unit];
ec5ba4b
+  nregs_xmode_unit_int = hard_regno_nregs[xregno][xmode_unit_int];
ec5ba4b
+
ec5ba4b
   /* If there are holes in a non-scalar mode in registers, we expect
ec5ba4b
      that it is made up of its units concatenated together.  */
ec5ba4b
-  if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
ec5ba4b
+  if (nregs_xmode_unit != nregs_xmode_unit_int)
ec5ba4b
     {
ec5ba4b
-      enum machine_mode xmode_unit;
ec5ba4b
-
ec5ba4b
-      nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
ec5ba4b
-      if (GET_MODE_INNER (xmode) == VOIDmode)
ec5ba4b
-	xmode_unit = xmode;
ec5ba4b
-      else
ec5ba4b
-	xmode_unit = GET_MODE_INNER (xmode);
ec5ba4b
-      gcc_assert (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode_unit));
ec5ba4b
-      gcc_assert (nregs_xmode
ec5ba4b
-		  == (GET_MODE_NUNITS (xmode)
ec5ba4b
-		      * HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode_unit)));
ec5ba4b
-      gcc_assert (hard_regno_nregs[xregno][xmode]
ec5ba4b
-		  == (hard_regno_nregs[xregno][xmode_unit]
ec5ba4b
-		      * GET_MODE_NUNITS (xmode)));
ec5ba4b
+      gcc_assert (nregs_xmode_unit * GET_MODE_NUNITS (xmode)
ec5ba4b
+		  == hard_regno_nregs[xregno][xmode]);
ec5ba4b
 
ec5ba4b
       /* You can only ask for a SUBREG of a value with holes in the middle
ec5ba4b
 	 if you don't cross the holes.  (Such a SUBREG should be done by
ec5ba4b
@@ -3218,12 +3244,15 @@ subreg_offset_representable_p (unsigned 
ec5ba4b
 	 3 for each part, but in memory it's two 128-bit parts.  
ec5ba4b
 	 Padding is assumed to be at the end (not necessarily the 'high part')
ec5ba4b
 	 of each unit.  */
ec5ba4b
-      if ((offset / GET_MODE_SIZE (xmode_unit) + 1 
ec5ba4b
-	   < GET_MODE_NUNITS (xmode))
ec5ba4b
-	  && (offset / GET_MODE_SIZE (xmode_unit)
ec5ba4b
+      if (nregs_xmode_unit != nregs_xmode_unit_int
ec5ba4b
+	  && (offset / GET_MODE_SIZE (xmode_unit_int) + 1 
ec5ba4b
+	      < GET_MODE_NUNITS (xmode))
ec5ba4b
+	  && (offset / GET_MODE_SIZE (xmode_unit_int) 
ec5ba4b
 	      != ((offset + GET_MODE_SIZE (ymode) - 1)
ec5ba4b
-		  / GET_MODE_SIZE (xmode_unit))))
ec5ba4b
+		  / GET_MODE_SIZE (xmode_unit_int))))
ec5ba4b
 	return false;
ec5ba4b
+
ec5ba4b
+      nregs_xmode = nregs_xmode_unit_int * GET_MODE_NUNITS (xmode);
ec5ba4b
     }
ec5ba4b
   else
ec5ba4b
     nregs_xmode = hard_regno_nregs[xregno][xmode];
ec5ba4b
@@ -3237,15 +3266,6 @@ subreg_offset_representable_p (unsigned 
ec5ba4b
 	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
ec5ba4b
     return true;
ec5ba4b
 
ec5ba4b
-  /* If registers store different numbers of bits in the different
ec5ba4b
-     modes, we cannot generally form this subreg.  */
ec5ba4b
-  regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
ec5ba4b
-  regsize_ymode = GET_MODE_SIZE (ymode) / nregs_ymode;
ec5ba4b
-  if (regsize_xmode > regsize_ymode && nregs_ymode > 1)
ec5ba4b
-    return false;
ec5ba4b
-  if (regsize_ymode > regsize_xmode && nregs_xmode > 1)
ec5ba4b
-    return false;
ec5ba4b
-
ec5ba4b
   /* Lowpart subregs are otherwise valid.  */
ec5ba4b
   if (offset == subreg_lowpart_offset (ymode, xmode))
ec5ba4b
     return true;
ec5ba4b
--- gcc/config/i386/i386.h	(revision 119967)
ec5ba4b
+++ gcc/config/i386/i386.h	(revision 119966)
ec5ba4b
@@ -827,15 +827,6 @@ do {									\
ec5ba4b
       ? (TARGET_64BIT ? 4 : 6)						\
ec5ba4b
       : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
ec5ba4b
 
ec5ba4b
-#define HARD_REGNO_NREGS_HAS_PADDING(REGNO, MODE)			\
ec5ba4b
-  ((TARGET_128BIT_LONG_DOUBLE && !TARGET_64BIT)				\
ec5ba4b
-   ? (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO)	\
ec5ba4b
-      ? 0								\
ec5ba4b
-      : ((MODE) == XFmode || (MODE) == XCmode))				\
ec5ba4b
-   : 0)
ec5ba4b
-
ec5ba4b
-#define HARD_REGNO_NREGS_WITH_PADDING(REGNO, MODE) ((MODE) == XFmode ? 4 : 8)
ec5ba4b
-
ec5ba4b
 #define VALID_SSE2_REG_MODE(MODE) \
ec5ba4b
     ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode    \
ec5ba4b
      || (MODE) == V2DImode || (MODE) == DFmode)
ec5ba4b
--- gcc/config/rs6000/rs6000.c	(revision 119967)
ec5ba4b
+++ gcc/config/rs6000/rs6000.c	(revision 119966)
ec5ba4b
@@ -3573,6 +3573,9 @@ rs6000_hard_regno_nregs (int regno, enum
ec5ba4b
   if (FP_REGNO_P (regno))
ec5ba4b
     return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
ec5ba4b
 
ec5ba4b
+  if (TARGET_E500_DOUBLE && mode == DFmode)
ec5ba4b
+    return 1;
ec5ba4b
+
ec5ba4b
   if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
ec5ba4b
     return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
ec5ba4b
 
ec5ba4b
@@ -3580,14 +3583,6 @@ rs6000_hard_regno_nregs (int regno, enum
ec5ba4b
     return
ec5ba4b
       (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
ec5ba4b
 
ec5ba4b
-  /* The value returned for SCmode in the E500 double case is 2 for
ec5ba4b
-     ABI compatibility; storing an SCmode value in a single register
ec5ba4b
-     would require function_arg and rs6000_spe_function_arg to handle
ec5ba4b
-     SCmode so as to pass the value correctly in a pair of
ec5ba4b
-     registers.  */
ec5ba4b
-  if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode)
ec5ba4b
-    return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
ec5ba4b
-
ec5ba4b
   return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
ec5ba4b
 }
ec5ba4b
 
ec5ba4b
@@ -3956,7 +3951,8 @@ rs6000_emit_move (rtx dest, rtx source, 
ec5ba4b
 
ec5ba4b
   /* 128-bit constant floating-point values on Darwin should really be
ec5ba4b
      loaded as two parts.  */
ec5ba4b
-  if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
ec5ba4b
+  if (!TARGET_IEEEQUAD
ec5ba4b
+      && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
ec5ba4b
       && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
ec5ba4b
     {
ec5ba4b
       /* DImode is used, not DFmode, because simplify_gen_subreg doesn't
ec5ba4b
@@ -12402,8 +12398,6 @@ rs6000_split_multireg_move (rtx dst, rtx
ec5ba4b
     reg_mode = DFmode;
ec5ba4b
   else if (ALTIVEC_REGNO_P (reg))
ec5ba4b
     reg_mode = V16QImode;
ec5ba4b
-  else if (TARGET_E500_DOUBLE && mode == TFmode)
ec5ba4b
-    reg_mode = DFmode;
ec5ba4b
   else
ec5ba4b
     reg_mode = word_mode;
ec5ba4b
   reg_mode_size = GET_MODE_SIZE (reg_mode);
ec5ba4b
--- gcc/config/rs6000/rs6000.md	(revision 119967)
ec5ba4b
+++ gcc/config/rs6000/rs6000.md	(revision 119966)
ec5ba4b
@@ -7789,7 +7789,8 @@ (define_insn "*movdf_softfloat64"
ec5ba4b
 (define_expand "movtf"
ec5ba4b
   [(set (match_operand:TF 0 "general_operand" "")
ec5ba4b
 	(match_operand:TF 1 "any_operand" ""))]
ec5ba4b
-  "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
ec5ba4b
+  "!TARGET_IEEEQUAD
ec5ba4b
+   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
ec5ba4b
   "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
ec5ba4b
 
ec5ba4b
 ; It's important to list the o->f and f->o moves before f->f because
ec5ba4b
@@ -7808,19 +7809,6 @@ (define_insn_and_split "*movtf_internal"
ec5ba4b
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
ec5ba4b
   [(set_attr "length" "8,8,8,20,20,16")])
ec5ba4b
 
ec5ba4b
-(define_insn_and_split "*movtf_softfloat"
ec5ba4b
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,Y,r")
ec5ba4b
-	(match_operand:TF 1 "input_operand"         "YGHF,r,r"))]
ec5ba4b
-  "!TARGET_IEEEQUAD
ec5ba4b
-   && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128
ec5ba4b
-   && (gpc_reg_operand (operands[0], TFmode)
ec5ba4b
-       || gpc_reg_operand (operands[1], TFmode))"
ec5ba4b
-  "#"
ec5ba4b
-  "&& reload_completed"
ec5ba4b
-  [(pc)]
ec5ba4b
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
ec5ba4b
-  [(set_attr "length" "20,20,16")])
ec5ba4b
-
ec5ba4b
 (define_expand "extenddftf2"
ec5ba4b
   [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
ec5ba4b
 		   (float_extend:TF (match_operand:DF 1 "input_operand" "")))