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>
PR rtl-opt/16114
......
......@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
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 machine_mode mode, rtx scratch_reg)
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)
......
......@@ -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), \
......
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