aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2024-09-03 17:14:13 +0200
committerArsen Arsenović <arsen@gcc.gnu.org>2024-09-04 16:46:34 +0200
commit7b7ad3f4b2455072f42e7884b93fd96ebb920bc8 (patch)
treea671a83ed3c5d751f72757826ff7c3e262098dbb /gcc
parent97e011a472e16ddab67d7374ee9c3db040b62798 (diff)
downloadgcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.zip
gcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.tar.gz
gcc-7b7ad3f4b2455072f42e7884b93fd96ebb920bc8.tar.bz2
coros: mark .CO_YIELD as LEAF [PR106973]
We rely on .CO_YIELD calls being followed by an assignment (optionally) and then a switch/if in the same basic block. This implies that a .CO_YIELD can never end a block. However, since a call to .CO_YIELD is still a call, if the function containing it calls setjmp, GCC thinks that the .CO_YIELD can introduce abnormal control flow, and generates an edge for the call. We know this is not the case; .CO_YIELD calls get removed quite early on and have no effect, and result in no other calls, so .CO_YIELD can be considered a leaf function, preventing generating an edge when calling it. PR c++/106973 - coroutine generator and setjmp PR c++/106973 gcc/ChangeLog: * internal-fn.def (CO_YIELD): Mark as ECF_LEAF. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr106973.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/internal-fn.def2
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr106973.C22
2 files changed, 23 insertions, 1 deletions
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 75b527b..23b4ab0 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -569,7 +569,7 @@ DEF_INTERNAL_FN (DIVMOD, ECF_CONST | ECF_LEAF, NULL)
/* For coroutines. */
DEF_INTERNAL_FN (CO_ACTOR, ECF_NOTHROW | ECF_LEAF, NULL)
-DEF_INTERNAL_FN (CO_YIELD, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (CO_YIELD, ECF_NOTHROW | ECF_LEAF, NULL)
DEF_INTERNAL_FN (CO_SUSPN, ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (CO_FRAME, ECF_PURE | ECF_NOTHROW | ECF_LEAF, NULL)
diff --git a/gcc/testsuite/g++.dg/coroutines/pr106973.C b/gcc/testsuite/g++.dg/coroutines/pr106973.C
new file mode 100644
index 0000000..6db6cbc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr106973.C
@@ -0,0 +1,22 @@
+// https://gcc.gnu.org/PR106973
+// { dg-require-effective-target indirect_jumps }
+#include <coroutine>
+#include <setjmp.h>
+
+struct generator;
+struct generator_promise {
+ generator get_return_object();
+ std::suspend_always initial_suspend();
+ std::suspend_always final_suspend() noexcept;
+ std::suspend_always yield_value(int);
+ void unhandled_exception();
+};
+
+struct generator {
+ using promise_type = generator_promise;
+};
+jmp_buf foo_env;
+generator foo() {
+ setjmp(foo_env);
+ co_yield 1;
+}