https://gcc.gnu.org/g:517d45af94f98f2c8c8bdf5231aa662c82b46c13

commit r17-1375-g517d45af94f98f2c8c8bdf5231aa662c82b46c13
Author: Konstantinos Eleftheriou <[email protected]>
Date:   Tue Mar 31 05:12:33 2026 -0700

    avoid-store-forwarding: Re-apply extension after bit insert sequence 
[PR124713]
    
    The avoid-store-forwarding pass loses SIGN_EXTEND/ZERO_EXTEND
    semantics when the forwarding target is an extending load that is
    not fully eliminated.  The bit-field insert operates on the
    full-width destination register, but does not re-apply the
    extension, leaving stale upper bits from the original load.
    
    Fix by emitting the corresponding extension after the bit insert
    sequence for non-eliminated extending loads, mirroring what the
    load-elimination path already does.
    
            PR rtl-optimization/124713
    
    gcc/ChangeLog:
    
            * avoid-store-forwarding.cc (process_store_forwarding): Re-apply
            SIGN_EXTEND/ZERO_EXTEND after bit insert sequence when the load is
            not eliminated.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/pr124713.c: New test.

Diff:
---
 gcc/avoid-store-forwarding.cc               | 30 +++++++++++++++++++++--------
 gcc/testsuite/gcc.target/aarch64/pr124713.c | 24 +++++++++++++++++++++++
 2 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index bb015681c458..67abd2e37bd6 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -420,20 +420,34 @@ process_store_forwarding (vec<store_fwd_info> &stores, 
rtx_insn *load_insn,
       stores.ordered_remove (move_to_front);
     }
 
-  if (load_elim)
+  machine_mode outer_mode = GET_MODE (SET_DEST (load));
+  if (load_elim || outer_mode != load_mem_mode)
     {
-      machine_mode outer_mode = GET_MODE (SET_DEST (load));
-      rtx load_move;
-      rtx load_value = dest;
+      /* If the load is being eliminated, emit a move (with extension if
+        needed) from the temp register to the original load destination.
+        Otherwise, if the load has SIGN_EXTEND or ZERO_EXTEND wrapping
+        the MEM, the bit insert sequence may have modified bits that
+        affect the extension (e.g. the sign bit), so re-apply it.  */
+      rtx move_src;
       if (outer_mode != load_mem_mode)
        {
-         load_value = simplify_gen_unary (GET_CODE (SET_SRC (load)),
-                                          outer_mode, dest, load_mem_mode);
+         rtx ext_op = dest;
+         if (!load_elim)
+           {
+             ext_op = lowpart_subreg (load_mem_mode, dest, outer_mode);
+             if (!ext_op)
+               return false;
+           }
+         move_src = simplify_gen_unary (GET_CODE (SET_SRC (load)),
+                                        outer_mode, ext_op, load_mem_mode);
        }
-      load_move = gen_rtx_SET (SET_DEST (load), load_value);
+      else
+       move_src = dest;
+
+      rtx move = gen_rtx_SET (SET_DEST (load), move_src);
 
       start_sequence ();
-      rtx_insn *insn = emit_insn (load_move);
+      rtx_insn *insn = emit_insn (move);
       rtx_insn *seq = end_sequence ();
 
       if (recog_memoized (insn) < 0)
diff --git a/gcc/testsuite/gcc.target/aarch64/pr124713.c 
b/gcc/testsuite/gcc.target/aarch64/pr124713.c
new file mode 100644
index 000000000000..798cf1fa9583
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr124713.c
@@ -0,0 +1,24 @@
+/* PR rtl-optimization/124713 */
+/* { dg-do run } */
+/* { dg-require-effective-target aarch64_little_endian } */
+/* { dg-options "-Og -favoid-store-forwarding -fwrapv" } */
+
+int x;
+long y;
+
+__attribute__((noipa)) long
+foo (short m)
+{
+  short b = m * 13;
+  __builtin_memset (1 + (char *) &b, x, 1);
+  long c = *(long *) __builtin_memset (&y, x, 4);
+  return c + b;
+}
+
+int
+main ()
+{
+  long x = foo (3840);
+  if (x)
+    __builtin_abort ();
+}

Reply via email to