Patch (rs6000): fix TFmode addressing
Dale Johannesen
dalej@apple.com
Sat Jun 19 20:56:00 GMT 2004
The rs6000 currently allows [reg+reg] addressing mode for TFmode
(128-bit
long double) objects. I think this is just wrong, as any access to
them involves
adding small constants. This disallows it, analogous to current code
for TImode.
Bootstrapped and tested on Darwin; testcase at bottom.
2004-06-19 Dale Johannesen <dalej@apple.com>
* config/rs6000/rs6000.c (rs6000_legitimate_address): Disallow
[reg+reg] mode for TFmode memory accesses.
(rs6000_eliminate_indexed_memrefs): New.
(rs6000_emit_move): Call preceding for TImode and TFmode.
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
*************** rs6000_legitimize_reload_address (rtx x,
*** 3328,3334 ****
word aligned.
For modes spanning multiple registers (DFmode in 32-bit GPRs,
! 32-bit DImode, TImode), indexed addressing cannot be used because
adjacent memory cells are accessed by adding word-sized offsets
during assembly output. */
int
--- 3327,3333 ----
word aligned.
For modes spanning multiple registers (DFmode in 32-bit GPRs,
! 32-bit DImode, TImode, TFmode), indexed addressing cannot be used
because
adjacent memory cells are accessed by adding word-sized offsets
during assembly output. */
int
*************** 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,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
+ && mode != TFmode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
|| (mode != DFmode && mode != TFmode))
*************** rs6000_emit_set_long_const (rtx dest, HO
*** 3653,3658 ****
--- 3653,3679 ----
return dest;
}
+ /* Helper for the following. Get rid of [r+r] memory refs
+ in cases where it won't work (TImode, TFmode). */
+
+ static void
+ rs6000_eliminate_indexed_memrefs (rtx operands[2])
+ {
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) != REG
+ && ! reload_in_progress)
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_addr_to_reg (XEXP (operands[0],
0)));
+
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) != REG
+ && ! reload_in_progress)
+ operands[1]
+ = replace_equiv_address (operands[1],
+ copy_addr_to_reg (XEXP (operands[1],
0)));
+ }
+
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
*************** rs6000_emit_move (rtx dest, rtx source,
*** 3790,3795 ****
--- 3811,3819 ----
break;
case TFmode:
+ rs6000_eliminate_indexed_memrefs (operands);
+ /* fall through */
+
case DFmode:
case SFmode:
if (CONSTANT_P (operands[1])
*************** rs6000_emit_move (rtx dest, rtx source,
*** 3972,3990 ****
break;
case TImode:
! if (GET_CODE (operands[0]) == MEM
! && GET_CODE (XEXP (operands[0], 0)) != REG
! && ! reload_in_progress)
! operands[0]
! = replace_equiv_address (operands[0],
! copy_addr_to_reg (XEXP (operands[0],
0)));
- if (GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) != REG
- && ! reload_in_progress)
- operands[1]
- = replace_equiv_address (operands[1],
- copy_addr_to_reg (XEXP (operands[1],
0)));
if (TARGET_POWER)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode,
--- 3996,4003 ----
break;
case TImode:
! rs6000_eliminate_indexed_memrefs (operands);
if (TARGET_POWER)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode,
/* { dg-options "-Os -mlong-double-128" } */
/* { dg-do compile { target rs6000-*-* powerpc-*-* } } */
/* Make sure compiler doesn't generate [reg+reg] address mode
for long doubles. */
union arg {
int intarg;
long double longdoublearg;
};
long double d;
int va(int n, union arg **argtable)
{
(*argtable)[n].longdoublearg = d;
}
More information about the Gcc-patches
mailing list