From 205b9ed14e15672ea5496d48430f954d12b089a3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 29 Oct 2016 22:22:36 +0200 Subject: [PATCH] re PR rtl-optimization/77919 (ICE converting DC to V2DF mode) PR rtl-optimization/77919 * expr.c (expand_expr_real_1) : 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 | 8 +++++++ gcc/expr.c | 27 +++++++++++++++++++++++- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/g++.dg/torture/pr77919-2.C | 10 +++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr77919-2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d153d27f37..e0d1c4860dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-10-29 Jakub Jelinek + + PR rtl-optimization/77919 + * expr.c (expand_expr_real_1) : 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 * config/pa/pa64-hpux.h (FINI_SECTION_ASM_OP): Define to null string. diff --git a/gcc/expr.c b/gcc/expr.c index 6420e278f3d..596b1bf8227 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 d23181c3592..7ebc61642d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2016-10-29 Jakub Jelinek + 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 00000000000..d61e704cb44 --- /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); -- 2.30.2