OSDN Git Service

* expr.c (expand_assignment): Handle CONCAT both as a final
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Dec 2004 05:24:11 +0000 (05:24 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Dec 2004 05:24:11 +0000 (05:24 +0000)
        destination and as a middle point.

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

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

index 6c7d2a0..7e4bd4d 100644 (file)
@@ -1,3 +1,8 @@
+2004-12-01  Richard Henderson  <rth@redhat.com>
+
+       * expr.c (expand_assignment): Handle CONCAT both as a final
+       destination and as a middle point.
+
 2004-12-01  Jeff Law  <law@redhat.com>
 
         * tree.h (save_eptr, save_filt): Now file scoped statics.
index 4616f21..f16f82f 100644 (file)
@@ -3757,8 +3757,16 @@ expand_assignment (tree to, tree from)
       /* Handle expand_expr of a complex value returning a CONCAT.  */
       if (GET_CODE (to_rtx) == CONCAT)
        {
-         gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
-         result = store_expr (from, XEXP (to_rtx, bitpos != 0), false);
+         if (TREE_CODE (TREE_TYPE (from)) == COMPLEX_TYPE)
+           {
+             gcc_assert (bitpos == 0);
+             result = store_expr (from, to_rtx, false);
+           }
+         else
+           {
+             gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
+             result = store_expr (from, XEXP (to_rtx, bitpos != 0), false);
+           }
        }
       else
        {
diff --git a/gcc/testsuite/gcc.dg/complex-3.c b/gcc/testsuite/gcc.dg/complex-3.c
new file mode 100644 (file)
index 0000000..54ec82c
--- /dev/null
@@ -0,0 +1,25 @@
+/* Verify that rtl expansion cleanup doesn't get too aggressive about
+   code dealing with complex CONCATs.  */
+/* { dg-do run } */
+/* { dg-options "-O -fno-tree-sra" } */
+
+extern void abort (void);
+extern void exit (int);
+
+__complex__ float foo (void)
+{
+  __complex__ float f[1];
+  __real__ f[0] = 1;
+  __imag__ f[0] = 1;
+  f[0] = __builtin_conjf (f[0]);
+  return f[0];
+}
+
+int main (void)
+{
+  __complex__ double d[1];
+  d[0] = foo ();
+  if (__real__ d[0] != 1 || __imag__ d[0] != -1)
+    abort ();
+  exit (0);
+}