]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtlanal: Use REG_UNUSED notes in single_set only in passes where df_analyze has compu...
authorJakub Jelinek <jakub@redhat.com>
Fri, 12 Dec 2025 14:18:08 +0000 (15:18 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 12 Dec 2025 14:18:08 +0000 (15:18 +0100)
REG_UNUSED and REG_DEAD notes are only valid when computed by df
with df_note_add_problem () before df_analyze ().
Generally, especially CSE/GCSE optimizations can invalidate those
notes by reusing the REG_UNUSED results later on, unfortunately dropping
REG_UNUSED notes in such cases is not very easy.
See e.g. PR113059 and PR40209 for additional details.

Most users of REG_UNUSED/REG_DEAD notes add the note problems, but
single_set function is called from many of the passes and requiring
that df_note_add_problem () is done in each such a case would be very
slow and would need some checking.

The following patch instead limits the use of REG_UNUSED notes to
passes which have the note problem computed (i.e. df && df_note), and
for pseudos as a fallback uses DF_REG_USE_COUNT == 0 check if at least
df is computed.

2025-12-12  Jakub Jelinek  <jakub@redhat.com>

PR rtl-optimization/121852
* rtlanal.cc (single_set_2): Only look for REG_UNUSED notes if
df && df_note, otherwise if df and SET_DEST is a pseudo with
DF_REG_USE_COUNT 0, assume it is unused as well.  Otherwise
assume it may be used.

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

gcc/rtlanal.cc
gcc/testsuite/gcc.dg/pr121852.c [new file with mode: 0644]

index 63a1d08c46cf0cc6ab59fdce902b582184c02f48..1a754f8dff885262a50176f787e3c9c9b2354a9a 100644 (file)
@@ -1546,6 +1546,9 @@ single_set_2 (const rtx_insn *insn, const_rtx pat)
            case CLOBBER:
              break;
 
+           default:
+             return NULL_RTX;
+
            case SET:
              /* We can consider insns having multiple sets, where all
                 but one are dead as single set insns.  In common case
@@ -1555,23 +1558,28 @@ single_set_2 (const rtx_insn *insn, const_rtx pat)
                 When we reach set first time, we just expect this is
                 the single set we are looking for and only when more
                 sets are found in the insn, we check them.  */
+             auto unused = [] (const rtx_insn *insn, rtx dest) {
+               if (!df)
+                 return false;
+               if (df_note)
+                 return !!find_reg_note (insn, REG_UNUSED, dest);
+               return (REG_P (dest)
+                       && !HARD_REGISTER_P (dest)
+                       && REGNO (dest) < df->regs_inited
+                       && DF_REG_USE_COUNT (REGNO (dest)) == 0);
+             };
              if (!set_verified)
                {
-                 if (find_reg_note (insn, REG_UNUSED, SET_DEST (set))
-                     && !side_effects_p (set))
+                 if (unused (insn, SET_DEST (set)) && !side_effects_p (set))
                    set = NULL;
                  else
                    set_verified = 1;
                }
              if (!set)
                set = sub, set_verified = 0;
-             else if (!find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
-                      || side_effects_p (sub))
+             else if (!unused (insn, SET_DEST (sub)) || side_effects_p (sub))
                return NULL_RTX;
              break;
-
-           default:
-             return NULL_RTX;
            }
        }
     }
diff --git a/gcc/testsuite/gcc.dg/pr121852.c b/gcc/testsuite/gcc.dg/pr121852.c
new file mode 100644 (file)
index 0000000..d5e3ffc
--- /dev/null
@@ -0,0 +1,49 @@
+/* PR rtl-optimization/121852 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-gcse" } */
+
+int a[] = { 0 }, d, e, h, i, j, k, l, n[1], *o = n;
+volatile int m;
+
+int
+foo (char q)
+{
+  return a[e ^ (q & 5)];
+}
+
+int
+bar (int q[])
+{
+  int b = 5;
+  for (int g = 0; g < d; ++g)
+    {
+      int c = foo (q[g] >> 6);
+      int f = (c & 4095) ^ a[c & 5];
+      b = f;
+    }
+  return b;
+}
+
+int
+baz (volatile int q)
+{
+  k = 5 % q;
+  int r[] = { h, i, k, j };
+  return bar (r);
+}
+
+int
+main ()
+{
+  int t;
+  do
+    {
+      if (baz (5))
+       m = 4;
+      l--;
+      t = l - 1 % m + 1;
+    }
+  while (!baz (5));
+  o[0] = 2 % t;
+  return 0;
+}