When store forwarding is avoided without eliminating the load (the store
only partially covers it), the extension wrapping the load's MEM is
re-applied after the bit-insert sequence, reusing SET_DEST (load) as the
move destination. As the load insn is kept here, that rtx is now shared
between two insns. That is fine for a plain REG, but in the case that the
dest is a SUBREG, it must not be shared (verify_rtx_sharing ICEs).

Unshare the destination with copy_rtx when building the move.

Bootstrapped/regtested on AArch64, x86-64 and PowerPC.

        PR rtl-optimization/126434

gcc/ChangeLog:

        * avoid-store-forwarding.cc (process_store_forwarding): Unshare the
        load destination when building the re-extension move.

gcc/testsuite/ChangeLog:

        * gcc.dg/pr126434.c: New test.
---
 gcc/avoid-store-forwarding.cc   |  4 +++-
 gcc/testsuite/gcc.dg/pr126434.c | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr126434.c

diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index 67abd2e37bd6..141f96c3d848 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -444,7 +444,9 @@ process_store_forwarding (vec<store_fwd_info> &stores, 
rtx_insn *load_insn,
       else
        move_src = dest;
 
-      rtx move = gen_rtx_SET (SET_DEST (load), move_src);
+      /* In the non-elimination case the load insn is retained, so unshare
+        its destination to avoid sharing a SUBREG between two insns.  */
+      rtx move = gen_rtx_SET (copy_rtx (SET_DEST (load)), move_src);
 
       start_sequence ();
       rtx_insn *insn = emit_insn (move);
diff --git a/gcc/testsuite/gcc.dg/pr126434.c b/gcc/testsuite/gcc.dg/pr126434.c
new file mode 100644
index 000000000000..b039ad0dfee6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr126434.c
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/126434 */
+/* { dg-do compile } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-O1 -favoid-store-forwarding 
--param=store-forwarding-max-distance=146" } */
+
+/* The store partially covers the load, so the load is kept and its
+   zero-extension is re-applied over a SUBREG destination.  */
+
+unsigned x;
+__int128 y;
+
+void
+foo ()
+{
+  __builtin_memset (&x, 0, 2);
+  y &= x;
+}
+
-- 
2.52.0

Reply via email to