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