A DEBUG_INSN can retain a volatile MEM after the corresponding ordinary
instruction has been deleted.  Do not treat that non-executing payload as an
intervening volatile access in can_combine_p.

        PR rtl-optimization/127422

gcc/ChangeLog:

        * combine.cc (can_combine_p): Ignore debug instructions when scanning
        for intervening volatile references.

gcc/testsuite/ChangeLog:

        * gcc.dg/pr127422.c: New test.

Assisted-by: OpenAI Codex 5.6 Sol, co-reviewed by Claude and Yongqiang Tian.
Signed-off-by: Yongqiang Tian <[email protected]>
---
 gcc/combine.cc                  |  5 ++++-
 gcc/testsuite/gcc.dg/pr127422.c | 35 +++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr127422.c

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 35c6a529950..11427f5a920 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -2024,7 +2024,10 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn 
*pred ATTRIBUTE_UNUSED,
     : volatile_insn_p;
 
   for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
-    if (INSN_P (p) && p != succ && p != succ2 && is_volatile_p (PATTERN (p)))
+    if (NONDEBUG_INSN_P (p)
+       && p != succ
+       && p != succ2
+       && is_volatile_p (PATTERN (p)))
       return false;
 
   /* If INSN contains an autoincrement or autodecrement, make sure that
diff --git a/gcc/testsuite/gcc.dg/pr127422.c b/gcc/testsuite/gcc.dg/pr127422.c
new file mode 100644
index 00000000000..bba30ad7844
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr127422.c
@@ -0,0 +1,35 @@
+/* PR rtl-optimization/127422 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcompare-debug" } */
+
+static int ordinary_0 = 3;
+static int ordinary_1 = 22;
+static volatile int effect_0 = 6;
+static volatile int effect_1 = 23;
+static int ordinary_2 = 41;
+__attribute__ ((used)) int *ordinary_escape[]
+    = { &ordinary_0, &ordinary_1, &ordinary_2 };
+
+static inline __attribute__ ((always_inline))
+unsigned long long
+accumulate (unsigned long long acc, unsigned long long val)
+{
+  return acc + val;
+}
+
+unsigned long long
+foo (void)
+{
+  int staged_ordinary_0 = ordinary_0;
+  int staged_ordinary_1 = ordinary_1;
+  int staged_effect_0 = effect_0;
+  int staged_effect_1 = effect_1;
+  int staged_ordinary_2 = ordinary_2;
+  unsigned long long sum = 0;
+  sum = accumulate (sum, staged_ordinary_0);
+  sum = accumulate (sum, staged_ordinary_1);
+  sum = accumulate (sum, staged_effect_0);
+  sum = accumulate (sum, staged_effect_1);
+  sum = accumulate (sum, staged_ordinary_2);
+  return sum;
+}
-- 
2.34.1

Reply via email to