mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-10 20:55:23 +08:00
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:
parent
b4b1c6aa6d
commit
733a1b777f
@ -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. */
|
||||
|
30
gcc/testsuite/gcc.dg/pr108117.c
Normal file
30
gcc/testsuite/gcc.dg/pr108117.c
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user