rs6000: Enable more sibcalls when TOC is not preserved
A function compiled with the PC-relative addressing model does not require r2 to contain a TOC pointer, and does not guarantee that r2 will be preserved for its caller. Such a function can make sibcalls without restriction based on TOC preservation rules. However, a caller that does preserve r2 cannot make a sibcall to a callee that does not. 2020-08-19 Bill Schmidt <wschmidt@linux.ibm.com> gcc/ * config/rs6000/rs6000-logue.c (rs6000_decl_ok_for_sibcall): Sibcalls are always legal when the caller doesn't preserve r2. gcc/testsuite/ * gcc.target/powerpc/pcrel-sibcall-1.c: Adjust.
This commit is contained in:
parent
5abc821556
commit
95f17e2611
@ -1080,28 +1080,28 @@ rs6000_decl_ok_for_sibcall (tree decl)
|
||||
|
||||
if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
|
||||
{
|
||||
/* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
|
||||
functions, because the callee may have a different TOC pointer to
|
||||
the caller and there's no way to ensure we restore the TOC when
|
||||
/* A function compiled using the PC-relative addressing model does not
|
||||
use a TOC pointer; nor is it guaranteed to preserve the value of
|
||||
r2 for its caller's TOC. Such a function may make sibcalls to any
|
||||
function, whether local or external, without restriction based on
|
||||
TOC-save/restore rules. */
|
||||
if (rs6000_pcrel_p (cfun))
|
||||
return true;
|
||||
|
||||
/* Otherwise, under the AIX or ELFv2 ABIs we can't allow sibcalls
|
||||
to non-local functions, because the callee may not preserve the
|
||||
TOC pointer, and there's no way to ensure we restore the TOC when
|
||||
we return. */
|
||||
if (!decl || DECL_EXTERNAL (decl) || DECL_WEAK (decl)
|
||||
|| !(*targetm.binds_local_p) (decl))
|
||||
return false;
|
||||
|
||||
/* Similarly, if the caller preserves the TOC pointer and the callee
|
||||
doesn't (or vice versa), proper TOC setup or restoration will be
|
||||
missed. For example, suppose A, B, and C are in the same binary
|
||||
and A -> B -> C. A and B preserve the TOC pointer but C does not,
|
||||
and B -> C is eligible as a sibcall. A will call B through its
|
||||
local entry point, so A will not restore its TOC itself. B calls
|
||||
C with a sibcall, so it will not restore the TOC. C does not
|
||||
preserve the TOC, so it may clobber r2 with impunity. Returning
|
||||
from C will result in a corrupted TOC for A. */
|
||||
else if (rs6000_fndecl_pcrel_p (decl) != rs6000_pcrel_p (cfun))
|
||||
/* A local sibcall from a function that preserves the TOC pointer
|
||||
to a function that does not is invalid for the same reason. */
|
||||
if (rs6000_fndecl_pcrel_p (decl))
|
||||
return false;
|
||||
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* With the secure-plt SYSV ABI we can't make non-local calls when
|
||||
|
@ -3,10 +3,9 @@
|
||||
/* { dg-require-effective-target powerpc_elfv2 } */
|
||||
/* { dg-require-effective-target power10_ok } */
|
||||
|
||||
/* Test that potential sibcalls are not generated when the caller preserves the
|
||||
TOC and the callee doesn't, or vice versa. At present, -mcpu=power10 does
|
||||
not enable pc-relative mode. Enable it here explicitly until it is turned
|
||||
on by default. */
|
||||
/* Test that potential sibcalls are generated when the caller does not
|
||||
preserve the TOC, even for external calls; and that sibcalls are not
|
||||
generated when the caller preserves the TOC but the callee does not. */
|
||||
|
||||
#pragma GCC target ("cpu=power10,pcrel")
|
||||
int x (void) __attribute__((noinline));
|
||||
@ -39,12 +38,20 @@ int xx (void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int yy (void);
|
||||
|
||||
#pragma GCC target ("cpu=power10,pcrel")
|
||||
int notoc_call (void)
|
||||
int notoc_sibcall (void)
|
||||
{
|
||||
return xx ();
|
||||
}
|
||||
|
||||
int extern_sibcall (void)
|
||||
{
|
||||
return yy ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\mb x@notoc\M} } } */
|
||||
/* { dg-final { scan-assembler {\mbl y\M} } } */
|
||||
/* { dg-final { scan-assembler {\mbl xx@notoc\M} } } */
|
||||
/* { dg-final { scan-assembler {\mb xx@notoc\M} } } */
|
||||
/* { dg-final { scan-assembler {\mb yy@notoc\M} } } */
|
||||
|
Loading…
Reference in New Issue
Block a user