]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR rtl-optimization/77919 (ICE converting DC to V2DF mode)
authorJakub Jelinek <jakub@redhat.com>
Tue, 30 May 2017 07:36:52 +0000 (09:36 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 30 May 2017 07:36:52 +0000 (09:36 +0200)
Backported from mainline
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.

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

From-SVN: r248619

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

index 2804651add67164de271c170d254648449b9680e..c2642468ce0283a19681749994d0928ff0c2fe65 100644 (file)
@@ -1,6 +1,14 @@
 2017-05-30  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       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-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/77919
index bfb7992290df937d792d297391deec7f7b572190..e92d781e3949dc21fec2d76e05238ede04b4d529 100644 (file)
@@ -10198,8 +10198,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))
-             return op0;
+               && 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 (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
                && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
                && bitsize)
index d060cbb678a5082588a541a3b2cd0842d3e016a5..875d4f6913d39bbaacbfe87155ad623e616963d1 100644 (file)
@@ -1,6 +1,11 @@
 2017-05-30  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2016-10-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/77919
+       * g++.dg/torture/pr77919-2.C: New test.
+
        2016-10-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/77919
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);