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.
---
 gcc/avoid-store-forwarding.cc   | 11 ++++++++---
 gcc/testsuite/gcc.dg/pr119160.c | 26 ++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr119160.c

diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index 34a7bba4043..ded8d7e596e 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -238,10 +238,15 @@ process_store_forwarding (vec<store_fwd_info> &stores, 
rtx_insn *load_insn,
        {
          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 ();
diff --git a/gcc/testsuite/gcc.dg/pr119160.c b/gcc/testsuite/gcc.dg/pr119160.c
new file mode 100644
index 00000000000..b4629a11d9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119160.c
@@ -0,0 +1,26 @@
+/* { 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
-- 
2.43.0

Reply via email to