[PATCH] S/390: Fix shifts and setmems predicates
Andreas Krebbel
krebbel1@de.ibm.com
Thu Aug 25 08:15:00 GMT 2005
Hi,
debugging the potential reload problem with my patch omitting ANDs
applied to a shift count operand I found that even without the patch
we had a bug when eliminable regs appear within the shift count operand.
The problem occurs whenever a local stack address is used as a shift
count operand and an immediate value is added:
return a << ((unsigned long)&f + 3);
is expanded and later on combined to:
(set (reg/i:DI 2 %r2 [ <result> ])
(ashift:DI (reg:DI 2 %r2 [ a ])
(plus:SI (subreg:SI (reg/f:DI 32 %ap) 4)
(const_int 3 [0x3]))))
reload eliminates the argument pointer (32) to stack pointer + offset:
(set (reg/i:DI 2 %r2 [ <result> ])
(ashift:DI (reg:DI 2 %r2 [ a ])
(plus:SI (subreg:SI (plus:DI (reg/f:DI 15 %r15)
(const_int 160 [0xa0])) 4)
(const_int 3 [0x3]))))
Now the shift count operand is not even a general_operand anymore.
As Ulrich suggested avoiding eliminable registers to fix the new failures
(with eliminables within an AND) also helps in this case.
The attached patch modifies the shift_count_operand and the setmem_operand
to take care of this.
Bootstrapped and testsuite run without regressions on s390 and s390x.
OK for mainline?
Bye,
-Andreas-
2005-08-25 Andreas Krebbel <krebbel1@de.ibm.com>
* config/s390/predicates.md ("shift_count_operand", "setmem_operand"):
Reject operands containing eliminable registers.
* testsuite/gcc.dg/20050825-1.c: New testcase.
Index: gcc/config/s390/predicates.md
===================================================================
--- gcc/config/s390/predicates.md.orig 2005-08-24 13:09:28.000000000 +0200
+++ gcc/config/s390/predicates.md 2005-08-24 13:58:54.000000000 +0200
@@ -107,6 +107,10 @@
if (op && GET_CODE (op) != REG)
return false;
+ if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && !GENERAL_REGNO_P (REGNO (op)))
+ return false;
+
/* Unfortunately we have to reject constants that are invalid
for an address, or else reload will get confused. */
if (!DISP_IN_RANGE (offset))
@@ -147,6 +151,10 @@
if (op && GET_CODE (op) != REG)
return false;
+ if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && !GENERAL_REGNO_P (REGNO (op)))
+ return false;
+
/* Unfortunately we have to reject constants that are invalid
for an address, or else reload will get confused. */
if (!DISP_IN_RANGE (offset))
Index: gcc/testsuite/gcc.dg/20050824-1.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/20050824-1.c 2005-08-24 13:26:34.000000000 +0200
@@ -0,0 +1,30 @@
+/* Make sure that the S/390 specific shift_count_operand
+ predicate work properly. */
+
+/* { dg-do compile { target s390*-*-* } } */
+/* { dg-options "-O3" } */
+
+unsigned long long
+f (unsigned long long a, unsigned long b)
+{
+ asm ("" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14");
+
+ return a << ((b + 3) & 63);
+}
+
+unsigned long long
+g (unsigned long long a, char **b , int c, int d, int e, int f)
+{
+ char buffer [4096];
+
+ *b = &buffer[0];
+
+ return a << ((unsigned long)&f & 63);
+}
+
+unsigned long long
+h (unsigned long long a, int b, int c, int d, int e, int f)
+{
+ return a << ((unsigned long)&f + 3);
+}
More information about the Gcc-patches
mailing list