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 7d153d2..e0d1c48 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 6420e27..596b1bf 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 d23181c..7ebc616 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);