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.
Other CFG code already handles DEBUG_INSNs at BB_END. Step backward
over trailing debug instructions and notes before inspecting the USE so
that this decision does not depend on debug information.
Add a MIPS __RTL test that exercises the affected multi-register return
path directly.
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
instructions when locating the return-value USE.
gcc/testsuite/ChangeLog:
* gcc.dg/rtl/mips/combine-likely-spilled-retval.c: New test.
Signed-off-by: Yongqiang Tian <[email protected]>
---
gcc/combine.cc | 9 +++-
.../rtl/mips/combine-likely-spilled-retval.c | 49 +++++++++++++++++++
2 files changed, 57 insertions(+), 1 deletion(-)
create mode 100644
gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval.c
diff --git a/gcc/combine.cc b/gcc/combine.cc
index 429530816..fd108f5a8 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -2315,7 +2315,14 @@ 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. Step back so that this decision
+ does not depend on debug information. */
+ if (use && DEBUG_INSN_P (use))
+ use = prev_nonnote_nondebug_insn_bb (use);
+ if (!use
+ || !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.c
b/gcc/testsuite/gcc.dg/rtl/mips/combine-likely-spilled-retval.c
new file mode 100644
index 000000000..d9cb86e40
--- /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" }
} */
--
2.34.1