diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-01-01 00:51:14 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-01-01 00:51:14 +0100 |
commit | c1329fc84c8f7ee892070cb4aa514c4dbab70625 (patch) | |
tree | 99327b117c62805bc20eb2ed91a3f21228c802e6 /gcc/expr.c | |
parent | d235d09b7c86a2955bebdcb1991cd21758bcc21b (diff) | |
download | gcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.zip gcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.tar.gz gcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.tar.bz2 |
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
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 33 |
1 files changed, 28 insertions, 5 deletions
@@ -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); |