public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] tree-optimization/100434 - DSE aggregate call LHS
@ 2021-05-06 10:53 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2021-05-06 10:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: ebotcazou, jakub

This makes DSE consider aggregate LHS of calls as dead, for pure
or const calls the whole stmt and for others by removing the LHS.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

I wonder if there's a more canonical test for call LHS that cannot
be removed than

+      if (gimple_call_return_slot_opt_p (as_a <gcall *>(stmt))
+         && (TREE_ADDRESSABLE (TREE_TYPE (gimple_call_fntype (stmt)))
+             || !poly_int_tree_p
+                   (TYPE_SIZE (TREE_TYPE (gimple_call_fntype (stmt))))))
+       return;

?

Richard.

2021-05-05  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/100434
	* tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle
	call LHS.
	(dse_optimize_stmt): Handle call LHS by dropping the
	LHS or the whole call if it doesn't have other
	side-effects.
	(pass_dse::execute): Adjust.

	* gcc.dg/tree-ssa/ssa-dse-43.c: New testcase.
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c |  22 +++++
 gcc/tree-ssa-dse.c                         | 107 +++++++++++++--------
 2 files changed, 87 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c
new file mode 100644
index 00000000000..f8785e9da46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-dse1-details" } */
+
+struct X { int x; };
+struct X x;
+
+extern struct X foo (void);
+void bar()
+{
+  x = foo();
+  x = (struct X){};
+}
+
+extern struct X __attribute__((const)) foo2 (int);
+void bar2()
+{
+  x = foo2 (1);
+  x = foo2 (2);
+}
+
+/* { dg-final { scan-tree-dump-times "Deleted dead store in call LHS: x = foo " 1 "dse1" } } */
+/* { dg-final { scan-tree-dump-times "Deleted dead store: x = foo2 " 1 "dse1" } } */
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 63c876a1ff2..c3939a6417f 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -140,10 +140,13 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write)
 	  break;
 	}
     }
-  else if (is_gimple_assign (stmt))
+  else if (tree lhs = gimple_get_lhs (stmt))
     {
-      ao_ref_init (write, gimple_assign_lhs (stmt));
-      return true;
+      if (TREE_CODE (lhs) != SSA_NAME)
+	{
+	  ao_ref_init (write, lhs);
+	  return true;
+	}
     }
   return false;
 }
@@ -1035,7 +1038,7 @@ delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type
    post dominates the first store, then the first store is dead.  */
 
 static void
-dse_optimize_stmt (gimple_stmt_iterator *gsi, sbitmap live_bytes)
+dse_optimize_stmt (function *fun, gimple_stmt_iterator *gsi, sbitmap live_bytes)
 {
   gimple *stmt = gsi_stmt (*gsi);
 
@@ -1113,49 +1116,69 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi, sbitmap live_bytes)
 	}
     }
 
-  if (is_gimple_assign (stmt))
+  bool by_clobber_p = false;
+
+  /* Check if this statement stores zero to a memory location,
+     and if there is a subsequent store of zero to the same
+     memory location.  If so, remove the subsequent store.  */
+  if (gimple_assign_single_p (stmt)
+      && initializer_zerop (gimple_assign_rhs1 (stmt)))
+    dse_optimize_redundant_stores (stmt);
+
+  /* Self-assignments are zombies.  */
+  if (is_gimple_assign (stmt)
+      && operand_equal_p (gimple_assign_rhs1 (stmt),
+			  gimple_assign_lhs (stmt), 0))
+    ;
+  else
     {
-      bool by_clobber_p = false;
-
-      /* Check if this statement stores zero to a memory location,
-	 and if there is a subsequent store of zero to the same
-	 memory location.  If so, remove the subsequent store.  */
-      if (gimple_assign_single_p (stmt)
-	  && initializer_zerop (gimple_assign_rhs1 (stmt)))
-	dse_optimize_redundant_stores (stmt);
-
-      /* Self-assignments are zombies.  */
-      if (operand_equal_p (gimple_assign_rhs1 (stmt),
-			   gimple_assign_lhs (stmt), 0))
-	;
-      else
-	{
-	  bool byte_tracking_enabled
-	    = setup_live_bytes_from_ref (&ref, live_bytes);
-	  enum dse_store_status store_status;
-	  store_status = dse_classify_store (&ref, stmt,
-					     byte_tracking_enabled,
-					     live_bytes, &by_clobber_p);
-	  if (store_status == DSE_STORE_LIVE)
-	    return;
+      bool byte_tracking_enabled
+	  = setup_live_bytes_from_ref (&ref, live_bytes);
+      enum dse_store_status store_status;
+      store_status = dse_classify_store (&ref, stmt,
+					 byte_tracking_enabled,
+					 live_bytes, &by_clobber_p);
+      if (store_status == DSE_STORE_LIVE)
+	return;
 
-	  if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
-	    {
-	      maybe_trim_partially_dead_store (&ref, live_bytes, stmt);
-	      return;
-	    }
+      if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
+	{
+	  maybe_trim_partially_dead_store (&ref, live_bytes, stmt);
+	  return;
 	}
+    }
 
-      /* Now we know that use_stmt kills the LHS of stmt.  */
+  /* Now we know that use_stmt kills the LHS of stmt.  */
 
-      /* But only remove *this_2(D) ={v} {CLOBBER} if killed by
-	 another clobber stmt.  */
-      if (gimple_clobber_p (stmt)
-	  && !by_clobber_p)
-	return;
+  /* But only remove *this_2(D) ={v} {CLOBBER} if killed by
+     another clobber stmt.  */
+  if (gimple_clobber_p (stmt)
+      && !by_clobber_p)
+    return;
 
-      delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup);
+  if (is_gimple_call (stmt)
+      && (gimple_has_side_effects (stmt)
+	  || (stmt_could_throw_p (fun, stmt)
+	      && !fun->can_delete_dead_exceptions)))
+    {
+      /* Make sure we do not remove a return slot we cannot reconstruct
+	 later.  */
+      if (gimple_call_return_slot_opt_p (as_a <gcall *>(stmt))
+	  && (TREE_ADDRESSABLE (TREE_TYPE (gimple_call_fntype (stmt)))
+	      || !poly_int_tree_p
+		    (TYPE_SIZE (TREE_TYPE (gimple_call_fntype (stmt))))))
+	return;
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "  Deleted dead store in call LHS: ");
+	  print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+	  fprintf (dump_file, "\n");
+	}
+      gimple_call_set_lhs (stmt, NULL_TREE);
+      update_stmt (stmt);
     }
+  else
+    delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup);
 }
 
 namespace {
@@ -1194,7 +1217,7 @@ pass_dse::execute (function *fun)
   need_eh_cleanup = BITMAP_ALLOC (NULL);
   auto_sbitmap live_bytes (param_dse_max_object_size);
 
-  renumber_gimple_stmt_uids (cfun);
+  renumber_gimple_stmt_uids (fun);
 
   calculate_dominance_info (CDI_DOMINATORS);
 
@@ -1211,7 +1234,7 @@ pass_dse::execute (function *fun)
 	  gimple *stmt = gsi_stmt (gsi);
 
 	  if (gimple_vdef (stmt))
-	    dse_optimize_stmt (&gsi, live_bytes);
+	    dse_optimize_stmt (fun, &gsi, live_bytes);
 	  else if (def_operand_p
 		     def_p = single_ssa_def_operand (stmt, SSA_OP_DEF))
 	    {
-- 
2.26.2

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-05-06 10:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-06 10:53 [PATCH] tree-optimization/100434 - DSE aggregate call LHS Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).