This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch (rs6000): fix codegen for lod/sto to double at offset 32760
- From: Dale Johannesen <dalej at apple dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Dale Johannesen <dalej at apple dot com>
- Date: Sat, 19 Jun 2004 15:59:03 -0700
- Subject: Patch (rs6000): fix codegen for lod/sto to double at offset 32760
The pattern generating FP move to or from memory at [Reg+32760] was
calling the generic offsettable_memref_p, which considers an address to
be
offsettable only if there is enough room for the largest possible mode
(TFmode)
without overflow. This results in invalid assembly code (x-form
instructions
referencing this address) on Darwin, and probably elsewhere. This
makes it
call the rs6000-specific legitimate_offset_address_p, which does the
right thing,
instead. That is also renamed to follow the usual convention. The
testcase
exhibits the problem on Darwin; adjustment of the array size is probably
necessary to make it fail on other OSs. Bootstrapped and tested on
Darwin.
2004-06-19 Dale Johannesen <dalej@apple.com>
* config/rs6000/rs6000.c (legitimate_offset_address_p): Make
global, rename rs6000_legitimate_offset_address_p.
(rs6000_legitimate_address_p): Adjust calls to it.
(lmw_operation): Ditto.
(stmw_operation): Ditto.
* config/rs6000/rs6000-protos.h: Declare it.
* config/rs6000/rs6000.md (*movdf_hardfloat32): Use it
instead of offsettable_memref_p.
Index: rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.81
diff -u -d -b -w -c -3 -p -r1.81 rs6000-protos.h
*** rs6000-protos.h 9 May 2004 14:32:49 -0000 1.81
--- rs6000-protos.h 19 Jun 2004 18:26:08 -0000
*************** extern bool rs6000_mode_dependent_addres
*** 139,144 ****
--- 139,145 ----
extern rtx rs6000_return_addr (int, rtx);
extern void rs6000_output_symbol_ref (FILE*, rtx);
extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int);
+ extern bool rs6000_legitimate_offset_address_p (enum machine_mode,
rtx, int);
extern rtx rs6000_machopic_legitimize_pic_address (rtx orig,
enum machine_mode mode, rtx reg);
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.650
diff -u -d -b -w -c -3 -p -r1.650 rs6000.c
*** rs6000.c 11 Jun 2004 18:41:44 -0000 1.650
--- rs6000.c 19 Jun 2004 18:26:09 -0000
*************** static int constant_pool_expr_1 (rtx, in
*** 303,309 ****
static bool constant_pool_expr_p (rtx);
static bool toc_relative_expr_p (rtx);
static bool legitimate_small_data_p (enum machine_mode, rtx);
- static bool legitimate_offset_address_p (enum machine_mode, rtx, int);
static bool legitimate_indexed_address_p (rtx, int);
static bool legitimate_indirect_address_p (rtx, int);
static bool macho_lo_sum_memory_operand (rtx x, enum machine_mode
mode);
--- 303,308 ----
*************** legitimate_small_data_p (enum machine_mo
*** 2648,2655 ****
&& small_data_operand (x, mode));
}
! static bool
! legitimate_offset_address_p (enum machine_mode mode, rtx x, int
strict)
{
unsigned HOST_WIDE_INT offset, extra;
--- 2647,2654 ----
&& small_data_operand (x, mode));
}
! bool
! rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
int strict)
{
unsigned HOST_WIDE_INT offset, extra;
*************** rs6000_legitimate_address (enum machine_
*** 3356,3364 ****
|| XEXP (x, 0) == arg_pointer_rtx)
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
return 1;
! if (legitimate_offset_address_p (mode, x, reg_ok_strict))
return 1;
if (mode != TImode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
|| (mode != DFmode && mode != TFmode))
--- 3355,3363 ----
|| XEXP (x, 0) == arg_pointer_rtx)
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
return 1;
! if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
return 1;
if (mode != TImode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
|| (mode != DFmode && mode != TFmode))
*************** lmw_operation (rtx op, enum machine_mode
*** 8383,8389 ****
if (base_regno == 0)
return 0;
}
! else if (legitimate_offset_address_p (SImode, src_addr, 0))
{
offset = INTVAL (XEXP (src_addr, 1));
base_regno = REGNO (XEXP (src_addr, 0));
--- 8396,8402 ----
if (base_regno == 0)
return 0;
}
! else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
{
offset = INTVAL (XEXP (src_addr, 1));
base_regno = REGNO (XEXP (src_addr, 0));
*************** lmw_operation (rtx op, enum machine_mode
*** 8411,8417 ****
newoffset = 0;
addr_reg = newaddr;
}
! else if (legitimate_offset_address_p (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
--- 8424,8430 ----
newoffset = 0;
addr_reg = newaddr;
}
! else if (rs6000_legitimate_offset_address_p (SImode, newaddr,
0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
*************** stmw_operation (rtx op, enum machine_mod
*** 8459,8465 ****
if (base_regno == 0)
return 0;
}
! else if (legitimate_offset_address_p (SImode, dest_addr, 0))
{
offset = INTVAL (XEXP (dest_addr, 1));
base_regno = REGNO (XEXP (dest_addr, 0));
--- 8472,8478 ----
if (base_regno == 0)
return 0;
}
! else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
{
offset = INTVAL (XEXP (dest_addr, 1));
base_regno = REGNO (XEXP (dest_addr, 0));
*************** stmw_operation (rtx op, enum machine_mod
*** 8487,8493 ****
newoffset = 0;
addr_reg = newaddr;
}
! else if (legitimate_offset_address_p (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
--- 8500,8506 ----
newoffset = 0;
addr_reg = newaddr;
}
! else if (rs6000_legitimate_offset_address_p (SImode, newaddr,
0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.305
diff -u -d -b -w -c -3 -p -r1.305 rs6000.md
*** rs6000.md 18 May 2004 05:35:30 -0000 1.305
--- rs6000.md 19 Jun 2004 18:26:09 -0000
***************
*** 8051,8061 ****
else
return \"mr %0,%1\;mr %L0,%L1\";
case 1:
! if (offsettable_memref_p (operands[1])
! || (GET_CODE (operands[1]) == MEM
! && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[1], 0)) == PRE_INC
! || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
{
/* If the low-address word is used in the address, we must
load
it last. Otherwise, load it first. Note that we cannot
have
--- 8051,8063 ----
else
return \"mr %0,%1\;mr %L0,%L1\";
case 1:
! if (GET_CODE (operands[1]) == MEM
! && (rs6000_legitimate_offset_address_p (DFmode, XEXP
(operands[1], 0),
! reload_completed || reload_in_progress)
! || GET_CODE (XEXP (operands[1], 0)) == REG
! || GET_CODE (XEXP (operands[1], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[1], 0)) == PRE_INC
! || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))
{
/* If the low-address word is used in the address, we must
load
it last. Otherwise, load it first. Note that we cannot
have
***************
*** 8091,8101 ****
}
}
case 2:
! if (offsettable_memref_p (operands[0])
! || (GET_CODE (operands[0]) == MEM
! && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[0], 0)) == PRE_INC
! || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
else
{
--- 8093,8105 ----
}
}
case 2:
! if (GET_CODE (operands[0]) == MEM
! && (rs6000_legitimate_offset_address_p (DFmode, XEXP
(operands[0], 0),
! reload_completed || reload_in_progress)
! || GET_CODE (XEXP (operands[0], 0)) == REG
! || GET_CODE (XEXP (operands[0], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[0], 0)) == PRE_INC
! || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
else
{
/* { dg-do link } */
void f(char x[32688], double *y, double *z) __attribute__((noinline));
void f(char x[32688], double *y, double *z) {}
main() {
char x[32688];
double y, z;
y = z = 3.0;
f(x, &y, &z);
}