Stricter invalid_e500_subreg (with jump.c:true_regnum fix)

Joseph S. Myers joseph@codesourcery.com
Wed Nov 29 00:55:00 GMT 2006


This patch makes the checks of invalid_e500_subreg more restrictive.
It needs to be checked by gpc_reg_operand in addition to the other
predicates checking it, and it can't allow offset 4 for SImode subregs
of SPE vectors after all (although such an offset is just the low
part, allowing it in invalid_e500_subreg ends up with operations on
the high part of the register getting lost).

Fixing this causes problems with insv instructions on E500 subregs
that don't get recognised, so the patch makes the insv pattern fail in
that case.  It also shows up a latent bug compiling the libstdc++ test
26_numerics/complex/13450.cc, where (subreg:DF (reg:DI 9 9) 0) gets
set but then (reg:DF 9 9) gets used in a comparison as if it had the
same value.  This is fixed by the change to jump.c:true_regnum to stop
it from using subreg_regno_offset unless subreg_offset_representable_p
is satisfied.

(I wonder if subreg_regno_offset should have an assert that
subreg_offset_representable_p passes?  I suspect this would show up
other bugs, perhaps too many such bugs for it to be possible just to
put such an assert in and let such bugs get fixed as they are found.)

Tested with no regressions with a cross to powerpc-none-linux-gnuspe 
(mainline, 4.2, 4.1).  Also bootstrapped with no regressions on 
i686-pc-linux-gnu.  OK to commit to mainline, 4.2, 4.1?

This patch fixes the following test FAILs, so leaving E500v2 results
reasonably clean again in conjunction with my other two unreviewed
patches, <http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01683.html> to
fix complex double va_arg and
<http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01700.html> to fix
subreg_regno_offset and subreg_offset_representable_p and make
associated back-end changes.  (The results are cleanest for 4.1; there
are a few remaining execution failures for 4.2 and mainline that are
likely E500-specific and may well be latent bugs in earlier versions.)

FAIL: gcc.c-torture/execute/pr23135.c execution,  -O1 
FAIL: gcc.c-torture/execute/pr23135.c execution,  -O2 
FAIL: gcc.c-torture/execute/pr23135.c execution,  -O3 -fomit-frame-pointer 
FAIL: gcc.c-torture/execute/pr23135.c execution,  -O3 -g 
FAIL: gcc.c-torture/execute/pr23135.c execution,  -Os 
FAIL: tmpdir-gcc.dg-struct-layout-1/t004 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t006 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t011 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t018 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t019 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t021 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-gcc.dg-struct-layout-1/t028 c_compat_x_tst.o-c_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t006 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t007 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t018 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t021 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t024 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t026 cp_compat_x_tst.o-cp_compat_y_tst.o execute 
FAIL: tmpdir-g++.dg-struct-layout-1/t027 cp_compat_x_tst.o-cp_compat_y_tst.o execute 

2006-11-29  Joseph Myers  <joseph@codesourcery.com>

	* config/rs6000/predicates.md (gpc_reg_operand): Check
	invalid_e500_subreg.
	* config/rs6000/rs6000.c (invalid_e500_subreg): Don't allow any
	SImode subregs of SPE vectors.
	* config/rs6000/rs6000.md (insv): Fail for invalid E500 subregs.
	* jump.c (true_regnum): Require subregs to satisfy
	subreg_offset_representable_p.

Index: gcc/jump.c
===================================================================
--- gcc/jump.c	(revision 119286)
+++ gcc/jump.c	(working copy)
@@ -1994,7 +1994,11 @@
   if (GET_CODE (x) == SUBREG)
     {
       int base = true_regnum (SUBREG_REG (x));
-      if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
+      if (base >= 0
+	  && base < FIRST_PSEUDO_REGISTER
+	  && subreg_offset_representable_p (REGNO (SUBREG_REG (x)),
+					    GET_MODE (SUBREG_REG (x)),
+					    SUBREG_BYTE (x), GET_MODE (x)))
 	return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
 					   GET_MODE (SUBREG_REG (x)),
 					   SUBREG_BYTE (x), GET_MODE (x));
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 119286)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -2555,8 +2555,7 @@
       && GET_CODE (op) == SUBREG
       && mode == SImode
       && REG_P (SUBREG_REG (op))
-      && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op)))
-      && SUBREG_BYTE (op) != 4)
+      && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op))))
     return true;
 
   return false;
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 119286)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -84,10 +84,11 @@
 ;; Return 1 if op is a register that is not special.
 (define_predicate "gpc_reg_operand"
    (and (match_operand 0 "register_operand")
-	(match_test "GET_CODE (op) != REG
-		     || (REGNO (op) >= ARG_POINTER_REGNUM
-			 && !XER_REGNO_P (REGNO (op)))
-		     || REGNO (op) < MQ_REGNO")))
+	(match_test "(GET_CODE (op) != REG
+		      || (REGNO (op) >= ARG_POINTER_REGNUM
+			  && !XER_REGNO_P (REGNO (op)))
+		      || REGNO (op) < MQ_REGNO)
+		     && !invalid_e500_subreg (op, mode)")))
 
 ;; Return 1 if op is a register that is a condition register field.
 (define_predicate "cc_reg_operand"
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 119286)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -2856,9 +2856,11 @@
 {
   /* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since
      the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the
-     compiler if the address of the structure is taken later.  */
+     compiler if the address of the structure is taken later.  Likewise, do
+     not handle invalid E500 subregs.  */
   if (GET_CODE (operands[0]) == SUBREG
-      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD))
+      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD
+	  || invalid_e500_subreg (operands[0], GET_MODE (operands[0]))))
     FAIL;
 
   if (TARGET_POWERPC64 && GET_MODE (operands[0]) == DImode)

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list