On Tue, 18 Nov 2014, Jakub Jelinek wrote: > 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.
So we have (subreg:OI (reg:V4DF ...) ...) for example? What do we end doing with that OI mode subreg? (why can't we simply use the V4DF one?) > 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? Looks ok to me. Not sure if the zero/all-ones case really happens that much to be worth special-casing - I think you could use fixed_wide_int<proper-size> and simply see if the result is representable in a CONST_INT/CONST_DOUBLE? Can you try if that works? It looks like the patch may be smaller for that. Thanks, Richard. > 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 > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284 (AG Nuernberg) Maxfeldstrasse 5, 90409 Nuernberg, Germany