re PR target/21101 (ICE: could not find a spill register on MMX intrinsics)
authorRichard Henderson <rth@redhat.com>
Sun, 24 Apr 2005 07:59:22 +0000 (00:59 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 24 Apr 2005 07:59:22 +0000 (00:59 -0700)
        PR target/21101
        * config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Move guts to ...
        * config/i386/i386.c (ix86_cannot_change_mode_class): ... here.
        Deny modes smaller than 4 bytes.
        * config/i386/i386-protos.h: Update.

From-SVN: r98650

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/testsuite/gcc.target/i386/pr21101.c [new file with mode: 0644]

index d4b9cf7..9f2ee99 100644 (file)
@@ -1,3 +1,11 @@
+2005-04-24  Richard Henderson  <rth@redhat.com>
+
+       PR target/21101
+       * config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Move guts to ...
+       * config/i386/i386.c (ix86_cannot_change_mode_class): ... here.
+       Deny modes smaller than 4 bytes.
+       * config/i386/i386-protos.h: Update.
+
 2005-04-24  Ralf Corsepius  <ralf.corsepius@rtems.org>
 
        * config.gcc (h8300-*-rtems*): Add h8300-*-rtemscoff*.
@@ -74,9 +82,9 @@
        
 2005-04-23  Richard Henderson  <rth@redhat.com>
 
-        PR rtl-opt/21102
-        * simplify-rtx.c (simplify_binary_operation): Fix mode check before
-        performing some integral scalar simplifications.
+       PR rtl-opt/21102
+       * simplify-rtx.c (simplify_binary_operation): Fix mode check before
+       performing some integral scalar simplifications.
 
 2005-04-23  Richard Henderson  <rth@redhat.com>
 
index 4834071..d8f15da 100644 (file)
@@ -187,6 +187,8 @@ extern int ix86_register_move_cost (enum machine_mode, enum reg_class,
                                    enum reg_class);
 extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
                                         enum machine_mode, int);
+extern bool ix86_cannot_change_mode_class (enum machine_mode,
+                                          enum machine_mode, enum reg_class);
 extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
 extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
 extern void emit_i387_cw_initialization (rtx, rtx, int);
index 5046cf5..110b233 100644 (file)
@@ -15297,6 +15297,41 @@ ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
   return false;
 }
 
+/* Return true if the registers in CLASS cannot represent the change from
+   modes FROM to TO.  */
+
+bool
+ix86_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
+                              enum reg_class class)
+{
+  if (from == to)
+    return false;
+
+  /* x87 registers can't do subreg at all, as all values are reformated
+     to extended precision.  */
+  if (MAYBE_FLOAT_CLASS_P (class))
+    return true;
+
+  if (MAYBE_SSE_CLASS_P (class) || MAYBE_MMX_CLASS_P (class))
+    {
+      /* Vector registers do not support QI or HImode loads.  If we don't
+        disallow a change to these modes, reload will assume it's ok to
+        drop the subreg from (subreg:SI (reg:HI 100) 0).  This affects
+        the vec_dupv4hi pattern.  */
+      if (GET_MODE_SIZE (from) < 4)
+       return true;
+
+      /* Vector registers do not support subreg with nonzero offsets, which
+        are otherwise valid for integer registers.  Since we can't see 
+        whether we have a nonzero offset from here, prohibit all
+         nonparadoxical subregs changing size.  */
+      if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from))
+       return true;
+    }
+
+  return false;
+}
+
 /* Return the cost of moving data from a register in class CLASS1 to
    one in class CLASS2.
 
index b58373f..fc0596b 100644 (file)
@@ -1338,19 +1338,10 @@ enum reg_class
    || ((CLASS) == FP_TOP_REG)                                          \
    || ((CLASS) == FP_SECOND_REG))
 
-/* Return a class of registers that cannot change FROM mode to TO mode.
-
-   x87 registers can't do subreg as all values are reformated to extended
-   precision.  XMM registers does not support with nonzero offsets equal
-   to 4, 8 and 12 otherwise valid for integer registers. Since we can't
-   determine these, prohibit all nonparadoxical subregs changing size.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)      \
-  (GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM)           \
-   ? reg_classes_intersect_p (FLOAT_SSE_REGS, (CLASS)) \
-     || MAYBE_MMX_CLASS_P (CLASS)                      \
-   : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)                \
-   ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
+/* Return a class of registers that cannot change FROM mode to TO mode.  */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  ix86_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
diff --git a/gcc/testsuite/gcc.target/i386/pr21101.c b/gcc/testsuite/gcc.target/i386/pr21101.c
new file mode 100644 (file)
index 0000000..104b08c
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -funroll-loops -march=nocona" } */
+
+#include <mmintrin.h>
+
+int W;
+void f()
+{
+  int j;
+  int B, C;
+  unsigned char* S;
+  __m64 *T = (__m64 *) &W;
+
+  for (j = 0; j < 16; j++, T++)
+  {
+    T[0] = T[1] = _mm_set1_pi8(*S);
+    S += W;
+  }
+
+  C = 3 * B;
+
+  __m64 E = _mm_set_pi16(3 * B, 3 * B, 3 * B, 5 * B);
+  __m64 G = _mm_set1_pi16(3 * B);
+
+  for (j = 0; j < 16; j++)
+  {
+    __m64 R = _mm_set1_pi16(B + j * C);
+    R = _m_paddw(R, E);
+    R = _m_paddw(R, G);
+    T[0] = _mm_srai_pi16(R, 3);
+  }
+}