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]

Patch (rs6000): fix TFmode addressing


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; }


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