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.
This commit is contained in:
Alexander Monakov 2023-01-13 21:04:02 +03:00
parent b4b1c6aa6d
commit 733a1b777f
2 changed files with 38 additions and 1 deletions

View File

@ -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. */

View File

@ -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;
}
}