Commit cae80939 by John David Anglin Committed by John David Anglin

re PR rtl-optimization/14782 (produces an unaligned data access at -O2)

	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.

From-SVN: r83464
parent a90fc8e0
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.
2004-06-21 Richard Henderson <rth@redhat.com> 2004-06-21 Richard Henderson <rth@redhat.com>
PR rtl-opt/16114 PR rtl-opt/16114
......
...@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg) ...@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
operand1 = gen_rtx_MEM (GET_MODE (operand1), tem); operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
/* Handle secondary reloads for loads/stores of FP registers from /* 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. */ (subreg (mem (addr))) cases. */
if (scratch_reg if (scratch_reg
&& fp_reg_operand (operand0, mode) && fp_reg_operand (operand0, mode)
&& ((GET_CODE (operand1) == MEM && ((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 (operand1) == SUBREG
&& GET_CODE (XEXP (operand1, 0)) == MEM && 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) if (GET_CODE (operand1) == SUBREG)
operand1 = XEXP (operand1, 0); operand1 = XEXP (operand1, 0);
...@@ -1600,10 +1603,13 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg) ...@@ -1600,10 +1603,13 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
else if (scratch_reg else if (scratch_reg
&& fp_reg_operand (operand1, mode) && fp_reg_operand (operand1, mode)
&& ((GET_CODE (operand0) == MEM && ((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 (operand0) == SUBREG)
&& GET_CODE (XEXP (operand0, 0)) == MEM && 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))))) XEXP (XEXP (operand0, 0), 0)))))
{ {
if (GET_CODE (operand0) == SUBREG) if (GET_CODE (operand0) == SUBREG)
......
...@@ -1284,7 +1284,7 @@ extern int may_call_alloca; ...@@ -1284,7 +1284,7 @@ extern int may_call_alloca;
`S' is the constant 31. `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. */ `U' is the constant 63. */
...@@ -1307,17 +1307,20 @@ extern int may_call_alloca; ...@@ -1307,17 +1307,20 @@ extern int may_call_alloca;
(GET_CODE (OP) == MEM \ (GET_CODE (OP) == MEM \
&& !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)) \ && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)) \
&& !IS_INDEX_ADDR_P (XEXP (OP, 0)) \ && !IS_INDEX_ADDR_P (XEXP (OP, 0)) \
/* Using DFmode forces only short displacements \ /* Floating-point loads and stores are used to load \
to be recognized as valid in reg+d addresses. \ integer values as well as floating-point values. \
However, this is not necessary for PA2.0 since \ They don't have the same set of REG+D address modes \
it has long FP loads/stores. \ 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 checks in GO_IF_LEGITIMATE_ADDRESS for SFmode and \
the FP register number in {fldw,fstw} insns. \ DFmode test the validity of an address for use in a \
Thus, we only allow long FP loads/stores on \ floating point load or store. So, we use SFmode/DFmode \
TARGET_64BIT. */ \ to see if the address is valid for a floating-point \
&& memory_address_p ((TARGET_PA_20 && !TARGET_ELF32 \ load/store operation. */ \
? GET_MODE (OP) \ && memory_address_p ((GET_MODE_SIZE (GET_MODE (OP)) == 4 \
? SFmode \
: DFmode), \ : DFmode), \
XEXP (OP, 0))) \ XEXP (OP, 0))) \
: ((C) == 'S' ? \ : ((C) == 'S' ? \
...@@ -1467,13 +1470,32 @@ extern int may_call_alloca; ...@@ -1467,13 +1470,32 @@ extern int may_call_alloca;
if (base \ if (base \
&& GET_CODE (index) == CONST_INT \ && GET_CODE (index) == CONST_INT \
&& ((INT_14_BITS (index) \ && ((INT_14_BITS (index) \
&& (TARGET_SOFT_FLOAT \ && (((MODE) != DImode \
|| (TARGET_PA_20 \ && (MODE) != SFmode \
&& ((MODE == SFmode \ && (MODE) != DFmode) \
&& (INTVAL (index) % 4) == 0) \ /* The base register for DImode loads and stores \
|| (MODE == DFmode \ with long displacements must be aligned because \
&& (INTVAL (index) % 8) == 0))) \ the lower three bits in the displacement are \
|| ((MODE) != SFmode && (MODE) != DFmode))) \ 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))) \ || INT_5_BITS (index))) \
goto ADDR; \ goto ADDR; \
if (!TARGET_DISABLE_INDEXING \ if (!TARGET_DISABLE_INDEXING \
...@@ -1589,6 +1611,11 @@ do { \ ...@@ -1589,6 +1611,11 @@ do { \
else \ else \
newoffset = offset & ~mask; \ 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)) \ if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \
{ \ { \
temp = gen_rtx_PLUS (Pmode, XEXP (new, 0), \ temp = gen_rtx_PLUS (Pmode, XEXP (new, 0), \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment