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)

Reply via email to