During the base register initialization, when we are eliminating the load instruction, we were calling `emit_move_insn` on registers of the same size but of different mode in some cases, causing an ICE.
This patch fixes this, by adding a check for the modes to match before calling `emit_move_insn`. Bootstrapped/regtested on AArch64 and x86_64. PR rtl-optimization/119884 gcc/ChangeLog: * avoid-store-forwarding.cc (process_store_forwarding): Added check to ensure that the register modes match before calling `emit_move_insn`. gcc/testsuite/ChangeLog: * gcc.target/i386/pr119884.c: New test. --- gcc/avoid-store-forwarding.cc | 3 ++- gcc/testsuite/gcc.target/i386/pr119884.c | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr119884.c diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc index ded8d7e596e0..aec05c22ac37 100644 --- a/gcc/avoid-store-forwarding.cc +++ b/gcc/avoid-store-forwarding.cc @@ -244,7 +244,8 @@ process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn, GET_MODE_BITSIZE (GET_MODE (it->mov_reg)))) base_reg = gen_rtx_ZERO_EXTEND (dest_mode, it->mov_reg); - if (base_reg) + /* Generate a move instruction, only when the modes match. */ + if (base_reg && dest_mode == GET_MODE (base_reg)) { rtx_insn *move0 = emit_move_insn (dest, base_reg); if (recog_memoized (move0) >= 0) diff --git a/gcc/testsuite/gcc.target/i386/pr119884.c b/gcc/testsuite/gcc.target/i386/pr119884.c new file mode 100644 index 000000000000..34d5b689244d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr119884.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-dse -favoid-store-forwarding" } */ + +typedef __attribute__((__vector_size__(64))) char V; +char c; +V v; + +char +foo() +{ + v *= c; + return v[0]; +} \ No newline at end of file -- 2.49.0