Hi!

OImode/XImode on i?86/x86_64 are not <= MAX_BITSIZE_MODE_ANY_INT, because
they are never used for integer arithmetics (and there is no way
to represent all their values in RTL if not using CONST_WIDE_INT).
As the following testcase shows, simplify_immed_subreg can be called
with such modes though, e.g. trying to forward propagate a CONST_VECTOR
(i?86/x86_64 handles all zeros and all ones as CONST_VECTORs that can appear
in the IL directly) into a SUBREG_REG.
The following patch instead of ICE handles the most common cases (all 0
and all 1 CONST_VECTORs) and returns NULL otherwise.

Before wide-int got merged, the testcase worked, though the code didn't
bother checking anything, just created 0 or constm1_rtx for the two cases
that could happen and if something else appeared, could just return what
matched low TImode (or DImode for -m32).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2014-11-18  Jakub Jelinek  <ja...@redhat.com>

        PR target/63910
        * simplify-rtx.c (simplify_immed_subreg): For integer modes
        wider than MAX_BITSIZE_MODE_ANY_INT, handle all zeros and all ones
        and for other values return NULL_RTX.

        * gcc.target/i386/pr63910.c: New test.

--- gcc/simplify-rtx.c.jj       2014-11-11 00:06:19.000000000 +0100
+++ gcc/simplify-rtx.c  2014-11-18 10:17:01.198668555 +0100
@@ -5505,6 +5505,21 @@ simplify_immed_subreg (machine_mode oute
            HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / 
HOST_BITS_PER_WIDE_INT];
            wide_int r;
 
+           if (GET_MODE_PRECISION (outer_submode) > MAX_BITSIZE_MODE_ANY_INT)
+             {
+               /* Handle just all zeros and all ones CONST_VECTORs in
+                  this case.  */
+               if ((vp[0] & value_mask) == 0)
+                 elems[elem] = const0_rtx;
+               else if ((vp[0] & value_mask) == value_mask)
+                 elems[elem] = constm1_rtx;
+               else
+                 return NULL_RTX;
+               for (i = value_bit; i < elem_bitsize; i += value_bit)
+                 if ((vp[i / value_bit] & value_mask) != (vp[0] & value_mask))
+                   return NULL_RTX;
+               break;
+             }
            for (u = 0; u < units; u++)
              {
                unsigned HOST_WIDE_INT buf = 0;
@@ -5516,8 +5531,6 @@ simplify_immed_subreg (machine_mode oute
                tmp[u] = buf;
                base += HOST_BITS_PER_WIDE_INT;
              }
-           gcc_assert (GET_MODE_PRECISION (outer_submode)
-                       <= MAX_BITSIZE_MODE_ANY_INT);
            r = wide_int::from_array (tmp, units,
                                      GET_MODE_PRECISION (outer_submode));
            elems[elem] = immed_wide_int_const (r, outer_submode);
--- gcc/testsuite/gcc.target/i386/pr63910.c.jj  2014-11-18 10:12:24.282659318 
+0100
+++ gcc/testsuite/gcc.target/i386/pr63910.c     2014-11-18 10:12:00.000000000 
+0100
@@ -0,0 +1,12 @@
+/* PR target/63910 */
+/* { dg-do compile } */
+/* { dg-options "-O -mstringop-strategy=vector_loop -mavx512f" } */
+
+extern void bar (float *c);
+
+void
+foo (void)
+{
+  float c[1024] = { };
+  bar (c);
+}

        Jakub

Reply via email to