re PR rtl-optimization/77919 (ICE converting DC to V2DF mode)
authorJakub Jelinek <jakub@redhat.com>
Sat, 29 Oct 2016 20:22:36 +0000 (22:22 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 29 Oct 2016 20:22:36 +0000 (22:22 +0200)
PR rtl-optimization/77919
* expr.c (expand_expr_real_1) <normal_inner_ref>: Only avoid forcing
into memory if both modes are complex and their inner modes have the
same precision.  If the two modes are different complex modes, convert
each part separately and generate a new CONCAT.

* g++.dg/torture/pr77919-2.C: New test.

From-SVN: r241681

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr77919-2.C [new file with mode: 0644]

index 7d153d27f3714e3e094ff029d1076b6f60eb9d6f..e0d1c4860dcdacab5a8504230dcd6c344c6a3fc0 100644 (file)
@@ -1,3 +1,11 @@
+2016-10-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/77919
+       * expr.c (expand_expr_real_1) <normal_inner_ref>: Only avoid forcing
+       into memory if both modes are complex and their inner modes have the
+       same precision.  If the two modes are different complex modes, convert
+       each part separately and generate a new CONCAT.
+
 2016-10-29  John David Anglin  <danglin@gcc.gnu.org>
 
        * config/pa/pa64-hpux.h (FINI_SECTION_ASM_OP): Define to null string.
index 6420e278f3d198e2ef1b122e832b87c0f816b1d5..596b1bf82277a667a785c2b279312cd5334cce7e 100644 (file)
@@ -10422,10 +10422,35 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
          {
            if (bitpos == 0
                && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
-               && COMPLEX_MODE_P (mode1))
+               && COMPLEX_MODE_P (mode1)
+               && COMPLEX_MODE_P (GET_MODE (op0))
+               && (GET_MODE_PRECISION (GET_MODE_INNER (mode1))
+                   == GET_MODE_PRECISION (GET_MODE_INNER (GET_MODE (op0)))))
              {
                if (reversep)
                  op0 = flip_storage_order (GET_MODE (op0), op0);
+               if (mode1 != GET_MODE (op0))
+                 {
+                   rtx parts[2];
+                   for (int i = 0; i < 2; i++)
+                     {
+                       rtx op = read_complex_part (op0, i != 0);
+                       if (GET_CODE (op) == SUBREG)
+                         op = force_reg (GET_MODE (op), op);
+                       rtx temp = gen_lowpart_common (GET_MODE_INNER (mode1),
+                                                      op);
+                       if (temp)
+                         op = temp;
+                       else
+                         {
+                           if (!REG_P (op) && !MEM_P (op))
+                             op = force_reg (GET_MODE (op), op);
+                           op = gen_lowpart (GET_MODE_INNER (mode1), op);
+                         }
+                       parts[i] = op;
+                     }
+                   op0 = gen_rtx_CONCAT (mode1, parts[0], parts[1]);
+                 }
                return op0;
              }
            if (bitpos == 0
index d23181c359298567b2419e6b27f722e168a31507..7ebc61642d2d7828fc8f9e2908029ca5c96f81cd 100644 (file)
@@ -1,5 +1,8 @@
 2016-10-29  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/77919
+       * g++.dg/torture/pr77919-2.C: New test.
+
        PR target/78148
        * gcc.dg/pr78148.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/torture/pr77919-2.C b/gcc/testsuite/g++.dg/torture/pr77919-2.C
new file mode 100644 (file)
index 0000000..d61e704
--- /dev/null
@@ -0,0 +1,10 @@
+// PR rtl-optimization/77919
+// { dg-do compile }
+
+typedef _Complex long long B;
+struct A { A (double) {} _Complex double i; };
+typedef struct { B b; } C;
+struct D { D (const B &x) : b (x) {} B b; };
+static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; }
+static inline D baz (const A &x) { return foo ((double *) &x); }
+D b = baz (0);