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 3.4/3.5] Fix PR rtl-optimization/14782


The enclosed patch fixes the unaligned DImode load noted in the PR.
On PA 2.0, the ldd/std instructions require both the base and the
displacement to be aligned.  Although the base and displacement in
REG+D modes start off correctly aligned, the PR showed a case where
loop optimization could create an unaligned base.  The fix is to
require that the displacement be correctly aligned in
GO_IF_LEGITIMATE_ADDRESS.

In working on this problem, I realized that the same problem could
occur for floating-point loads and stores with long displacements.
They also require alignment of the base register.  There was also
a minor problem with the T constraint for SImode/SFmode loads and
stores to a floating-point registers.  We were incorrectly requiring
DFmode alignment which would cause address reloading more often than
necessary.  We also didn't handle unaligned bases in SImode loads and
stores to floating registers.  I have changed this and fixed the
reload issues.

The patch has been tested on hppa64-hp-hpux11.11 and hppa-unknown-linux-gnu
(3.5), hppa64-hp-hpux11.00 (3.4) and hppa-unknown-linux-gnu (3.3).

Installed to 3.4 and 3.5.  Gaby is the ok for 3.3 when the branch
reopens?

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

2004-06-21  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR rtl-optimization/14782
	* pa.c (emit_move_sequence): Use SFmode for 4-byte modes when doing
	the address checks for secondary reloads for loads from and stores
	to floating-point registers.
	* pa.h (EXTRA_CONSTRAINT, case T): Use SFmode for 4-byte modes
	in the address check.  Move work around for ELF32 targets to
	GO_IF_LEGITIMATE_ADDRESS.
	(GO_IF_LEGITIMATE_ADDRESS): Require constant offsets to be
	correctly aligned for DImode loads and stores.  Don't allow long
	SFmode displacements on ELF32.

Index: config/pa/pa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.251
diff -u -3 -p -r1.251 pa.c
--- config/pa/pa.c	11 Jun 2004 23:09:57 -0000	1.251
+++ config/pa/pa.c	21 Jun 2004 04:58:48 -0000
@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum 
     operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
 
   /* Handle secondary reloads for loads/stores of FP registers from
-     REG+D addresses where D does not fit in 5 bits, including
+     REG+D addresses where D does not fit in 5 or 14 bits, including
      (subreg (mem (addr))) cases.  */
   if (scratch_reg
       && fp_reg_operand (operand0, mode)
       && ((GET_CODE (operand1) == MEM
-	   && !memory_address_p (DFmode, XEXP (operand1, 0)))
+	   && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
+				 XEXP (operand1, 0)))
 	  || ((GET_CODE (operand1) == SUBREG
 	       && GET_CODE (XEXP (operand1, 0)) == MEM
-	       && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))))
+	       && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+				      ? SFmode : DFmode),
+				     XEXP (XEXP (operand1, 0), 0))))))
     {
       if (GET_CODE (operand1) == SUBREG)
 	operand1 = XEXP (operand1, 0);
@@ -1600,10 +1603,13 @@ emit_move_sequence (rtx *operands, enum 
   else if (scratch_reg
 	   && fp_reg_operand (operand1, mode)
 	   && ((GET_CODE (operand0) == MEM
-		&& ! memory_address_p (DFmode, XEXP (operand0, 0)))
+		&& !memory_address_p ((GET_MODE_SIZE (mode) == 4
+					? SFmode : DFmode),
+				       XEXP (operand0, 0)))
 	       || ((GET_CODE (operand0) == SUBREG)
 		   && GET_CODE (XEXP (operand0, 0)) == MEM
-		   && !memory_address_p (DFmode,
+		   && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+					  ? SFmode : DFmode),
 			   		 XEXP (XEXP (operand0, 0), 0)))))
     {
       if (GET_CODE (operand0) == SUBREG)
Index: config/pa/pa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.218
diff -u -3 -p -r1.218 pa.h
--- config/pa/pa.h	13 May 2004 06:40:03 -0000	1.218
+++ config/pa/pa.h	21 Jun 2004 04:58:59 -0000
@@ -1284,7 +1284,7 @@ extern int may_call_alloca;
 
    `S' is the constant 31.
 
-   `T' is for fp loads and stores.
+   `T' is for floating-point loads and stores.
 
    `U' is the constant 63.  */
 
@@ -1307,17 +1307,20 @@ extern int may_call_alloca;
       (GET_CODE (OP) == MEM						\
        && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))				\
        && !IS_INDEX_ADDR_P (XEXP (OP, 0))				\
-       /* Using DFmode forces only short displacements			\
-	  to be recognized as valid in reg+d addresses. 		\
-	  However, this is not necessary for PA2.0 since		\
-	  it has long FP loads/stores.					\
+       /* Floating-point loads and stores are used to load		\
+	  integer values as well as floating-point values.		\
+	  They don't have the same set of REG+D address modes		\
+	  as integer loads and stores.  PA 1.x supports only		\
+	  short displacements.  PA 2.0 supports long displacements	\
+	  but the base register needs to be aligned.			\
 									\
-	  FIXME: the ELF32 linker clobbers the LSB of			\
-	  the FP register number in {fldw,fstw} insns.			\
-	  Thus, we only allow long FP loads/stores on			\
-	  TARGET_64BIT.  */						\
-       && memory_address_p ((TARGET_PA_20 && !TARGET_ELF32		\
-			     ? GET_MODE (OP)				\
+	  The checks in GO_IF_LEGITIMATE_ADDRESS for SFmode and		\
+	  DFmode test the validity of an address for use in a		\
+	  floating point load or store.  So, we use SFmode/DFmode	\
+	  to see if the address is valid for a floating-point		\
+	  load/store operation.  */					\
+       && memory_address_p ((GET_MODE_SIZE (GET_MODE (OP)) == 4		\
+			     ? SFmode					\
 			     : DFmode),					\
 			    XEXP (OP, 0)))				\
    : ((C) == 'S' ?							\
@@ -1467,13 +1470,32 @@ extern int may_call_alloca;
       if (base								\
 	  && GET_CODE (index) == CONST_INT				\
 	  && ((INT_14_BITS (index)					\
-	       && (TARGET_SOFT_FLOAT					\
-		   || (TARGET_PA_20					\
-		       && ((MODE == SFmode				\
-			    && (INTVAL (index) % 4) == 0)		\
-			   || (MODE == DFmode				\
-			       && (INTVAL (index) % 8) == 0)))		\
-		   || ((MODE) != SFmode && (MODE) != DFmode)))		\
+	       && (((MODE) != DImode					\
+		    && (MODE) != SFmode					\
+		    && (MODE) != DFmode)				\
+		   /* The base register for DImode loads and stores	\
+		      with long displacements must be aligned because	\
+		      the lower three bits in the displacement are	\
+		      assumed to be zero.  */				\
+		   || ((MODE) == DImode					\
+		       && (!TARGET_64BIT				\
+			   || (INTVAL (index) % 8) == 0))		\
+		   /* Similarly, the base register for SFmode/DFmode	\
+		      loads and stores with long displacements must	\
+		      be aligned.					\
+									\
+		      FIXME: the ELF32 linker clobbers the LSB of	\
+		      the FP register number in PA 2.0 floating-point	\
+		      insns with long displacements.  This is because	\
+		      R_PARISC_DPREL14WR and other relocations like	\
+		      it are not supported.  For now, we reject long	\
+		      displacements on this target.  */			\
+		   || (((MODE) == SFmode || (MODE) == DFmode)		\
+		       && (TARGET_SOFT_FLOAT				\
+			   || (TARGET_PA_20				\
+			       && !TARGET_ELF32				\
+			       && (INTVAL (index)			\
+				   % GET_MODE_SIZE (MODE)) == 0)))))	\
 	       || INT_5_BITS (index)))					\
 	goto ADDR;							\
       if (!TARGET_DISABLE_INDEXING					\
@@ -1589,6 +1611,11 @@ do { 									\
       else								\
 	newoffset = offset & ~mask;					\
 									\
+      /* Ensure that long displacements are aligned.  */		\
+      if (!VAL_5_BITS_P (newoffset)					\
+	  && GET_MODE_CLASS (MODE) == MODE_FLOAT)			\
+	newoffset &= ~(GET_MODE_SIZE (MODE) -1);			\
+									\
       if (newoffset != 0 && VAL_14_BITS_P (newoffset))			\
 	{								\
 	  temp = gen_rtx_PLUS (Pmode, XEXP (new, 0),			\


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