Hi! We ICE on the following testcase, because lower-subreg sees only SFmode subregs of a multi-word pseudo (V4SFmode) and decides to decompose it. Decomposition is done through replacing the multi-word pseudo with a concat of word-sized integer pseudos; unfortunately, we don't allow SFmode subregs of DImode inner regs (or any other mix of floating and integral mode where the sizes aren't the same), so we ICE later on during the lower-subreg pass.
The following patch punts in that case, unless the size is the same (i.e. allows SFmode on 32-bit word targets or DFmode on 64-bit word ones). Bootstrapped/regtested on x86_64-linux and i686-linux plus tested with a cross to s390x-linux on the testcase. Ok for trunk? BTW, wonder if we also shouldn't punt in case the inner mode is vector mode, I don't think it is desirable to undo vectorization this way (but would like to try that as a separate patch and gather some statistics). For this patch I've gathered statistics too, on x86_64/i686-linux this patch changes behavior in a couple of 64-bit gcc.target/i386/ tests where the modes in all cases were SFmode (outer) and V4SFmode (inner), but it seems at least on avx5124fmadd-v4fnmaddss-1.c I've looked at we in the end didn't decide to decompose it anyway (perhaps some other non-subreg use). 2018-05-29 Jakub Jelinek <ja...@redhat.com> PR target/85945 * lower-subreg.c (find_decomposable_subregs): Don't decompose float subregs of multi-word pseudos unless the float mode has word size. * gcc.c-torture/compile/pr85945.c: New test. --- gcc/lower-subreg.c.jj 2018-01-04 00:43:17.209703103 +0100 +++ gcc/lower-subreg.c 2018-05-28 16:52:48.078871856 +0200 @@ -497,7 +497,16 @@ find_decomposable_subregs (rtx *loc, enu were the same number and size of pieces. Hopefully this doesn't happen much. */ - if (outer_words == 1 && inner_words > 1) + if (outer_words == 1 + && inner_words > 1 + /* Don't allow to decompose floating point subregs of + multi-word pseudos if the floating point mode does + not have word size, because otherwise we'd generate + a subreg with that floating mode from a different + sized integral pseudo which is not allowed by + validate_subreg. */ + && (!FLOAT_MODE_P (GET_MODE (x)) + || outer_size == UNITS_PER_WORD)) { bitmap_set_bit (decomposable_context, regno); iter.skip_subrtxes (); --- gcc/testsuite/gcc.c-torture/compile/pr85945.c.jj 2018-05-28 18:26:28.043765766 +0200 +++ gcc/testsuite/gcc.c-torture/compile/pr85945.c 2018-05-28 18:24:23.274594221 +0200 @@ -0,0 +1,16 @@ +/* PR target/85945 */ + +typedef float V __attribute__((vector_size(16))); +union U { V v; float f[4]; }; +int f; +float g[4]; + +void +foo (void) +{ + V d; + union U i; + i.v = d; + for (f = 0; f < 4; f++) + g[f] = i.f[f]; +} Jakub