On Thu, 27 Oct 2016, Jakub Jelinek wrote: > Hi! > > The following testcase ICEs on x86_64-linux with -O1, the problem is > that we expand assignment from COMPONENT_REF of MEM_REF into a V4SImode > SSA_NAME. The MEM_REF has non-addressable DCmode var inside of it, and > type of a struct containing a single V4SImode element. > > The bug seems to be that if the op0 (i.e. get_inner_reference expanded) > is a CONCAT and we want a reference that covers all bits of the CONCAT, > we just short path it and return it immediately, rather than trying > to convert it to the requested mode. > > I've bootstrapped/regtested on x86_64-linux and i686-linux the following > patch, which takes the short path only if we want a complex mode. > The only place it makes a difference in both bootstraps/regtests was this > new testcase. > > Though, perhaps COMPLEX_MODE_P (mode1) is also wrong, if mode1 isn't > GET_MODE (op0), then we still will return something with unexpected mode > (e.g. DCmode vs. CDImode); I wonder if for such mismatches we shouldn't > just force_reg (convert_modes ()) each CONCAT operand separately and > create a new CONCAT. Do we have a guarantee that COMPLEX_MODE_P (GET_MODE > (op0)) > if op0 is CONCAT?
I think so. I'll leave the rest to people more familiar with RTL expansion -- generally I thought the callers of expand() have to deal with expansions that return a different mode? Richard. > 2016-10-27 Jakub Jelinek <ja...@redhat.com> > > PR rtl-optimization/77919 > * expr.c (expand_expr_real_1) <normal_inner_ref>: Force CONCAT into > MEM if mode1 is not a complex mode. > > * g++.dg/torture/pr77919.C: New test. > > --- gcc/expr.c.jj 2016-10-27 20:50:22.699586175 +0200 > +++ gcc/expr.c 2016-10-27 21:15:30.146309091 +0200 > @@ -10421,7 +10421,8 @@ expand_expr_real_1 (tree exp, rtx target > if (GET_CODE (op0) == CONCAT && !must_force_mem) > { > if (bitpos == 0 > - && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) > + && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)) > + && COMPLEX_MODE_P (mode1)) > { > if (reversep) > op0 = flip_storage_order (GET_MODE (op0), op0); > --- gcc/testsuite/g++.dg/torture/pr77919.C.jj 2016-10-27 21:15:19.883440139 > +0200 > +++ gcc/testsuite/g++.dg/torture/pr77919.C 2016-10-27 21:16:01.694906242 > +0200 > @@ -0,0 +1,11 @@ > +// PR rtl-optimization/77919 > +// { dg-do compile } > +// { dg-additional-options "-Wno-psabi" } > + > +struct A { A (double) {} _Complex double i; }; > +typedef int __attribute__ ((vector_size (16))) B; > +typedef struct { B b; } C; > +struct D { D (const B &x) : b (x) {} B b; }; > +static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; } > +static inline D baz (const A &x) { return foo ((double *) &x); } > +D b = baz (0); > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)