In the case that we are eliminating the load instruction, we use zero_extend
for the initialization of the base register for the zero-offset store.
This causes issues when the store and the load use the same mode,
as we are trying to generate a zero_extend with the same inner and
outer modes.
This patch fixes the issue by zero-extending the value stored in the
base register only when the load's mode is wider than the store's mode.
PR rtl-optimization/119160
gcc/ChangeLog:
* avoid-store-forwarding.cc (process_store_forwarding):
Zero-extend the value stored in the base register, in case
of load-elimination, only when the mode of the destination
is wider.
gcc/testsuite/ChangeLog:
* gcc.dg/pr119160.c: New test.
{
start_sequence ();
- rtx ext0 = gen_rtx_ZERO_EXTEND (GET_MODE (dest), it->mov_reg);
- if (ext0)
+ machine_mode dest_mode = GET_MODE (dest);
+ rtx base_reg = it->mov_reg;
+ if (known_gt (GET_MODE_BITSIZE (dest_mode),
+ GET_MODE_BITSIZE (GET_MODE (it->mov_reg))))
+ base_reg = gen_rtx_ZERO_EXTEND (dest_mode, it->mov_reg);
+
+ if (base_reg)
{
- rtx_insn *move0 = emit_move_insn (dest, ext0);
+ rtx_insn *move0 = emit_move_insn (dest, base_reg);
if (recog_memoized (move0) >= 0)
{
insns = get_insns ();
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -finstrument-functions-once -favoid-store-forwarding -fnon-call-exceptions -fschedule-insns -mgeneral-regs-only -Wno-psabi" } */
+
+typedef __attribute__((__vector_size__ (32))) int V;
+
+void
+foo (V v, V, V, V *r)
+{
+ V u = (V){} + v[0];
+ *r = u;
+}
+
+__attribute__((__noipa__)) void
+bar(int x)
+{
+ if (x != 2) __builtin_abort();
+}
+
+int
+main ()
+{
+ V x;
+ foo ((V){ 2, 3 }, (V){ }, (V){ }, &x);
+ for (unsigned i = 0; i < sizeof(x)/sizeof(x[0]); i++)
+ bar(x[i]);
+}
\ No newline at end of file