From b8e444f4381296174b6098aad12de229bfb1f887 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 20 Aug 2009 00:51:20 +0200 Subject: [PATCH] re PR middle-end/41123 (ICE in expand_expr_real_1) PR middle-end/41123 * expr.c (expand_expr_real_1) : Handle all kinds of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT. * gcc.dg/pr41123.c: New test. From-SVN: r150946 --- gcc/ChangeLog | 6 +++++ gcc/expr.c | 37 +++++++++++++++++++-------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/pr41123.c | 46 ++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr41123.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76f606046f8..3a6e2619974 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2009-08-19 Jakub Jelinek + + PR middle-end/41123 + * expr.c (expand_expr_real_1) : Handle all kinds + of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT. + 2009-08-19 Jason Merrill * doc/invoke.texi (C++ Dialect Options): Note change of minimum diff --git a/gcc/expr.c b/gcc/expr.c index 08c747ecffb..6805cdc6e6d 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7871,6 +7871,33 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, || 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) @@ -7944,16 +7971,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a29294938c4..993f2c3bfec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-08-19 Jakub Jelinek + + PR middle-end/41123 + * gcc.dg/pr41123.c: New test. + 2009-08-19 Jason Merrill PR c++/41120 diff --git a/gcc/testsuite/gcc.dg/pr41123.c b/gcc/testsuite/gcc.dg/pr41123.c new file mode 100644 index 00000000000..076edb46ee5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr41123.c @@ -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; +}