aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-10-29 22:22:36 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-10-29 22:22:36 +0200
commit205b9ed14e15672ea5496d48430f954d12b089a3 (patch)
treeaa26aad337f9a7f61eff3d734f7a3f9e8de39d3d /gcc
parente421be7677f480f1ca5842c5a2a96c829fd47266 (diff)
downloadgcc-205b9ed14e15672ea5496d48430f954d12b089a3.zip
gcc-205b9ed14e15672ea5496d48430f954d12b089a3.tar.gz
gcc-205b9ed14e15672ea5496d48430f954d12b089a3.tar.bz2
re PR rtl-optimization/77919 (ICE converting DC to V2DF mode)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/expr.c27
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/torture/pr77919-2.C10
4 files changed, 47 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d153d2..e0d1c48 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/expr.c b/gcc/expr.c
index 6420e27..596b1bf 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d23181c..7ebc616 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d61e704
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr77919-2.C
@@ -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);