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] [PR target/34091] Secondary reloads for floating-point register classes


The attached patch fixes a regression introduced in 4.2 regarding the
behavior of secondary reloads.

As background, the basic problem is that the range of displacements
allowed for REG+D addresses differs for integer and floating-point
loads and stores in the PA-RISC 1.x architecture.  Integer instructions
can handle 14-bit signed offsets.  Floating-point instructions can
only handle 5-bit signed offsets.

The technique to handle this asymmetry has always been to accept
14-bit offsets in GO_IF_LEGITIMATE_ADDRESS for integer modes and 5-bit
offsets for floating-point modes.  A secondary reload was used to
rewrite floating-point loads and stores so that register elimination
wouldn't result in an invalid REG+D offset.

In the testcase submitted with PR 34091, we have the following
failure:

swrast/s_texfilter.c:1420: error: insn does not satisfy its constraints:
(insn 2621 1258 1259 96 (set (mem/c:HI (plus:SI (reg/f:SI 30 %r30)
                (const_int -474 [0xfffffe26])) [0 S2 A16])
	(reg:HI 68 %fr22)) 53 {*pa.md:3126} (nil)
    (nil))

This exposed these issues:

1) The PA backend has no patterns that operate on HImode values in
   floating-point registers.  It is expense to copy between the general
   and floating-point registers (it must be done via memory), so we
   never want to use the floating point registers for temporary registers
   for HImode and QImode values.  The fact that floating-point registers
   are being used suggests a problem with costs.

2) We don't have reload_inhi and reload_outhi patterns, so the secondary
   reload technique described above is broken for HImode and QImode values
   in the floating-point registers.

So, I decided to modify the backend to prevent the loading of HImode
and QImode values into the floating registers.  I removed pattern
duplication from pa.md.  Updated the defines VALID_FP_MODE_P, and
turned MODES_TIEABLE_P and CANNOT_CHANGE_MODE_CLASS into functions.
pa_cannot_change_mode_class() now prohibits mode changes in the
floating-point registers.  pa_modes_tieable_p() is functionally
unchanged.  I left it because I wanted to more easily experiment
with its definition.

After doing this, the testcase for PR 34091 still failed.  I found
that secondary reloads for REG+D addresses weren't always generated,
possibly because GO_IF_LEGITIMATE_ADDRESS accepts reloading pseudos
and 5-bit immediates.  An offset relative to the frame pointer might
be valid but invalid as a stack pointer offset.

I looked at the alternative of changing GO_IF_LEGITIMATE_ADDRESS
to only allow 5-bit offsets.  However, this significantly increases
register pressure (I had some spill failures in testing), requires
more register saves and restores, and increases code size.  I didn't
come up with a way to generate 14-bit code using reload, so to get
the code size back, a bunch of peephole2 patterns would be needed.

Eric Botcazou indicated that sparc uses an intermediate general
register instead of a scratch-register reload.  So, that's what we
have now for copies of integer mode MEMs to/from the floating-point
registers.  I'm not particularly happy about this.

The code generated using this technique is less efficient than that
previously generated using a secondary scratch-register reload.  For that,
the pseudo would be forced to memory and its address loaded into the
scratch register.  Using a general intermediate requires copying the
value through memory.

When generating PA 2.0 code (hppa), we have 14-bit displacements
for floating-point loads and stores.  Thus, it might seem that
an intermediate general register wouldn't be needed.  However, it
seems to do this requires handling paradoxical subregs in the
floating-point registers.

Further, it turns out that we still need the old secondary reload
technique for SYMBOL_REFs and possibly some other RTL forms.

I had a lot of trouble with this change because the documentation
as to the behavior of TARGET_SECONDARY_RELOAD is quite vague with
respect to when it's used and the rtx's to expect in the argument
X.

There are some secondary changes in this patch.  There are minor
corrections to MODE_OK_FOR_SCALED_INDEXING_P, MODE_OK_FOR_UNSCALED_INDEXING_P
and LEGITIMIZE_RELOAD_ADDRESS.  The macro INT14_OK_STRICT was defined
to facilitate testing and simplify GO_IF_LEGITIMATE_ADDRESS.  This
defines allows 14-bit when TARGET_DISABLE_FPREGS is true.  Moving the
define of SECONDARY_MEMORY_NEEDED from pa.h to pa-64.h wasn't absolutely
necessary but it prevents some unnecessary code from being compiled
into reload.

I've tested the change on hppa-unknown-linux-gnu, hppa2.0w-hp-hpux11.11
and hppa64-hp-hpux11.11 on both trunk and 4.2 branch with no regressions.

The patch has been committed to the trunk.  I'm pondering whether
to commit it to 4.2.  This is a very tricky change and it might easily
introduce problems elsewhere.  In developing this change, I thought
several times that I had the final version only to find that I had
broken the 64-bit port, or the 32-bit port.

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

2007-12-09  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	PR middle-end/32889
	PR target/34091
	* pa.md: Consolidate HImode and QImode move patterns into one pattern
	each, eliminating floating-point alternatives.
	* pa-protos.h (pa_cannot_change_mode_class, pa_modes_tieable_p):
	Declare functions.
	* pa-64.h (SECONDARY_MEMORY_NEEDED): Define here.
	* pa.c (pa_secondary_reload): Use an intermediate general register
	for copies to/from floating-point register classes.  Simplify code
	SHIFT_REGS class.  Provide additional comments.
	(pa_cannot_change_mode_class, pa_modes_tieable_p): New functions.
	* pa.h (MODES_TIEABLE_P): Use pa_modes_tieable_p.
	(SECONDARY_MEMORY_NEEDED): Delete define.
	(INT14_OK_STRICT): Define.
	(MODE_OK_FOR_SCALED_INDEXING_P): Allow SFmode and DFmode when using
	soft float.
	(MODE_OK_FOR_UNSCALED_INDEXING_P): Likewise.
	(GO_IF_LEGITIMATE_ADDRESS): Use INT14_OK_STRICT in REG+D case for
	SFmode and DFmode.
	(LEGITIMIZE_RELOAD_ADDRESS): Use INT14_OK_STRICT in mask selection.
	Align DImode offsets when generating 64-bit code.
	* pa32-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
	(CANNOT_CHANGE_MODE_CLASS): Define.
	* pa64-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
	(CANNOT_CHANGE_MODE_CLASS): Define using pa_cannot_change_mode_class.

Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 130717)
+++ config/pa/pa.md	(working copy)
@@ -3183,60 +3183,11 @@
 
 (define_insn ""
   [(set (match_operand:HI 0 "move_dest_operand"
-	 		  "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
-	(match_operand:HI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
-  "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && !TARGET_SOFT_FLOAT
-   && !TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldh%M1 %1,%0
-   sth%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %sar,%0
-   fcpy,sgl %f1,%0
-   {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
-   {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "move_dest_operand"
-	 		  "=r,r,r,r,r,Q,!*q,!r,!*f")
-	(match_operand:HI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
-  "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && !TARGET_SOFT_FLOAT
-   && TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   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,move")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "move_dest_operand"
 	 		  "=r,r,r,r,r,Q,!*q,!r")
 	(match_operand:HI 1 "move_src_operand"
 			  "r,J,N,K,RQ,rM,!rM,!*q"))]
   "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && TARGET_SOFT_FLOAT"
+    || reg_or_0_operand (operands[1], HImode))"
   "@
    copy %1,%0
    ldi %1,%0
@@ -3356,60 +3307,11 @@
 
 (define_insn ""
   [(set (match_operand:QI 0 "move_dest_operand"
-			  "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
-	(match_operand:QI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
-  "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && !TARGET_SOFT_FLOAT
-   && !TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldb%M1 %1,%0
-   stb%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %%sar,%0
-   fcpy,sgl %f1,%0
-   {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
-   {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
-
-(define_insn ""
-  [(set (match_operand:QI 0 "move_dest_operand"
-			  "=r,r,r,r,r,Q,!*q,!r,!*f")
-	(match_operand:QI 1 "move_src_operand"
-			  "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
-  "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && !TARGET_SOFT_FLOAT
-   && TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   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,move")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
-
-(define_insn ""
-  [(set (match_operand:QI 0 "move_dest_operand"
 			  "=r,r,r,r,r,Q,!*q,!r")
 	(match_operand:QI 1 "move_src_operand"
 			  "r,J,N,K,RQ,rM,!rM,!*q"))]
   "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && TARGET_SOFT_FLOAT"
+    || reg_or_0_operand (operands[1], QImode))"
   "@
    copy %1,%0
    ldi %1,%0
Index: config/pa/pa-protos.h
===================================================================
--- config/pa/pa-protos.h	(revision 130717)
+++ config/pa/pa-protos.h	(working copy)
@@ -172,6 +172,9 @@
 					 unsigned HOST_WIDE_INT,
 					 unsigned int);
 extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
+extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode,
+					 enum reg_class);
+extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode);
 
 extern const int magic_milli[];
 extern int shadd_constant_p (int);
Index: config/pa/pa-64.h
===================================================================
--- config/pa/pa-64.h	(revision 130717)
+++ config/pa/pa-64.h	(working copy)
@@ -84,3 +84,17 @@
    want aggregates padded down.  */
 
 #define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
+
+/* In the PA architecture, it is not possible to directly move data
+   between GENERAL_REGS and FP_REGS.  On the 32-bit port, we use the
+   location at SP-16 because PA 1.X only supports 5-bit immediates for
+   floating-point loads and stores.  We don't expose this location in
+   the RTL to avoid scheduling related problems.  For example, the
+   store and load could be separated by a call to a pure or const
+   function which has no frame and this function might also use SP-16.
+   We have 14-bit immediates on the 64-bit port, so we use secondary
+   memory for the copies.  */
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+  (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)		\
+   || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))
+
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 130717)
+++ config/pa/pa.c	(working copy)
@@ -5687,30 +5687,66 @@
   if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
     regno = true_regnum (x);
 
-  /* Handle out of range displacement for integer mode loads/stores of
-     FP registers.  */
-  if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
-       && GET_MODE_CLASS (mode) == MODE_INT
-       && FP_REG_CLASS_P (class))
-      || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
+  /* In order to allow 14-bit displacements in integer loads and stores,
+     we need to prevent reload from generating out of range integer mode
+     loads and stores to the floating point registers.  Previously, we
+     used to call for a secondary reload and have emit_move_sequence()
+     fix the instruction sequence.  However, reload occasionally wouldn't
+     generate the reload and we would end up with an invalid REG+D memory
+     address.  So, now we use an intermediate general register for most
+     memory loads and stores.  */
+  if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && FP_REG_CLASS_P (class))
     {
+      /* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check
+	 the secondary reload needed for a pseudo.  It never passes a
+	 REG+D address.  */
+      if (GET_CODE (x) == MEM)
+	{
+	  x = XEXP (x, 0);
+
+	  /* We don't need an intermediate for indexed and LO_SUM DLT
+	     memory addresses.  When INT14_OK_STRICT is true, it might
+	     appear that we could directly allow register indirect
+	     memory addresses.  However, this doesn't work because we
+	     don't support SUBREGs in floating-point register copies
+	     and reload doesn't tell us when it's going to use a SUBREG.  */
+	  if (IS_INDEX_ADDR_P (x)
+	      || IS_LO_SUM_DLT_ADDR_P (x))
+	    return NO_REGS;
+
+	  /* Otherwise, we need an intermediate general register.  */
+	  return GENERAL_REGS;
+	}
+
+      /* Request a secondary reload with a general scratch register
+	 for everthing else.  ??? Could symbolic operands be handled
+	 directly when generating non-pic PA 2.0 code?  */
       sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
       return NO_REGS;
     }
 
+  /* We need a secondary register (GPR) for copies between the SAR
+     and anything other than a general register.  */
+  if (class == SHIFT_REGS && (regno <= 0 || regno >= 32))
+    {
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
+
   /* A SAR<->FP register copy requires a secondary register (GPR) as
      well as secondary memory.  */
   if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
-      && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
-	  || (class == SHIFT_REGS
-	      && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
+      && (REGNO_REG_CLASS (regno) == SHIFT_REGS
+      && FP_REG_CLASS_P (class)))
     {
       sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
       return NO_REGS;
     }
 
   /* Secondary reloads of symbolic operands require %r1 as a scratch
-     register when we're generating PIC code and the operand isn't
+     register when we're generating PIC code and when the operand isn't
      readonly.  */
   if (GET_CODE (x) == HIGH)
     x = XEXP (x, 0);
@@ -9570,4 +9606,62 @@
 }
 #endif
 
+/* Return true if a change from mode FROM to mode TO for a register
+   in register class CLASS is invalid.  */
+
+bool
+pa_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
+			     enum reg_class class)
+{
+  if (from == to)
+    return false;
+
+  /* Reject changes to/from complex and vector modes.  */
+  if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from)
+      || COMPLEX_MODE_P (to) || VECTOR_MODE_P (to))
+    return true;
+      
+  if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to))
+    return false;
+
+  /* There is no way to load QImode or HImode values directly from
+     memory.  SImode loads to the FP registers are not zero extended.
+     On the 64-bit target, this conflicts with the definition of
+     LOAD_EXTEND_OP.  Thus, we can't allow changing between modes
+     with different sizes in the floating-point registers.  */
+  if (MAYBE_FP_REG_CLASS_P (class))
+    return true;
+
+  /* HARD_REGNO_MODE_OK places modes with sizes larger than a word
+     in specific sets of registers.  Thus, we cannot allow changing
+     to a larger mode when it's larger than a word.  */
+  if (GET_MODE_SIZE (to) > UNITS_PER_WORD
+      && GET_MODE_SIZE (to) > GET_MODE_SIZE (from))
+    return true;
+
+  return false;
+}
+
+/* Returns TRUE if it is a good idea to tie two pseudo registers
+   when one has mode MODE1 and one has mode MODE2.
+   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+   for any hard reg, then this must be FALSE for correct output.
+   
+   We should return FALSE for QImode and HImode because these modes
+   are not ok in the floating-point registers.  However, this prevents
+   tieing these modes to SImode and DImode in the general registers.
+   So, this isn't a good idea.  We rely on HARD_REGNO_MODE_OK and
+   CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
+   in the floating-point registers.  */
+
+bool
+pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+  /* Don't tie modes in different classes.  */
+  if (GET_MODE_CLASS (mode1) != GET_MODE_CLASS (mode2))
+    return false;
+
+  return true;
+}
+
 #include "gt-pa.h"
Index: config/pa/pa.h
===================================================================
--- config/pa/pa.h	(revision 130717)
+++ config/pa/pa.h	(working copy)
@@ -349,7 +349,7 @@
    If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
    for any hard reg, then this must be 0 for correct output.  */
 #define MODES_TIEABLE_P(MODE1, MODE2) \
-  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+  pa_modes_tieable_p (MODE1, MODE2)
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -497,17 +497,6 @@
 #define MAYBE_FP_REG_CLASS_P(CLASS) \
   reg_classes_intersect_p ((CLASS), FP_REGS)
 
-/* On the PA it is not possible to directly move data between
-   GENERAL_REGS and FP_REGS.  On the 32-bit port, we use the
-   location at SP-16.  We don't expose this location in the RTL to
-   avoid scheduling related problems.  For example, the store and
-   load could be separated by a call to a pure or const function
-   which has no frame and uses SP-16.  */
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE)			\
-  (TARGET_64BIT								\
-   && (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)		\
-       || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1)))
-
 
 /* Stack layout; function entry, exit and calling.  */
 
@@ -1116,6 +1105,24 @@
    && REG_OK_FOR_BASE_P (XEXP (OP, 0))			\
    && GET_CODE (XEXP (OP, 1)) == UNSPEC)
 
+/* Nonzero if 14-bit offsets can be used for all loads and stores.
+   This is not possible when generating PA 1.x code as floating point
+   loads and stores only support 5-bit offsets.  Note that we do not
+   forbid the use of 14-bit offsets in GO_IF_LEGITIMATE_ADDRESS.
+   Instead, we use pa_secondary_reload() to reload integer mode
+   REG+D memory addresses used in floating point loads and stores.
+
+   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
+   yet supported by GNU ld.  For now, we reject long displacements
+   on this target.  */
+
+#define INT14_OK_STRICT \
+  (TARGET_SOFT_FLOAT                                                   \
+   || TARGET_DISABLE_FPREGS                                            \
+   || (TARGET_PA_20 && !TARGET_ELF32))
+
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
    We have two alternate definitions for each of them.
@@ -1134,16 +1141,18 @@
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
 
 #else
 
 /* Nonzero if X is a hard reg that can be used as an index.  */
 #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+
 /* Nonzero if X is a hard reg that can be used as a base reg.  */
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
@@ -1195,12 +1204,8 @@
 
    We treat a SYMBOL_REF as legitimate if it is part of the current
    function's constant-pool, because such addresses can actually be
-   output as REG+SMALLINT. 
+   output as REG+SMALLINT.  */
 
-   Note we only allow 5-bit immediates for access to a constant address;
-   doing so avoids losing for loading/storing a FP register at an address
-   which will not fit in 5 bits.  */
-
 #define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20)
 #define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X))
 
@@ -1227,7 +1232,8 @@
   ((TARGET_64BIT && (MODE) == DImode)					\
    || (MODE) == SImode							\
    || (MODE) == HImode							\
-   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+   || (MODE) == SFmode							\
+   || (MODE) == DFmode)
 
 /* These are the modes that we allow for unscaled indexing.  */
 #define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \
@@ -1235,7 +1241,8 @@
    || (MODE) == SImode							\
    || (MODE) == HImode							\
    || (MODE) == QImode							\
-   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+   || (MODE) == SFmode							\
+   || (MODE) == DFmode)
 
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
 {									\
@@ -1269,20 +1276,10 @@
 			   || (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.  */			\
+		      be aligned.  */					\
 		   || (((MODE) == SFmode || (MODE) == DFmode)		\
-		       && (TARGET_SOFT_FLOAT				\
-			   || (TARGET_PA_20				\
-			       && !TARGET_ELF32				\
-			       && (INTVAL (index)			\
-				   % GET_MODE_SIZE (MODE)) == 0)))))	\
+		       && INT14_OK_STRICT				\
+		       && (INTVAL (index) % GET_MODE_SIZE (MODE)) == 0))) \
 	       || INT_5_BITS (index)))					\
 	goto ADDR;							\
       if (!TARGET_DISABLE_INDEXING					\
@@ -1382,7 +1379,7 @@
   rtx new, temp = NULL_RTX;						\
 									\
   mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT				\
-	  ? (TARGET_PA_20 && !TARGET_ELF32 ? 0x3fff : 0x1f) : 0x3fff);	\
+	  ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff);		\
 									\
   if (optimize && GET_CODE (AD) == PLUS)				\
     temp = simplify_binary_operation (PLUS, Pmode,			\
@@ -1404,9 +1401,10 @@
 	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 (mask == 0x3fff						\
+	  && (GET_MODE_CLASS (MODE) == MODE_FLOAT			\
+	      || (TARGET_64BIT && (MODE) == DImode)))			\
+	newoffset &= ~(GET_MODE_SIZE (MODE) - 1);			\
 									\
       if (newoffset != 0 && VAL_14_BITS_P (newoffset))			\
 	{								\
Index: config/pa/pa32-regs.h
===================================================================
--- config/pa/pa32-regs.h	(revision 130717)
+++ config/pa/pa32-regs.h	(working copy)
@@ -172,8 +172,7 @@
 #define VALID_FP_MODE_P(MODE)						\
   ((MODE) == SFmode || (MODE) == DFmode					\
    || (MODE) == SCmode || (MODE) == DCmode				\
-   || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode		\
-   || (TARGET_PA_11 && (MODE) == DImode))
+   || (MODE) == SImode || (TARGET_PA_11 && (MODE) == DImode))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
 
@@ -288,6 +287,11 @@
   {0x00000000, 0x00000000, 0x01000000},	/* SHIFT_REGS */		\
   {0xfffffffe, 0xffffffff, 0x01ffffff}}	/* ALL_REGS */
 
+/* Defines invalid mode changes.  */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  pa_cannot_change_mode_class (FROM, TO, CLASS)
+
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
Index: config/pa/pa64-regs.h
===================================================================
--- config/pa/pa64-regs.h	(revision 130717)
+++ config/pa/pa64-regs.h	(working copy)
@@ -156,8 +156,7 @@
 #define VALID_FP_MODE_P(MODE)						\
   ((MODE) == SFmode || (MODE) == DFmode					\
    || (MODE) == SCmode || (MODE) == DCmode				\
-   || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode		\
-   || (MODE) == DImode)
+   || (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
@@ -242,18 +241,11 @@
   {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
   {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
 
-/* Defines invalid mode changes.
+/* Defines invalid mode changes.  */
 
-   SImode loads to floating-point registers are not zero-extended.
-   The definition for LOAD_EXTEND_OP specifies that integer loads
-   narrower than BITS_PER_WORD will be zero-extended.  As a result,
-   we inhibit changes from SImode unless they are to a mode that is
-   identical in size.  */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  pa_cannot_change_mode_class (FROM, TO, CLASS)
 
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)		\
-  ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)       \
-   ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
-
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */


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