The testcase constructs a sequence of insns that are fully dead and yet (due to forced options) are not removed as such. This triggered a case where we would emit a meaningless reload for a to-be-deleted insn.
We can't delete the insns first because that might disrupt the iteration ranges. So this patch turns them into notes before the walk and then continues to delete them properly afterwards. Tested on aarch64-linux-gnu & pushed. Richard gcc/ PR target/113094 * config/aarch64/aarch64-early-ra.cc (apply_allocation): Stub out instructions that are going to be deleted before iterating over the rest. gcc/testsuite/ PR target/113094 * gcc.target/aarch64/pr113094.c: New test. --- gcc/config/aarch64/aarch64-early-ra.cc | 3 +++ gcc/testsuite/gcc.target/aarch64/pr113094.c | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr113094.c diff --git a/gcc/config/aarch64/aarch64-early-ra.cc b/gcc/config/aarch64/aarch64-early-ra.cc index 24415bd829c..5d2da3e1110 100644 --- a/gcc/config/aarch64/aarch64-early-ra.cc +++ b/gcc/config/aarch64/aarch64-early-ra.cc @@ -3210,6 +3210,9 @@ early_ra::maybe_convert_to_strided_access (rtx_insn *insn) void early_ra::apply_allocation () { + for (auto *insn : m_dead_insns) + set_insn_deleted (insn); + rtx_insn *prev; for (auto insn_range : m_insn_ranges) for (rtx_insn *insn = insn_range.first; diff --git a/gcc/testsuite/gcc.target/aarch64/pr113094.c b/gcc/testsuite/gcc.target/aarch64/pr113094.c new file mode 100644 index 00000000000..b79e1f744ed --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr113094.c @@ -0,0 +1,10 @@ +/* { dg-options "-fno-tree-dse -Ofast -fno-tree-coalesce-vars -fno-dce -fno-tree-dce" } */ + +struct TV4 { + __attribute__((vector_size(sizeof(int) * 4))) int v; +}; +void modify() { + struct TV4 __trans_tmp_1, temp; + temp.v[0] = temp.v[3] = 0; + __trans_tmp_1 = temp; +} -- 2.25.1