[PATCH] Fix ICE in expand_expr_real_1 on CONCAT (PR middle-end/41123)

Richard Guenther richard.guenther@gmail.com
Wed Aug 19 22:40:00 GMT 2009


On Wed, Aug 19, 2009 at 11:12 PM, Jakub Jelinek<jakub@redhat.com> wrote:
> Hi!
>
> GCC 4.4 ICEs on the following testcase on i686, due to VCE the tree
> optimizers create normal_inner_ref: case in expand_expr_real_1 is called
> with a CONCAT op0.  Before PR6177 this didn't handle CONCAT at all,
> afterwards only bitpos == 0 && bitsize == sizeof op0 has been handled.
> The following patch handles the easy cases (first or second part of the
> CONCAT) specially and for the rest just forces spilling it into memory.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux on the 4.4 branch.
> The testcase doesn't ICE on the trunk, supposedly because of SSA expansion,
> but IMHO it shouldn't hurt there either.
>
> Ok for trunk/4.4?

Ok.

Thanks,
Richard.

> 2009-08-19  Jakub Jelinek  <jakub@redhat.com>
>
>        PR middle-end/41123
>        * expr.c (expand_expr_real_1) <normal_inner_ref>: Handle all kinds
>        of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT.
>
>        * gcc.dg/pr41123.c: New test.
>
> --- gcc/expr.c.jj       2009-06-19 12:35:39.000000000 +0200
> +++ gcc/expr.c  2009-08-19 21:00:37.000000000 +0200
> @@ -7806,6 +7806,33 @@ expand_expr_real_1 (tree exp, rtx target
>                          || mode1 == BLKmode
>                          || bitpos + bitsize > GET_MODE_BITSIZE (mode2));
>
> +       /* Handle CONCAT first.  */
> +       if (GET_CODE (op0) == CONCAT && !must_force_mem)
> +         {
> +           if (bitpos == 0
> +               && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
> +             return op0;
> +           if (bitpos == 0
> +               && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
> +               && bitsize)
> +             {
> +               op0 = XEXP (op0, 0);
> +               mode2 = GET_MODE (op0);
> +             }
> +           else if (bitpos == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
> +                    && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 1)))
> +                    && bitpos
> +                    && bitsize)
> +             {
> +               op0 = XEXP (op0, 1);
> +               bitpos = 0;
> +               mode2 = GET_MODE (op0);
> +             }
> +           else
> +             /* Otherwise force into memory.  */
> +             must_force_mem = 1;
> +         }
> +
>        /* If this is a constant, put it in a register if it is a legitimate
>           constant and we don't need a memory reference.  */
>        if (CONSTANT_P (op0)
> @@ -7879,16 +7906,6 @@ expand_expr_real_1 (tree exp, rtx target
>            MEM_VOLATILE_P (op0) = 1;
>          }
>
> -       /* The following code doesn't handle CONCAT.
> -          Assume only bitpos == 0 can be used for CONCAT, due to
> -          one element arrays having the same mode as its element.  */
> -       if (GET_CODE (op0) == CONCAT)
> -         {
> -           gcc_assert (bitpos == 0
> -                       && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)));
> -           return op0;
> -         }
> -
>        /* In cases where an aligned union has an unaligned object
>           as a field, we might be extracting a BLKmode value from
>           an integer-mode (e.g., SImode) object.  Handle this case
> --- gcc/testsuite/gcc.dg/pr41123.c.jj   2009-08-19 21:06:05.000000000 +0200
> +++ gcc/testsuite/gcc.dg/pr41123.c      2009-08-19 21:06:45.000000000 +0200
> @@ -0,0 +1,46 @@
> +/* PR middle-end/41123 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-strict-aliasing" } */
> +
> +struct S { char a, b, c, d, e, f, g, h; };
> +struct T { int a, b; };
> +
> +struct S
> +f1 (float _Complex x)
> +{
> +  return *(struct S *) & x;
> +}
> +
> +int
> +f2 (float _Complex x)
> +{
> +  struct S f = f1 (x);
> +  return f.b;
> +}
> +
> +struct T
> +f3 (float _Complex x)
> +{
> +  return *(struct T *) & x;
> +}
> +
> +int
> +f4 (float _Complex x)
> +{
> +  struct T f = f3 (x);
> +  return f.a;
> +}
> +
> +int
> +f5 (float _Complex x)
> +{
> +  struct T f = f3 (x);
> +  return f.b;
> +}
> +
> +struct T
> +f6 (float _Complex x)
> +{
> +  struct T f = f3 (x);
> +  return f;
> +}
>
>        Jakub
>



More information about the Gcc-patches mailing list