aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-10-12 10:13:58 +0200
committerRichard Biener <rguenther@suse.de>2023-10-13 08:34:05 +0200
commit35b5bb475375dba4ea9101d6db13a6012c4e84ca (patch)
tree890f5b428ff77f8716746062cfc95fc37f44d0e8 /gcc
parent6b580560a0e393e3b65567263e2cf5477d670592 (diff)
downloadgcc-35b5bb475375dba4ea9101d6db13a6012c4e84ca.zip
gcc-35b5bb475375dba4ea9101d6db13a6012c4e84ca.tar.gz
gcc-35b5bb475375dba4ea9101d6db13a6012c4e84ca.tar.bz2
tree-optimization/111773 - avoid CD-DCE of noreturn special calls
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. 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/torture/pr111773.C31
-rw-r--r--gcc/tree-ssa-dce.cc8
2 files changed, 39 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/torture/pr111773.C b/gcc/testsuite/g++.dg/torture/pr111773.C
new file mode 100644
index 0000000..af8c687
--- /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 f0b0245..bbdf931 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))