https://gcc.gnu.org/g:0ab0aff01313b52b1d2fc9e50294724fb30fc1f9

commit r17-5496-g0ab0aff01313b52b1d2fc9e50294724fb30fc1f9
Author: Yongqiang Tian <[email protected]>
Date:   Thu Oct 22 21:37:28 2026 -0600

    [PATCH v2] combine: Ignore trailing debug insns when checking return values
    
    likely_spilled_retval_p uses BB_END to locate the USE of a
    multi-register return value.  With debug information, BB_END can be a
    DEBUG_INSN, causing the check to fail and allowing combine to merge into
    a return-register copy that it rejects without debug information.
    
    Use prev_nondebug_insn to ignore trailing debug insns while preserving
    the existing treatment of notes.  Skipping notes only when a debug insn
    follows them would introduce a compare-debug difference in the opposite
    direction.
    
    No null check is needed because BB_END is nonnull for the basic block
    being processed.  The backwards walk cannot leave the block: in cfgrtl
    mode, BB_HEAD is a non-debug NOTE_INSN_BASIC_BLOCK.
    
    Add one MIPS __RTL test for the original failure and another that places
    a NOTE_INSN_DELETED between the return-value USE and the debug insn.  The
    second test guards against skipping notes in the debug build.
    
    Bootstrapped and regression tested on x86_64-pc-linux-gnu.
    
    Also tested on mips-elf with an incremental GCC rebuild.  The two
    targeted RTL tests produced 8 expected passes and no failures.
    contrib/check_GNU_style.sh and git diff --check also passed.
    
    Assisted-by: OpenAI Codex 5.6 Sol, co-reviewed by Claude and Yongqiang Tian.
    
    gcc/ChangeLog:
    
            * combine.cc (likely_spilled_retval_p): Skip trailing debug insns
            when locating the return-value USE.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/rtl/mips/combine-likely-spilled-retval.c: New test.
            * gcc.dg/rtl/mips/combine-likely-spilled-retval-note.c: New test.
    
    Signed-off-by: Yongqiang Tian <[email protected]>

Diff:
---
 gcc/combine.cc                                     |  8 +++-
 .../rtl/mips/combine-likely-spilled-retval-note.c  | 47 +++++++++++++++++++++
 .../rtl/mips/combine-likely-spilled-retval.c       | 49 ++++++++++++++++++++++
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/gcc/combine.cc b/gcc/combine.cc
index c9daefc905c3..c57cd631b8b2 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -2315,7 +2315,13 @@ likely_spilled_retval_p (rtx_insn *insn)
   unsigned mask;
   struct likely_spilled_retval_info info;
 
-  if (!NONJUMP_INSN_P (use) || GET_CODE (PATTERN (use)) != USE || insn == use)
+  /* With -g, BB_END may be a DEBUG_INSN.  Ignore trailing debug
+     instructions without changing how notes are handled.  */
+  if (DEBUG_INSN_P (use))
+    use = prev_nondebug_insn (use);
+  if (!NONJUMP_INSN_P (use)
+      || GET_CODE (PATTERN (use)) != USE
+      || insn == use)
     return false;
   reg = XEXP (PATTERN (use), 0);
   if (!REG_P (reg) || !targetm.calls.function_value_regno_p (REGNO (reg)))
diff --git a/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval-note.c 
b/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval-note.c
new file mode 100644
index 000000000000..ec91c9b57749
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval-note.c
@@ -0,0 +1,47 @@
+/* { dg-do compile { target mips*-*-* } } */
+/* { dg-options "-O2 -g -mips1 -mabi=32 -mfix-r4000 
-fdump-rtl-combine-details" } */
+
+/* Verify that a trailing debug instruction does not cause the scan to skip
+   a note that it would retain without debug information.  */
+
+long long __RTL (startwith ("combine"))
+f (long long a, long long b)
+{
+(function "f"
+  (param "a"
+    (DECL_RTL (reg/v:DI <3> [ a ]))
+    (DECL_RTL_INCOMING (reg:DI $4 [ a ])))
+  (param "b"
+    (DECL_RTL (reg/v:DI <4> [ b ]))
+    (DECL_RTL_INCOMING (reg:DI $6 [ b ])))
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 8 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 19 (set (reg:SI <0> [ a+4 ])
+                     (reg:SI $5 [ a+4 ])))
+      (cinsn 21 (set (reg:SI <1> [ b+4 ])
+                     (reg:SI $7 [ b+4 ])))
+      (cnote 7 NOTE_INSN_FUNCTION_BEG)
+      (cinsn 10 (set (reg:DI <2>)
+                     (mult:DI
+                       (sign_extend:DI (reg:SI <0> [ a+4 ]))
+                       (sign_extend:DI (reg:SI <1> [ b+4 ])))))
+      (cinsn 15 (set (reg/i:DI $2)
+                     (reg:DI <2>)))
+      (cinsn 16 (use (reg/i:DI $2)))
+      (cnote 18 NOTE_INSN_DELETED)
+      (cdebug_insn 17 (debug_marker))
+      (edge-to exit (flags "FALLTHRU"))
+    )
+  )
+  (crtl
+    (return_rtx (reg/i:DI $2))
+  )
+)
+}
+
+/* The combine cost dump prints the BEGIN_STMT marker.  Check it so that the
+   other scans cannot pass because debug information was discarded.  */
+/* { dg-final { scan-rtl-dump "debug begin stmt marker" "combine" } } */
+/* { dg-final { scan-rtl-dump "allowing combination of insns 10 and 15" 
"combine" } } */
diff --git a/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval.c 
b/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval.c
new file mode 100644
index 000000000000..d9cb86e40a98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval.c
@@ -0,0 +1,49 @@
+/* { dg-do compile { target mips*-*-* } } */
+/* { dg-options "-O2 -g -mips1 -mabi=32 -mfix-r4000 
-fdump-rtl-combine-details" } */
+
+/* Verify that a debug instruction after the return-value USE does not allow
+   combine to form a multi-register return value in a likely-spilled register
+   class.  */
+
+long long __RTL (startwith ("combine"))
+f (long long a, long long b)
+{
+(function "f"
+  (param "a"
+    (DECL_RTL (reg/v:DI <3> [ a ]))
+    (DECL_RTL_INCOMING (reg:DI $4 [ a ])))
+  (param "b"
+    (DECL_RTL (reg/v:DI <4> [ b ]))
+    (DECL_RTL_INCOMING (reg:DI $6 [ b ])))
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 8 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 19 (set (reg:SI <0> [ a+4 ])
+                     (reg:SI $5 [ a+4 ])))
+      (cinsn 21 (set (reg:SI <1> [ b+4 ])
+                     (reg:SI $7 [ b+4 ])))
+      (cnote 7 NOTE_INSN_FUNCTION_BEG)
+      (cinsn 10 (set (reg:DI <2>)
+                     (mult:DI
+                       (sign_extend:DI (reg:SI <0> [ a+4 ]))
+                       (sign_extend:DI (reg:SI <1> [ b+4 ])))))
+      (cinsn 15 (set (reg/i:DI $2)
+                     (reg:DI <2>)))
+      (cinsn 16 (use (reg/i:DI $2)))
+      (cdebug_insn 17 (debug_marker))
+      (edge-to exit (flags "FALLTHRU"))
+    )
+  )
+  (crtl
+    (return_rtx (reg/i:DI $2))
+  )
+)
+}
+
+/* The combine cost dump prints the BEGIN_STMT marker.  Check it so that the
+   other scans cannot pass because debug information was discarded.  */
+/* { dg-final { scan-rtl-dump "debug begin stmt marker" "combine" } } */
+/* { dg-final { scan-rtl-dump "\\(insn 10 " "combine" } } */
+/* { dg-final { scan-rtl-dump "\\(insn 15 " "combine" } } */
+/* { dg-final { scan-rtl-dump-not "combination of insns 10 and 15" "combine" } 
} */

Reply via email to