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]

[committed] Fix target/21723--problem handling complex modes on PA


The enclosed change fixes PR target/21723.  The fundamental issue was
that we weren't providing sufficient registers when generating PA 1.0
code to handle SCmode.  PA 1.0 differs from PA 1.1 and later in that
the two halves of floating point register are not separately addressable.

This got me thinking about the alignment of values in both floating
and general registers.  The HP 2.0 architecture specifies that quad
precision floating point values should be aligned to an even floating
point register.  So, I added code to provide for this alignment.  We
also allowed everything under the sun to be placed in the floating
registers but in fact it's not possible to do anything useful with
certain types.  Thus, I defined a macro along the lines used in the
i386 port to limit the valid types.

The change was tested on 4.1 on hppa2.0w-hp-hpux11.11 and hppa64-hp-hpux11.11.
Since 4.1 is rather broken, the change was also tested on 4.0 using
the above and hppa-unknown-linux-gnu.  I also did a complete build
and test using the configure option --with-arch=1.0 to ensure that the
problem reported in the PR was fixed.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2005-07-04  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR target/21723
	* pa.md: Remove fcpy alternative from movhi and movqi patterns.
	* pa32-regs.h (HARD_REGNO_NREGS): Return two floating point registers
	for complex modes when generating code for PA 1.0.
	(VALID_FP_MODE_P): New macro.
	(HARD_REGNO_MODE_OK): Use VALID_FP_MODE_P.  Use non-overlapping register
	sets for all general and floating point modes.  Align wide floating
	point modes to even register boundaries to comply with architectural
	requirements.
	(CLASS_MAX_NREGS): Update to align with change to HARD_REGNO_NREGS.
	* pa64-regs.h (HARD_REGNO_NREGS): Update comment and formatting.
	(VALID_FP_MODE_P): New macro.
	(HARD_REGNO_MODE_OK): Use VALID_FP_MODE_P.  Use non-overlapping register
	sets for all general and floating point modes.  Align wide floating
	point modes to even register boundaries to comply with architectural
	requirements.

Index: config/pa/pa.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.md,v
retrieving revision 1.158.6.1
diff -u -3 -p -r1.158.6.1 pa.md
--- config/pa/pa.md	27 Feb 2005 16:17:08 -0000	1.158.6.1
+++ config/pa/pa.md	3 Jul 2005 18:05:24 -0000
@@ -2896,9 +2896,9 @@
 
 (define_insn ""
   [(set (match_operand:HI 0 "move_dest_operand"
-	 		  "=r,r,r,r,r,Q,!*q,!r,!*f")
+	 		  "=r,r,r,r,r,Q,!*q,!r")
 	(match_operand:HI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
+			  "r,J,N,K,RQ,rM,!rM,!*q"))]
   "register_operand (operands[0], HImode)
    || reg_or_0_operand (operands[1], HImode)"
   "@
@@ -2909,11 +2909,10 @@
    ldh%M1 %1,%0
    sth%M0 %r1,%0
    mtsar %r1
-   {mfctl|mfctl,w} %sar,%0
-   fcpy,sgl %f1,%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,fpalu")
+   {mfctl|mfctl,w} %sar,%0"
+  [(set_attr "type" "move,move,move,shift,load,store,move,move")
    (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
+   (set_attr "length" "4,4,4,4,4,4,4,4")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
@@ -3021,9 +3020,9 @@
 
 (define_insn ""
   [(set (match_operand:QI 0 "move_dest_operand"
-			  "=r,r,r,r,r,Q,!*q,!r,!*f")
+			  "=r,r,r,r,r,Q,!*q,!r")
 	(match_operand:QI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
+			  "r,J,N,K,RQ,rM,!rM,!*q"))]
   "register_operand (operands[0], QImode)
    || reg_or_0_operand (operands[1], QImode)"
   "@
@@ -3034,11 +3033,10 @@
    ldb%M1 %1,%0
    stb%M0 %r1,%0
    mtsar %r1
-   {mfctl|mfctl,w} %%sar,%0
-   fcpy,sgl %f1,%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,fpalu")
+   {mfctl|mfctl,w} %%sar,%0"
+  [(set_attr "type" "move,move,move,shift,load,store,move,move")
    (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
+   (set_attr "length" "4,4,4,4,4,4,4,4")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=r")
Index: config/pa/pa32-regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa32-regs.h,v
retrieving revision 1.14
diff -u -3 -p -r1.14 pa32-regs.h
--- config/pa/pa32-regs.h	13 Jul 2004 22:17:11 -0000	1.14
+++ config/pa/pa32-regs.h	3 Jul 2005 18:05:24 -0000
@@ -156,32 +156,69 @@
    This is ordinarily the length in words of a value of mode MODE
    but can be less for certain modes in special long registers.
 
-   On the HP-PA, ordinary registers hold 32 bits worth;
-   The floating point registers are 64 bits wide. Snake fp regs are 32
-   bits wide */
+   On the HP-PA, general registers are 32 bits wide.  The floating
+   point registers are 64 bits wide.  Snake fp regs are treated as
+   32 bits wide since the left and right parts are independently
+   accessible.  */
 #define HARD_REGNO_NREGS(REGNO, MODE)					\
   (FP_REGNO_P (REGNO)							\
-   ? (!TARGET_PA_11 ? 1 : (GET_MODE_SIZE (MODE) + 4 - 1) / 4)		\
-   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+   ? (!TARGET_PA_11							\
+      ? COMPLEX_MODE_P (MODE) ? 2 : 1					\
+      : (GET_MODE_SIZE (MODE) + 4 - 1) / 4) 	                        \
+   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* There are no instructions that use DImode in PA 1.0, so we only
+   allow it in PA 1.1 and later.  */
+#define VALID_FP_MODE_P(MODE)						\
+  ((MODE) == SFmode || (MODE) == DFmode					\
+   || (MODE) == SCmode || (MODE) == DCmode				\
+   || (MODE) == SImode || (TARGET_PA_11 && (MODE) == DImode))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-   On the HP-PA, the cpu registers can hold any mode.  For DImode, we
-   choose a set of general register that includes the incoming arguments
-   and the return value.  We specify a set with no overlaps so that we don't
-   have to specify that the destination register in patterns using this mode
-   is an early clobber.  */
+
+   On the HP-PA, the cpu registers can hold any mode that fits in 32 bits.
+   For the 64-bit modes, we choose a set of non-overlapping general registers
+   that includes the incoming arguments and the return value.  We specify a
+   set with no overlaps so that we don't have to specify that the destination
+   register is an early clobber in patterns using this mode.  Except for the
+   return value, the starting registers are odd.  For 128 and 256 bit modes,
+   we similarly specify non-overlapping sets of cpu registers.  However,
+   there aren't any patterns defined for modes larger than 64 bits at the
+   moment.
+
+   We limit the modes allowed in the floating point registers to the
+   set of modes used in the machine definition.  In addition, we allow
+   the complex modes SCmode and DCmode.  The real and imaginary parts
+   of complex modes are allocated to separate registers.  This might
+   allow patterns to be defined in the future to operate on these values.
+
+   The PA 2.0 architecture specifies that quad-precision floating-point
+   values should start on an even floating point register.  Thus, we
+   choose non-overlapping sets of registers starting on even register
+   boundaries for large modes.  However, there is currently no support
+   in the machine definition for modes larger than 64 bits.  TFmode is
+   supported under HP-UX using libcalls.  Since TFmode values are passed
+   by reference, they never need to be loaded into the floating-point
+   registers.  */
 #define HARD_REGNO_MODE_OK(REGNO, MODE) \
   ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode		\
-   /* On 1.0 machines, don't allow wide non-fp modes in fp regs.  */	\
    : !TARGET_PA_11 && FP_REGNO_P (REGNO)				\
-     ? GET_MODE_SIZE (MODE) <= 4 || GET_MODE_CLASS (MODE) == MODE_FLOAT	\
+     ? (VALID_FP_MODE_P (MODE)						\
+	&& (GET_MODE_SIZE (MODE) <= 8					\
+	    || (GET_MODE_SIZE (MODE) == 16 && ((REGNO) & 3) == 0)))	\
    : FP_REGNO_P (REGNO)							\
-     ? GET_MODE_SIZE (MODE) <= 4 || ((REGNO) & 1) == 0			\
+     ? (VALID_FP_MODE_P (MODE)						\
+	&& (GET_MODE_SIZE (MODE) <= 4					\
+	    || (GET_MODE_SIZE (MODE) == 8 && ((REGNO) & 1) == 0)	\
+	    || (GET_MODE_SIZE (MODE) == 16 && ((REGNO) & 3) == 0)	\
+	    || (GET_MODE_SIZE (MODE) == 32 && ((REGNO) & 7) == 0)))	\
    : (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD				\
       || (GET_MODE_SIZE (MODE) == 2 * UNITS_PER_WORD			\
 	  && ((((REGNO) & 1) == 1 && (REGNO) <= 25) || (REGNO) == 28))	\
       || (GET_MODE_SIZE (MODE) == 4 * UNITS_PER_WORD			\
-	  && (((REGNO) & 3) == 3 && (REGNO) <= 23))))
+	  && ((REGNO) & 3) == 3 && (REGNO) <= 23)			\
+      || (GET_MODE_SIZE (MODE) == 8 * UNITS_PER_WORD			\
+	  && ((REGNO) & 7) == 3 && (REGNO) <= 19)))
 
 /* How to renumber registers for dbx and gdb.
 
@@ -276,7 +313,9 @@ enum reg_class { NO_REGS, R1_REGS, GENER
    needed to represent mode MODE in a register of class CLASS.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)					\
   ((CLASS) == FP_REGS || (CLASS) == FPUPPER_REGS			\
-   ? (!TARGET_PA_11 ? 1 : (GET_MODE_SIZE (MODE) + 4 - 1) / 4)		\
+   ? (!TARGET_PA_11							\
+      ? COMPLEX_MODE_P (MODE) ? 2 : 1					\
+      : (GET_MODE_SIZE (MODE) + 4 - 1) / 4)				\
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
 /* 1 if N is a possible register number for function argument passing.  */
Index: config/pa/pa64-regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa64-regs.h,v
retrieving revision 1.18
diff -u -3 -p -r1.18 pa64-regs.h
--- config/pa/pa64-regs.h	18 Sep 2004 19:19:39 -0000	1.18
+++ config/pa/pa64-regs.h	3 Jul 2005 18:05:24 -0000
@@ -145,11 +145,19 @@ Boston, MA 02111-1307, USA.  */
    This is ordinarily the length in words of a value of mode MODE
    but can be less for certain modes in special long registers.
 
-   For PA64, GPRs and FPRs hold 64 bits worth (we ignore the 32bit
-   addressability of the FPRs).  i.e., we pretend each register holds
-   precisely WORD_SIZE bits.  */
+   For PA64, GPRs and FPRs hold 64 bits worth.  We ignore the 32-bit
+   addressability of the FPRs and pretend each register holds precisely
+   WORD_SIZE bits.  Note that SCmode values are placed in a single FPR.
+   Thus, any patterns defined to operate on these values would have to
+   use the 32-bit addressability of the FPR registers.  */
 #define HARD_REGNO_NREGS(REGNO, MODE)					\
-   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* These are the valid FP modes.  */
+#define VALID_FP_MODE_P(MODE)                                           \
+  ((MODE) == SFmode || (MODE) == DFmode                                 \
+   || (MODE) == SCmode || (MODE) == DCmode                              \
+   || (MODE) == SImode || (MODE) == DImode)
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    On the HP-PA, the cpu registers can hold any mode.  We
@@ -158,8 +166,16 @@ Boston, MA 02111-1307, USA.  */
   ((REGNO) == 0								\
    ? (MODE) == CCmode || (MODE) == CCFPmode				\
    /* Make wide modes be in aligned registers.  */			\
+   : FP_REGNO_P (REGNO)							\
+     ? (VALID_FP_MODE_P (MODE)						\
+	&& (GET_MODE_SIZE (MODE) <= 8					\
+	    || (GET_MODE_SIZE (MODE) == 16 && ((REGNO) & 1) == 0)	\
+	    || (GET_MODE_SIZE (MODE) == 32 && ((REGNO) & 3) == 0)))	\
    : (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD				\
-      || (GET_MODE_SIZE (MODE) <= 2 * UNITS_PER_WORD && ((REGNO) & 1) == 0)))
+      || (GET_MODE_SIZE (MODE) == 2 * UNITS_PER_WORD			\
+	  && ((((REGNO) & 1) == 1 && (REGNO) <= 25) || (REGNO) == 28))	\
+      || (GET_MODE_SIZE (MODE) == 4 * UNITS_PER_WORD			\
+	  && ((REGNO) & 3) == 3 && (REGNO) <= 23)))
 
 /* How to renumber registers for dbx and gdb.
 


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