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)