aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexander Monakov <amonakov@ispras.ru>2023-01-13 21:04:02 +0300
committerAlexander Monakov <amonakov@ispras.ru>2023-01-13 21:33:14 +0300
commit733a1b777f16cd397b43a242d9c31761f66d3da8 (patch)
treeaecfd13965c06cc086077992307d31d06a75714f /gcc
parentb4b1c6aa6d28d3afe989a6dc3210606a3d55a367 (diff)
downloadgcc-733a1b777f16cd397b43a242d9c31761f66d3da8.zip
gcc-733a1b777f16cd397b43a242d9c31761f66d3da8.tar.gz
gcc-733a1b777f16cd397b43a242d9c31761f66d3da8.tar.bz2
sched-deps: do not schedule pseudos across calls [PR108117]
Scheduling across calls in the pre-RA scheduler is problematic: we do not take liveness info into account, and are thus prone to extending lifetime of a pseudo over the loop, requiring a callee-saved hardreg or causing a spill. If current function called a setjmp, lifting an assignment over a call may be incorrect if a longjmp would happen before the assignment. Thanks to Jose Marchesi for testing on AArch64. gcc/ChangeLog: PR rtl-optimization/108117 PR rtl-optimization/108132 * sched-deps.cc (deps_analyze_insn): Do not schedule across calls before reload. gcc/testsuite/ChangeLog: PR rtl-optimization/108117 PR rtl-optimization/108132 * gcc.dg/pr108117.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/sched-deps.cc9
-rw-r--r--gcc/testsuite/gcc.dg/pr108117.c30
2 files changed, 38 insertions, 1 deletions
diff --git a/gcc/sched-deps.cc b/gcc/sched-deps.cc
index 08877b3..f9371b8 100644
--- a/gcc/sched-deps.cc
+++ b/gcc/sched-deps.cc
@@ -3688,7 +3688,14 @@ deps_analyze_insn (class deps_desc *deps, rtx_insn *insn)
CANT_MOVE (insn) = 1;
- if (find_reg_note (insn, REG_SETJMP, NULL))
+ if (!reload_completed)
+ {
+ /* Scheduling across calls may increase register pressure by extending
+ live ranges of pseudos over the call. Worse, in presence of setjmp
+ it may incorrectly move up an assignment over a longjmp. */
+ reg_pending_barrier = MOVE_BARRIER;
+ }
+ else if (find_reg_note (insn, REG_SETJMP, NULL))
{
/* This is setjmp. Assume that all registers, not just
hard registers, may be clobbered by this call. */
diff --git a/gcc/testsuite/gcc.dg/pr108117.c b/gcc/testsuite/gcc.dg/pr108117.c
new file mode 100644
index 0000000..ae15169
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr108117.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-require-effective-target nonlocal_goto } */
+/* { dg-options "-O2 -fschedule-insns" } */
+
+#include <stdio.h>
+#include <setjmp.h>
+
+jmp_buf ex_buf;
+
+__attribute__((noipa))
+void fn_throw(int x)
+{
+ if (x)
+ longjmp(ex_buf, 1);
+}
+
+int main(void)
+{
+ int vb = 0; // NB: not volatile, not modified after setjmp
+
+ if (!setjmp(ex_buf)) {
+ fn_throw(1);
+ vb = 1; // not reached in the abstract machine
+ }
+
+ if (vb) {
+ printf("Failed, vb = %d!\n", vb);
+ return 1;
+ }
+}