ppc codegen bugfix

Jeffrey A Law law@cygnus.com
Tue Jul 13 01:26:00 GMT 1999


Many double-precision tests in lapack on ppc-linux are getting runtime
failures.

The symptom is the test core dumps trying to load/store from a bogus
memory address.  A typical sequence looks like:

        stwx 10,9,0      # 1154 *movdf_hardfloat32/3    [length = 16]
        la 0,4(0)
        stwx 11,9,0
        la 0,-4(0)

Due to the unusual conventions for r0 on the ppc this sequence does not
do what we want.   The "la 0,4(0)" is implemented with an "addi" instruction
and a reference to r0 in an addi instruction results in the value zero, not
the value contained by r0.  So this instruction just loads the value 4 into
register r0 instead of incrementing r0 by 4.  Opps.

The correct sequence is:


        stwx 10,9,0      # 1154 *movdf_hardfloat32/3    [length = 16]
        la 9,4(9)
        stwx 11,9,0
        la 9,-4(9)


ie, use r9 as the base register when fixing up non-offsettable memory
addresses.

	* rs6000.c (find_addr_reg): Do not select r0 as an address
	register.

Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.70.4.7
diff -c -3 -p -r1.70.4.7 rs6000.c
*** rs6000.c	1999/06/28 03:21:11	1.70.4.7
--- rs6000.c	1999/07/13 07:29:22
*************** rs6000_encode_section_info (decl)
*** 5692,5708 ****
  
  
  /* Return a REG that occurs in ADDR with coefficient 1.
!    ADDR can be effectively incremented by incrementing REG.  */
  
  struct rtx_def *
  find_addr_reg (addr)
       rtx addr;
  {
    while (GET_CODE (addr) == PLUS)
      {
!       if (GET_CODE (XEXP (addr, 0)) == REG)
  	addr = XEXP (addr, 0);
!       else if (GET_CODE (XEXP (addr, 1)) == REG)
  	addr = XEXP (addr, 1);
        else if (CONSTANT_P (XEXP (addr, 0)))
  	addr = XEXP (addr, 1);
--- 5692,5714 ----
  
  
  /* Return a REG that occurs in ADDR with coefficient 1.
!    ADDR can be effectively incremented by incrementing REG.
  
+    r0 is special and we must not select it as an address
+    register by this routine since our caller will try to
+    increment the returned register via an "la" instruction.  */
+ 
  struct rtx_def *
  find_addr_reg (addr)
       rtx addr;
  {
    while (GET_CODE (addr) == PLUS)
      {
!       if (GET_CODE (XEXP (addr, 0)) == REG
! 	  && REGNO (XEXP (addr, 0)) != 0)
  	addr = XEXP (addr, 0);
!       else if (GET_CODE (XEXP (addr, 1)) == REG
! 	       && REGNO (XEXP (addr, 1)) != 0)
  	addr = XEXP (addr, 1);
        else if (CONSTANT_P (XEXP (addr, 0)))
  	addr = XEXP (addr, 1);
*************** find_addr_reg (addr)
*** 5711,5717 ****
        else
  	abort ();
      }
!   if (GET_CODE (addr) == REG)
      return addr;
    abort ();
  }
--- 5717,5723 ----
        else
  	abort ();
      }
!   if (GET_CODE (addr) == REG && REGNO (addr) != 0)
      return addr;
    abort ();
  }






More information about the Gcc-patches mailing list