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