https://gcc.gnu.org/g:2fc25a21820001c67258d30f0960ac9cd0f268cf
commit r15-4951-g2fc25a21820001c67258d30f0960ac9cd0f268cf Author: Richard Biener <rguent...@suse.de> Date: Mon Nov 4 11:39:05 2024 +0100 middle-end/117433 - ICE with gimple BLKmode reg copy When we end up expanding a SSA name copy with BLKmode regs which can happen for vectors, possibly wrapped in a NOP-conversion or a PAREN_EXPR and we are not optimizing we can end up with two BLKmode MEMs that expand_gimple_stmt_1 doesn't properly handle when expanding, trying to emit_move_insn them. Looking at store_expr which what expand_gimple_stmt_1 is really doing reveals a lot of magic that's missing. It eventually falls back to emit_block_move (store_expr isn't exported), so this is what I ended up using here given I think we'll only have BLKmode "registers" for vectors. PR middle-end/117433 * cfgexpand.cc (expand_gimple_stmt_1): Use emit_block_move when moving temp to BLKmode target. * gcc.dg/pr117433.c: New testcase. Diff: --- gcc/cfgexpand.cc | 7 ++++++- gcc/testsuite/gcc.dg/pr117433.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index e35664cc93d8..f3a33ff9a07d 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -4068,8 +4068,13 @@ expand_gimple_stmt_1 (gimple *stmt) else { temp = force_operand (temp, target); - if (temp != target) + if (temp == target) + ; + else if (GET_MODE (target) != BLKmode) emit_move_insn (target, temp); + else + emit_block_move (target, temp, expr_size (lhs), + BLOCK_OP_NORMAL); } } } diff --git a/gcc/testsuite/gcc.dg/pr117433.c b/gcc/testsuite/gcc.dg/pr117433.c new file mode 100644 index 000000000000..1014c1ef3186 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr117433.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ + +__attribute__((__vector_size__ (sizeof (long unsigned) * 8))) long unsigned b; + +void __attribute__((noipa)) +foo () +{ + b += __builtin_assoc_barrier (b); +} + +int main() +{ + int i; + for (i = 0; i < 8; ++i) + b[i] = i; + foo (); + for (i = 0; i < 8; ++i) + if (b[i] != 2*i) + __builtin_abort (); + return 0; +}