Hi! On the following testcase we ICE in simplify_gen_subreg, when result has BLKmode and we want to convert it to some complex mode (e.g. DCmode or in theory XCmode or TCmode too). Such SUBREGs are invalid, but BLKmode can only live in memory and when it is a MEM, we don't really need to create a subreg, we can change_address and just load it as if it is a complex MEM.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-02-20 Jakub Jelinek <ja...@redhat.com> PR middle-end/89412 * expr.c (expand_assignment): If result is a MEM, use change_address instead of simplify_gen_subreg. * gcc.c-torture/compile/pr89412.c: New test. --- gcc/expr.c.jj 2019-02-16 12:19:37.602192262 +0100 +++ gcc/expr.c 2019-02-20 16:29:39.261497006 +0100 @@ -5211,9 +5211,13 @@ expand_assignment (tree to, tree from, b } else { - rtx from_rtx - = simplify_gen_subreg (to_mode, result, - TYPE_MODE (TREE_TYPE (from)), 0); + rtx from_rtx; + if (MEM_P (result)) + from_rtx = change_address (result, to_mode, NULL_RTX); + else + from_rtx + = simplify_gen_subreg (to_mode, result, + TYPE_MODE (TREE_TYPE (from)), 0); if (from_rtx) { emit_move_insn (XEXP (to_rtx, 0), --- gcc/testsuite/gcc.c-torture/compile/pr89412.c.jj 2019-02-20 16:30:47.722387639 +0100 +++ gcc/testsuite/gcc.c-torture/compile/pr89412.c 2019-02-20 16:31:29.288714080 +0100 @@ -0,0 +1,16 @@ +/* PR middle-end/89412 */ + +struct S { double a, b; } d; +int e; +double f; + +void +foo () +{ + _Complex double h; + while (e) + { + f = h; + *(struct S *) &h = d; + } +} Jakub