From 039fc560d9c42de7947e47b1515641de8f672296 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 30 May 2017 09:36:52 +0200 Subject: [PATCH] backport: re PR rtl-optimization/77919 (ICE converting DC to V2DF mode) Backported from mainline 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. * g++.dg/torture/pr77919-2.C: New test. From-SVN: r248619 --- gcc/ChangeLog | 8 ++++++ gcc/expr.c | 31 ++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/torture/pr77919-2.C | 10 ++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr77919-2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2804651add67..c2642468ce02 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,14 @@ 2017-05-30 Jakub Jelinek Backported from mainline + 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-28 Jakub Jelinek PR rtl-optimization/77919 diff --git a/gcc/expr.c b/gcc/expr.c index bfb7992290df..e92d781e3949 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d060cbb678a5..875d4f6913d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2017-05-30 Jakub Jelinek Backported from mainline + 2016-10-29 Jakub Jelinek + + PR rtl-optimization/77919 + * g++.dg/torture/pr77919-2.C: New test. + 2016-10-28 Jakub Jelinek 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 index 000000000000..d61e704cb44a --- /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.47.2