[PATCH] S/390: Addends of larl operand must be in -/+2GB range

Andreas Krebbel Andreas.Krebbel@de.ibm.com
Fri Nov 24 15:54:00 GMT 2006


Hello,

the attached patch fixes a problem with addends to larl 
(load address relative long) operands getting too large.

The patch consists of what Michael proposed in the PR 
plus the changes proposed by Ulrich.

I'm about to test the patch for gcc 4.1 4.2 and mainline.

Ok for these 3 - in case there are no testsuite regressions?

Michael, thanks for looking into this.


Bye,

-Andreas-


2006-11-24  Michael Matz  <matz@suse.de>
            Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/29319
	* config/s390/s390.c (legitimize_pic_address): Check addend of larl
	operand to be in range of -/+2GB.
	* config/s390/predicates.md (larl_operand): Likewise.


2006-11-24  Michael Matz  <matz@suse.de>
            Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/29319
	* gcc.dg/20061124-2.c: New testcase.


Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig	2006-11-24 13:39:20.000000000 +0100
--- gcc/config/s390/s390.c	2006-11-24 15:52:21.000000000 +0100
*************** legitimize_pic_address (rtx orig, rtx re
*** 3002,3008 ****
  		|| (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
!               if (TARGET_CPU_ZARCH && larl_operand (op0, VOIDmode))
                  {
                    if (INTVAL (op1) & 1)
                      {
--- 3002,3011 ----
  		|| (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
!               if (TARGET_CPU_ZARCH
! 		  && larl_operand (op0, VOIDmode)
! 		  && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
! 		  && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
                  {
                    if (INTVAL (op1) & 1)
                      {
*************** legitimize_pic_address (rtx orig, rtx re
*** 3012,3018 ****
  
                        if (!DISP_IN_RANGE (INTVAL (op1)))
                          {
!                           int even = INTVAL (op1) - 1;
                            op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
  			  op0 = gen_rtx_CONST (Pmode, op0);
                            op1 = const1_rtx;
--- 3015,3021 ----
  
                        if (!DISP_IN_RANGE (INTVAL (op1)))
                          {
!                           HOST_WIDE_INT even = INTVAL (op1) - 1;
                            op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
  			  op0 = gen_rtx_CONST (Pmode, op0);
                            op1 = const1_rtx;
Index: gcc/config/s390/predicates.md
===================================================================
*** gcc/config/s390/predicates.md.orig	2006-11-24 15:44:13.000000000 +0100
--- gcc/config/s390/predicates.md	2006-11-24 15:52:32.000000000 +0100
***************
*** 126,133 ****
        if (GET_CODE (XEXP (op, 1)) != CONST_INT
            || (INTVAL (XEXP (op, 1)) & 1) != 0)
          return false;
!       if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
! 	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
          return false;
        op = XEXP (op, 0);
      }
--- 126,133 ----
        if (GET_CODE (XEXP (op, 1)) != CONST_INT
            || (INTVAL (XEXP (op, 1)) & 1) != 0)
          return false;
!       if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
! 	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
          return false;
        op = XEXP (op, 0);
      }
Index: gcc/testsuite/gcc.dg/20061124-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/20061124-2.c	2006-11-24 15:59:37.000000000 +0100
***************
*** 0 ****
--- 1,32 ----
+ { dg-compile }
+ { dg-options "-O1 -fPIC" }
+ 
+ /* PR target/29319 */
+ 
+ extern void abort(void);
+ 
+ static char l_info[100];
+ 
+ void bug1 (unsigned long tag)
+ {
+   char *info = l_info;
+   info[tag - 0x100000000 + 1] = 1;
+ }
+ 
+ void bug2 (unsigned long tag)
+ {
+   char *info = l_info;
+   info[tag - 0x100000000 + 1] = 2;
+ }
+ 
+ int main()
+ {
+   unsigned i;
+   for (i = 0; i < sizeof(l_info); i++)
+     l_info[i] = 0;
+   bug1(0x100000000);
+   bug2(0x100000000);
+   if (l_info[2] != 2 || l_info[1] != 1)
+     abort();
+   return 0;
+ }



More information about the Gcc-patches mailing list