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]

[PowerPC] Fix pr25212, indexed address predicates


pr25212 is an ICE caused by attempting to reload an altivec indexed mem
address as an indirect address.  The resulting reload expression,
(set (reg) (and (plus (reg) (reg)) (const_int))), is too complex for any
rs6000 insn, and reload itself doesn't try to simplify it.

The root cause of this problem is that reload is tossing out a perfectly
good indexed address as invalid, because the rs6000 predicates are too
restrictive during reload:  legitimate_indexed_address_p only allows
valid base/index hard regs, or pseudos (and the PLUS I added for
pr24997).  In particular, they disallow invalid hard regs such as lr,
yet reload will arrange for an invalid reg to be reloaded into a valid
one.  All MEMs are processed by find_reloads_address early in
find_reloads.

So, as Ian Lance Taylor suggested, this patch simply relaxes the
predicate to accept more indexed addresses when !strict, trusting that
reload will ensure they match in the strict sense after reloading.  No
doubt other powerpc predicates could also be relaxed similarly, but I'll
leave that to later sometime when I feel like wrestling with reload
again.

As mentioned previously this also fixes INT_REG_OK_FOR_BASE_P, which can
return true for a pseudo reg that has reg_renumber[REGNO] == 0.

This has passed a "make quickstrap" followed by "make check" in gcc/,
ie. running gcc, g++, gfortran, objc testsuites without regressions on
both powerpc-linux and powerpc64-linux.  I'm running full bootstraps as
well, but these haven't completed.  OK for mainline and 4.1?

:ADDPATCH target:

	PR target/25212
	* config/rs6000/rs6000.c (legitimate_indexed_address_p): Relax
	tests further when !strict && reload_in_progress.
	(print_operand): Check that both operands of indexed address are regs.
	(print_operand_address): Likewise.
	* config/rs6000/rs6000.h (INT_REG_OK_FOR_INDEX_P): Simplify.
	(INT_REG_OK_FOR_BASE_P): Correct.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 108055)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -2726,23 +2726,19 @@ legitimate_indexed_address_p (rtx x, int
   op0 = XEXP (x, 0);
   op1 = XEXP (x, 1);
 
-  if (REG_P (op0) && REG_P (op1))
-    return ((INT_REG_OK_FOR_BASE_P (op0, strict)
-	     && INT_REG_OK_FOR_INDEX_P (op1, strict))
-	    || (INT_REG_OK_FOR_BASE_P (op1, strict)
-		&& INT_REG_OK_FOR_INDEX_P (op0, strict)));
-
   /* Recognize the rtl generated by reload which we know will later be
-     replaced by a base reg.  We rely on nothing but reload generating
-     this particular pattern, a reasonable assumption because it is not
-     canonical.  */
-  else if (reload_in_progress
-	   && GET_CODE (op0) == PLUS
-	   && REG_P (XEXP (op0, 0))
 -	   && GET_CODE (XEXP (op0, 1)) == CONST_INT
-	   && REG_P (op1))
-    return INT_REG_OK_FOR_INDEX_P (op1, strict);
-  return false;
+     replaced with proper base and index regs.  */
+  if (!strict
+      && reload_in_progress
+      && (REG_P (op0) || GET_CODE (op0) == PLUS)
+      && REG_P (op1))
+    return true;
+
+  return (REG_P (op0) && REG_P (op1)
+	  && ((INT_REG_OK_FOR_BASE_P (op0, strict)
+	       && INT_REG_OK_FOR_INDEX_P (op1, strict))
+	      || (INT_REG_OK_FOR_BASE_P (op1, strict)
+		  && INT_REG_OK_FOR_INDEX_P (op0, strict))));
 }
 
 inline bool
@@ -10667,7 +10677,8 @@ print_operand (FILE *file, rtx x, int co
 	else
 	  {
 	    gcc_assert (GET_CODE (tmp) == PLUS
-			&& GET_CODE (XEXP (tmp, 1)) == REG);
+			&& REG_P (XEXP (tmp, 0))
+			&& REG_P (XEXP (tmp, 1)));
 
 	    if (REGNO (XEXP (tmp, 0)) == 0)
 	      fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
@@ -10727,6 +10738,7 @@ print_operand_address (FILE *file, rtx x
     }
   else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
     {
+      gcc_assert (REG_P (XEXP (x, 0)));
       if (REGNO (XEXP (x, 0)) == 0)
 	fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
 		 reg_names[ REGNO (XEXP (x, 0)) ]);
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 108055)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1723,17 +1751,14 @@ typedef struct rs6000_args
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg in the non-strict case.  */
 #define INT_REG_OK_FOR_INDEX_P(X, STRICT)			\
-  ((! (STRICT)							\
-    && (REGNO (X) <= 31						\
-	|| REGNO (X) == ARG_POINTER_REGNUM			\
-	|| REGNO (X) == FRAME_POINTER_REGNUM			\
-	|| REGNO (X) >= FIRST_PSEUDO_REGISTER))			\
-   || ((STRICT) && REGNO_OK_FOR_INDEX_P (REGNO (X))))
+  ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER)		\
+   || REGNO_OK_FOR_INDEX_P (REGNO (X)))
 
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg in the non-strict case.  */
 #define INT_REG_OK_FOR_BASE_P(X, STRICT)			\
-  (REGNO (X) > 0 && INT_REG_OK_FOR_INDEX_P (X, (STRICT)))
+  ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER)		\
+   || REGNO_OK_FOR_BASE_P (REGNO (X)))
 
 #define REG_OK_FOR_INDEX_P(X) INT_REG_OK_FOR_INDEX_P (X, REG_OK_STRICT_FLAG)
 #define REG_OK_FOR_BASE_P(X)  INT_REG_OK_FOR_BASE_P (X, REG_OK_STRICT_FLAG)

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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