[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