https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104894
--- Comment #8 from Peter Bergner <bergner at gcc dot gnu.org> ---
Sorry for the delay, but getting back to this now...
(In reply to Alan Modra from comment #6)
> What I should have said is that -mlongcall code is correct but is
> missing a sibcall optimisation. -fno-plt code (after removing the assert or
> using your patch) is incorrect. A direct call is wrong, because it may
> require a plt call stub. gcc ought to be producing an inline plt call.
First off, is it just me, or does the -fno-plt option seem to slow down
basically all function calls since it forces us to emit a call that uses an
inline plt? Even for functions that don't need it.
> Change the testcase to
>
> void foo();
>
> void bar() {
> foo();
> foo();
> }
>
> to see what I mean. The asm output is
[snip]
> That "b foo@notoc" ought to be
> pld 12,0(0),1
> .reloc .-8,R_PPC64_PLT_PCREL34_NOTOC,foo
> mtctr 12
> .reloc .-4,R_PPC64_PLTSEQ,foo
> .reloc .,R_PPC64_PLTCALL_NOTOC,foo
> bctr
Thanks for the education! The change below gives us that code sequence:
bar:
.LFB0:
.cfi_startproc
.localentry bar,1
mflr 0
std 0,16(1)
stdu 1,-96(1)
.cfi_def_cfa_offset 96
.cfi_offset 65, 16
pld 12,0(0),1
.reloc .-8,R_PPC64_PLT_PCREL34_NOTOC,foo
mtctr 12
.reloc .-4,R_PPC64_PLTSEQ,foo
.reloc .,R_PPC64_PLTCALL_NOTOC,foo
bctrl
pld 12,0(0),1
.reloc .-8,R_PPC64_PLT_PCREL34_NOTOC,foo
addi 1,1,96
.cfi_def_cfa_offset 0
mtctr 12
ld 0,16(1)
mtlr 0
.cfi_restore 65
bctr
How does this look now? I'll go ahead and regtest this.
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index cb18db06a2d..e045657a2b0 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -25659,11 +25659,21 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx
tlsarg, rtx cookie)
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) != 0
+ && GET_CODE (func_desc) == SYMBOL_REF)
+ {
+ /* Only 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)