]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Remove variables only used with .DEFERRED_INIT
authorRichard Biener <rguenther@suse.de>
Tue, 14 Mar 2023 08:42:45 +0000 (09:42 +0100)
committerRichard Biener <rguenther@suse.de>
Tue, 14 Mar 2023 12:46:30 +0000 (13:46 +0100)
In PR109087 it was noticed that we rely on DSE to remove .DEFERRED_INIT
when it is the only remaining use of a variable.  Since DSE is imperfect
and even if it were not would be limited by the amount of statements to
walk the following enhances the unused var removal pass to handle
.DEFERRED_INIT like CLOBBERs, thus we do not keep local variables just
because they are deferred initialized.

* tree-ssa-live.cc (remove_unused_locals): Do not treat
the .DEFERRED_INIT of a variable as use, instead remove
that if it is the only use.

* gcc.dg/auto-init-unused-1.c: New testcase.

gcc/testsuite/gcc.dg/auto-init-unused-1.c [new file with mode: 0644]
gcc/tree-ssa-live.cc

diff --git a/gcc/testsuite/gcc.dg/auto-init-unused-1.c b/gcc/testsuite/gcc.dg/auto-init-unused-1.c
new file mode 100644 (file)
index 0000000..b7d44e6
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=zero -fdump-tree-ssa" } */
+
+int a;
+int foo (void);
+int bar (void);
+
+void
+baz (void)
+{
+  int *b[6];
+  if (foo ())
+    a |= bar ();
+}
+
+/* { dg-final { scan-tree-dump-not "DEFERRED_INIT" "ssa" } } */
index c179444e8e1ba5aa077ab9595ca1c5a464ee1ccd..9118e82b4f1bf9fcf356349c078ab53dcfe55f49 100644 (file)
@@ -813,6 +813,12 @@ remove_unused_locals (void)
              continue;
            }
 
+         if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+           {
+             have_local_clobbers = true;
+             continue;
+           }
+
          if (b)
            TREE_USED (b) = true;
 
@@ -856,7 +862,7 @@ remove_unused_locals (void)
      to remove them if they are the only references to a local variable,
      but we want to retain them when there's any other.  So the first pass
      ignores them, and the second pass (if there were any) tries to remove
-     them.  */
+     them.  We do the same for .DEFERRED_INIT.  */
   if (have_local_clobbers)
     FOR_EACH_BB_FN (bb, cfun)
       {
@@ -888,6 +894,19 @@ remove_unused_locals (void)
                if (b)
                  TREE_USED (b) = true;
              }
+           else if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+             {
+               tree lhs = gimple_call_lhs (stmt);
+               if (DECL_P (lhs) && !is_used_p (lhs))
+                 {
+                   unlink_stmt_vdef (stmt);
+                   gsi_remove (&gsi, true);
+                   release_defs (stmt);
+                   continue;
+                 }
+               if (b)
+                 TREE_USED (b) = true;
+             }
            else if (gimple_debug_bind_p (stmt))
              {
                tree var = gimple_debug_bind_get_var (stmt);