From 733a1b777f16cd397b43a242d9c31761f66d3da8 Mon Sep 17 00:00:00 2001 From: Alexander Monakov Date: Fri, 13 Jan 2023 21:04:02 +0300 Subject: [PATCH] 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. --- gcc/sched-deps.cc | 9 ++++++++- gcc/testsuite/gcc.dg/pr108117.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr108117.c diff --git a/gcc/sched-deps.cc b/gcc/sched-deps.cc index 08877b344b64..f9371b81fb41 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 000000000000..ae151693e2f9 --- /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 +#include + +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; + } +}