tree-optimization/111773 - avoid CD-DCE of noreturn special calls

Message ID 20231012090145.196C73856DC8@sourceware.org
State Accepted
Headers
Series tree-optimization/111773 - avoid CD-DCE of noreturn special calls |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Richard Biener Oct. 12, 2023, 9:01 a.m. UTC
  The support to elide calls to allocation functions in DCE runs into
the issue that when implementations are discovered noreturn we end
up DCEing the calls anyway, leaving blocks without termination and
without outgoing edges which is both invalid IL and wrong-code when
as in the example the noreturn call would throw.  The following
avoids taking advantage of both noreturn and the ability to elide
allocation at the same time.

For the testcase it's valid to throw or return 10 by eliding the
allocation.  But we have to do either where currently we'd run
off the function.

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

Honza, any objections here?

Thanks,
Richard.

	PR tree-optimization/111773
	* tree-ssa-dce.cc (mark_stmt_if_obviously_necessary): Do
	not elide noreturn calls that are reflected to the IL.

	* g++.dg/torture/pr111773.C: New testcase.
---
 gcc/testsuite/g++.dg/torture/pr111773.C | 31 +++++++++++++++++++++++++
 gcc/tree-ssa-dce.cc                     |  8 +++++++
 2 files changed, 39 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr111773.C
  

Patch

diff --git a/gcc/testsuite/g++.dg/torture/pr111773.C b/gcc/testsuite/g++.dg/torture/pr111773.C
new file mode 100644
index 00000000000..af8c687252c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr111773.C
@@ -0,0 +1,31 @@ 
+// { dg-do run }
+
+#include <new>
+
+void* operator new(std::size_t sz)
+{
+  throw std::bad_alloc{};
+}
+
+int __attribute__((noipa)) foo ()
+{
+  int* p1 = static_cast<int*>(::operator new(sizeof(int)));
+  return 10;
+}
+
+int main()
+{
+  int res;
+  try
+    {
+      res = foo ();
+    }
+  catch (...)
+    {
+      return 0;
+    }
+
+  if (res != 10)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index f0b02456132..bbdf9312c9f 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -221,6 +221,14 @@  mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
 
     case GIMPLE_CALL:
       {
+	/* Never elide a noreturn call we pruned control-flow for.  */
+	if ((gimple_call_flags (stmt) & ECF_NORETURN)
+	    && gimple_call_ctrl_altering_p (stmt))
+	  {
+	    mark_stmt_necessary (stmt, true);
+	    return;
+	  }
+
 	tree callee = gimple_call_fndecl (stmt);
 	if (callee != NULL_TREE
 	    && fndecl_built_in_p (callee, BUILT_IN_NORMAL))