[gcc r17-2790] avoid-store-forwarding: Unshare load dest when re-applying extension [PR126434]

Philipp Tomsich via Gcc-cvs <[email protected]> Wed, 29 Jul 2026 14:34:45 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:91663770f795fd02688c1da004337a1e7c94e810

commit r17-2790-g91663770f795fd02688c1da004337a1e7c94e810
Author: Konstantinos Eleftheriou <[email protected]>
Date:   Tue Jul 28 11:27:38 2026 +0200

    avoid-store-forwarding: Unshare load dest when re-applying extension [PR126434]
    
    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.

Diff:
---
 gcc/avoid-store-forwarding.cc   |  4 +++-
 gcc/testsuite/gcc.dg/pr126434.c | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

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;
+}
+