subreg-safety for rs6000.md

Geoff Keating geoffk@cygnus.com
Sun Aug 27 14:53:00 GMT 2000


This fixes a few cases where rs6000.md was not SUBREG-safe; it would
generate SUBREGs of SUBREGs, which is bad.  The attached test exposes
the problems.

Bootstrapped & tested on powerpc-aix.
-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~/patches/cygnus/gcc-104400.patch===================
2000-08-25  Geoff Keating  <geoffk@cygnus.com>

	* config/rs6000/rs6000.md (movdi_internal64+5): Make SUBREG-safe
	by using gen_lowpart_common.
	(movdi_internal64+6): Likewise.

2000-08-25  Geoff Keating  <geoffk@cygnus.com>

	* gcc.c-torture/compile/20000825-1.c: New test.

Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.97
diff -p -u -u -p -r1.97 rs6000.md
--- gcc/config/rs6000/rs6000.md	2000/08/08 18:50:14	1.97
+++ gcc/config/rs6000/rs6000.md	2000/08/25 19:40:56
@@ -8087,9 +8087,12 @@
   [(set (match_dup 0)
 	(match_dup 2))
    (set (match_dup 0)
-	(zero_extend:DI (subreg:SI (match_dup 0) 0)))]
+	(zero_extend:DI (match_dup 3)))]
   "
-{ operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); }")
+{ 
+  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); 
+  operands[3] = gen_lowpart_common (SImode, operands[0]);
+}")
 
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -8102,12 +8105,13 @@
   [(set (match_dup 0)
 	(match_dup 2))
    (set (match_dup 0)
-	(zero_extend:DI (subreg:SI (match_dup 0) 0)))]
+	(zero_extend:DI (match_dup 3)))]
   "
 {
 #if HOST_BITS_PER_WIDE_INT != 32
-operands[2] = GEN_INT ((INTVAL (operands[1]) << 32) >> 32);
+  operands[2] = GEN_INT ((INTVAL (operands[1]) << 32) >> 32);
 #endif
+  operands[3] = gen_lowpart_common (SImode, operands[0]);
 }")
 
 ;; 32-bit value in upper half of doubleword
Index: testsuite/gcc.c-torture/compile/20000825-1.c
===================================================================
RCS file: 20000825-1.c
diff -N 20000825-1.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.c-torture/compile/20000825-1.c	Fri Aug 25 12:43:23 2000
@@ -0,0 +1,31 @@
+typedef signed int      s32;
+typedef signed long     s64;
+typedef unsigned int    u32;
+typedef unsigned long   u64;
+
+extern __inline__ u32 foobar(int logmask)
+{
+        u32 ret = ~(1 << logmask);      // fails
+        // s32 ret = ~(1 << logmask);   // ok
+        // u64 ret = ~(1 << logmask);   // ok
+        // s64 ret = ~(1 << logmask);   // ok
+        return ret;
+}
+
+// This procedure compiles fine...
+u32 good(u32 var)
+{
+        var = foobar(0);
+        return var;
+}
+
+// This procedure does not compile...
+// Same as above, but formal parameter is a pointer
+// Both good() and fails() compile ok if we choose
+// a different type for "ret" in foobar().
+u32 fails(u32 *var)
+{
+        *var = foobar(0);
+        return *var;
+}
+
============================================================


More information about the Gcc-patches mailing list