The transformations performed by the avr-2moves pass might depend
on the presence of debug insns, which is fixed by this patch.

It now uses next_nondebug_insn_bb() to traverses the insns in such a
way that the seen insns don't depend on the presence of debug insns.

Plus, it ignores debug insns when it traverses the DF_REG_USE_CHAIN
of the considered register.

The patch passes without new regression.  It fixes

  gcc.dg/pr103837.c (test for excess errors)
  gcc.dg/pr45865.c (test for excess errors)

which failed with -fcompare-debug.

Ok to apply?

Johann

--

        PR target/127188
gcc/
        * avr-passes.cc (avr_pass_2moves) <optimize_2moves_bb>:
        Use next_nondebug_insn_bb to traverse the insns.
        <optimize_2moves>: Ignore degug insns when traversing
        DF_REG_USE_CHAIN.
gcc/testsuite/
        * gcc.target/avr/pr127188.c: New test.
diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index 73608de4f83..6091bdf3aa3 100644
--- a/gcc/config/avr/avr-passes.cc
+++ b/gcc/config/avr/avr-passes.cc
@@ -4923,18 +4923,19 @@ bool
 avr_pass_2moves::optimize_2moves_bb (basic_block bb)
 {
   bool changed = false;
-  rtx_insn *insn1 = nullptr;
-  rtx_insn *insn2 = nullptr;
-  rtx_insn *curr;
+  rtx_insn *insn1 = next_nondebug_insn_bb (bb, BB_HEAD (bb));
 
-  FOR_BB_INSNS (bb, curr)
+  while (insn1)
     {
-      if (insn1 && INSN_P (insn1)
-	  && insn2 && INSN_P (insn2))
-	changed |= optimize_2moves (insn1, insn2);
+      rtx_insn *insn2 = next_nondebug_insn_bb (bb, insn1);
+      if (!insn2)
+	break;
+
+      rtx_insn *next = next_nondebug_insn_bb (bb, insn2);
 
-      insn1 = insn2;
-      insn2 = curr;
+      bool change = optimize_2moves (insn1, insn2);
+      changed |= change;
+      insn1 = change ? next : insn2;
     }
 
   return changed;
@@ -4974,7 +4975,10 @@ avr_pass_2moves::optimize_2moves (rtx_insn *insn1, rtx_insn *insn2)
       for (; use; use = DF_REF_NEXT_REG (use))
 	{
 	  rtx_insn *user = DF_REF_INSN (use);
-	  avr_dump (" %d", INSN_UID (user));
+	  bool debug_p = DEBUG_INSN_P (user);
+	  avr_dump (" %d%s", INSN_UID (user), debug_p ? "=debug_insn" : "");
+	  if (debug_p)
+	    continue;
 	  good |= INSN_UID (user) == INSN_UID (insn2);
 	  bad |= INSN_UID (user) != INSN_UID (insn2);
 	}
diff --git a/gcc/testsuite/gcc.target/avr/pr127188.c b/gcc/testsuite/gcc.target/avr/pr127188.c
new file mode 100644
index 00000000000..f2c5145b4c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr127188.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcompare-debug" } */
+
+extern int foo (int);
+
+int bar (int a, int b)
+{
+  int q;
+  if (a < 0)
+    q = 0;
+  else
+    q = 1;
+  int c = foo (b);
+  if (q != 0)
+    c = foo (c);
+  int d = foo (c);
+  return d;
+}

Reply via email to