Before PCREL in POWER10, we were not allowed to perform sibcalls to longcall
functions since callee's return would skip the TOC restore in the caller.
However, with PCREL we can now safely perform a sibling call to longcall
functions. The problem with the current code is that pcrel sibcall
branches to a PLT stub label even though -fno-plt was used. The solution
here is to check for a pcrel longcall and emit an inline plt stub in
that case.
2022-04-11 Peter Bergner <bergner@linux.ibm.com>
gcc/
PR target/104894
* config/rs6000/rs6000.c (rs6000_sibcall_aix): Handle pcrel sibcalls
to longcall functions.
gcc/testsuite/
PR target/104894
* gcc.target/powerpc/pr104894.c: New test.
* gcc.target/powerpc/pr104894-2.c: New test.
(cherry picked from commit
d74c4c6a1b4956b5cd9b2a770bb7261836fa1289)
rtx r12 = NULL_RTX;
rtx func_addr = func_desc;
- gcc_assert (INTVAL (cookie) == 0);
-
if (global_tlsarg)
tlsarg = global_tlsarg;
+ /* Handle longcall attributes. */
+ if (INTVAL (cookie) & CALL_LONG && SYMBOL_REF_P (func_desc))
+ {
+ /* PCREL can do a sibling call to a longcall function
+ because we don't need to restore the TOC register. */
+ gcc_assert (rs6000_pcrel_p ());
+ func_desc = rs6000_longcall_ref (func_desc, tlsarg);
+ }
+ else
+ gcc_assert (INTVAL (cookie) == 0);
+
/* For ELFv2, r12 and CTR need to hold the function address
for an indirect call. */
if (GET_CODE (func_desc) != SYMBOL_REF && DEFAULT_ABI == ABI_ELFv2)
--- /dev/null
+/* PR target/104894 */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -fno-plt" } */
+
+/* Verify we do not ICE on the following test case and that we emit one
+ indirect call and one indirect sibcall, with r12 and CTR containing
+ the function addresses. */
+
+void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+ foo ();
+}
+
+/* { dg-final { scan-assembler-times {\mmtctr 12\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mbctrl\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mbctr\M} 1 } } */
+/* { dg-final { scan-assembler-not {\mbl\M} } } */
--- /dev/null
+/* PR target/104894 */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -fno-plt" } */
+
+/* Verify we do not ICE on the following test case and that we emit an
+ indirect sibcall, with r12 and CTR containing the function address. */
+
+void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
+
+/* { dg-final { scan-assembler-times {\mmtctr 12\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mbctr\M} 1 } } */
+/* { dg-final { scan-assembler-not {\mbl\M} } } */
+/* { dg-final { scan-assembler-not {\mbctrl\M} } } */