re PR target/6043 (IICE on ia64 for Blitz config test for C++ complex math)
authorJakub Jelinek <jakub@redhat.com>
Mon, 25 Mar 2002 11:34:11 +0000 (12:34 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 25 Mar 2002 11:34:11 +0000 (12:34 +0100)
PR target/6043
* expr.c (emit_group_store): Handle storing into CONCAT.

* g++.dg/opt/conj2.C: New test.

From-SVN: r51311

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/conj2.C [new file with mode: 0644]

index 9998544ca26a7ffc9aeed23775dec01295b21185..613342afeb32781de3a4196d69a1070cc7ab34d9 100644 (file)
@@ -1,3 +1,8 @@
+2002-03-25  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/6043
+       * expr.c (emit_group_store): Handle storing into CONCAT.
+
 2002-03-25  Jakub Jelinek  <jakub@redhat.com>
 
        * regrename.c (build_def_use): Share RTL between MATCH_OPERATOR and
index 3913ebd76a08cccf429a2386878bdfc082555948..e6821d5f28f982249c584f747a89af0bff0ff554 100644 (file)
@@ -2113,6 +2113,7 @@ emit_group_store (orig_dst, src, ssize)
       HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
       enum machine_mode mode = GET_MODE (tmps[i]);
       unsigned int bytelen = GET_MODE_SIZE (mode);
+      rtx dest = dst;
 
       /* Handle trailing fragments that run over the size of the struct.  */
       if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
@@ -2126,14 +2127,27 @@ emit_group_store (orig_dst, src, ssize)
          bytelen = ssize - bytepos;
        }
 
+      if (GET_CODE (dst) == CONCAT)
+       {
+         if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
+           dest = XEXP (dst, 0);
+         else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
+           {
+             bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
+             dest = XEXP (dst, 1);
+           }
+         else
+           abort ();
+       }
+
       /* Optimize the access just a bit.  */
-      if (GET_CODE (dst) == MEM
-         && MEM_ALIGN (dst) >= GET_MODE_ALIGNMENT (mode)
+      if (GET_CODE (dest) == MEM
+         && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
-       emit_move_insn (adjust_address (dst, mode, bytepos), tmps[i]);
+       emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
       else
-       store_bit_field (dst, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
+       store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
                         mode, tmps[i], ssize);
     }
 
index 0ec9af500bb95eb74f4cd21ccd8c6cde404e29b8..8a22162ec6648bb1ff569a72cf2e5fc7bc5c07be 100644 (file)
@@ -2,6 +2,8 @@
 
        * gcc.c-torture/compile/20020323-1.c: New test.
 
+       * g++.dg/opt/conj2.C: New test.
+
 2002-03-24  Richard Henderson  <rth@redhat.com>
 
        * gcc.dg/weak-1.c: Use -fno-common.
diff --git a/gcc/testsuite/g++.dg/opt/conj2.C b/gcc/testsuite/g++.dg/opt/conj2.C
new file mode 100644 (file)
index 0000000..25e832a
--- /dev/null
@@ -0,0 +1,23 @@
+// PR target/6043
+// This testcase ICEd on IA-64 because emit_group_store
+// did not handle loading CONCAT from register group
+// { dg-do compile }
+
+struct C
+{
+  C (double y, double z) { __real__ x = y; __imag__ x = z; }
+  double r () const { return __real__ x; }
+  double i () const { return __imag__ x; }
+  __complex__ double x;
+};
+
+inline C conj (const C& x)
+{
+  return C (x.r (), - x.i ());
+}
+
+void foo (void)
+{
+  C x (1.0, 1.0);
+  conj (x);
+}