OSDN Git Service

PR middle-end/41123
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Aug 2009 22:51:20 +0000 (22:51 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Aug 2009 22:51:20 +0000 (22:51 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150946 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr41123.c [new file with mode: 0644]

index 76f6060..3a6e261 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2009-08-19  Jason Merrill  <jason@redhat.com>
 
        * doc/invoke.texi (C++ Dialect Options): Note change of minimum
index 08c747e..6805cdc 100644 (file)
@@ -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
index a292949..993f2c3 100644 (file)
@@ -1,3 +1,8 @@
+2009-08-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/41123
+       * gcc.dg/pr41123.c: New test.
+
 2009-08-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/41120
diff --git a/gcc/testsuite/gcc.dg/pr41123.c b/gcc/testsuite/gcc.dg/pr41123.c
new file mode 100644 (file)
index 0000000..076edb4
--- /dev/null
@@ -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;
+}