From c1329fc84c8f7ee892070cb4aa514c4dbab70625 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 1 Jan 2018 00:51:14 +0100 Subject: [PATCH] re PR tree-optimization/83609 (ICE in read_complex_part at gcc/expr.c:3202) PR middle-end/83609 * expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg last argument when extracting from CONCAT. If either from_real or from_imag is NULL, use expansion through memory. If result is not a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg the parts directly to inner mode, if even that fails, use expansion through memory. * gcc.dg/pr83609.c: New test. * g++.dg/opt/pr83609.C: New test. From-SVN: r256052 --- gcc/ChangeLog | 8 ++++++++ gcc/expr.c | 33 +++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/opt/pr83609.C | 28 +++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr83609.c | 29 ++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr83609.C create mode 100644 gcc/testsuite/gcc.dg/pr83609.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 548bb17c10c..98073e8f942 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2018-01-01 Jakub Jelinek + PR middle-end/83609 + * expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg + last argument when extracting from CONCAT. If either from_real or + from_imag is NULL, use expansion through memory. If result is not + a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg + the parts directly to inner mode, if even that fails, use expansion + through memory. + PR middle-end/83623 * expmed.c (expand_shift_1): For 2-byte rotates by BITS_PER_UNIT, check for bswap in mode rather than HImode and use that in expand_unop diff --git a/gcc/expr.c b/gcc/expr.c index 4e7349e6494..0a735762e51 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5158,7 +5158,9 @@ expand_assignment (tree to, tree from, bool nontemporal) from_mode, 0); rtx from_imag = simplify_gen_subreg (to_mode, XEXP (result, 1), - from_mode, 1); + from_mode, 0); + if (!from_real || !from_imag) + goto concat_store_slow; emit_move_insn (XEXP (to_rtx, 0), from_real); emit_move_insn (XEXP (to_rtx, 1), from_imag); } @@ -5167,14 +5169,35 @@ expand_assignment (tree to, tree from, bool nontemporal) rtx from_rtx = simplify_gen_subreg (GET_MODE (to_rtx), result, TYPE_MODE (TREE_TYPE (from)), 0); - emit_move_insn (XEXP (to_rtx, 0), - read_complex_part (from_rtx, false)); - emit_move_insn (XEXP (to_rtx, 1), - read_complex_part (from_rtx, true)); + if (from_rtx) + { + emit_move_insn (XEXP (to_rtx, 0), + read_complex_part (from_rtx, false)); + emit_move_insn (XEXP (to_rtx, 1), + read_complex_part (from_rtx, true)); + } + else + { + machine_mode to_mode + = GET_MODE_INNER (GET_MODE (to_rtx)); + rtx from_real + = simplify_gen_subreg (to_mode, result, + TYPE_MODE (TREE_TYPE (from)), + 0); + rtx from_imag + = simplify_gen_subreg (to_mode, result, + TYPE_MODE (TREE_TYPE (from)), + GET_MODE_SIZE (to_mode)); + if (!from_real || !from_imag) + goto concat_store_slow; + emit_move_insn (XEXP (to_rtx, 0), from_real); + emit_move_insn (XEXP (to_rtx, 1), from_imag); + } } } else { + concat_store_slow:; rtx temp = assign_stack_temp (GET_MODE (to_rtx), GET_MODE_SIZE (GET_MODE (to_rtx))); write_complex_part (temp, XEXP (to_rtx, 0), false); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f89ae2e5496..59c9543de5f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2018-01-01 Jakub Jelinek + PR middle-end/83609 + * gcc.dg/pr83609.c: New test. + * g++.dg/opt/pr83609.C: New test. + PR middle-end/83623 * gcc.dg/pr83623.c: New test. diff --git a/gcc/testsuite/g++.dg/opt/pr83609.C b/gcc/testsuite/g++.dg/opt/pr83609.C new file mode 100644 index 00000000000..a43d2916d9d --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr83609.C @@ -0,0 +1,28 @@ +// PR middle-end/83609 +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop" } + +template class B; +template <> struct B +{ + float foo () { return __real__ b; } + _Complex float b; +}; + +void bar (int); + +template +void +baz () +{ + B h; + T *a = (T *) &h; + a[0] = a[1] = 6; + h.foo () ? void () : bar (7); +} + +int +main () +{ + baz (); +} diff --git a/gcc/testsuite/gcc.dg/pr83609.c b/gcc/testsuite/gcc.dg/pr83609.c new file mode 100644 index 00000000000..eac11fca936 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr83609.c @@ -0,0 +1,29 @@ +/* PR middle-end/83609 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fno-tree-pre -fno-code-hoisting" } */ + +#if __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_FLOAT__ +_Complex float +foo (void) +{ + _Complex float c; + *((unsigned long long *)&c) = 0x123456789abcdef0ULL; + return c; +} + +int +main () +{ + union { _Complex float c; unsigned long long l; } u; + u.c = foo (); + if (u.l != 0x123456789abcdef0ULL) + __builtin_abort (); + return 0; +} +#else +int +main () +{ + return 0; +} +#endif -- 2.30.2