Hello, > > There are codes like > > extern void foo (void); > > void > bar (void) > { > foo (); > } > > Even with LTO, compiler may have to assume foo is external > when foo is compiled with LTO.
This is not exactly true if FOO is defined in other translation unit compiled with LTO and hidden visibility. OK, so as I get it, we get the following cases: 1) compiler knows it is generating call to a local symbol a current unit (binds_to_current_def_p returns true). We handle this correctly by doing IP relative call. 2) compiler knows it is generating call to a local symbol in DSO (binds_local_p return true) Currently I think this is only the -fno-pic case or case of explicit hidden visibility and in this case we do IP relative call. We may want to propose plugin API update adding PREVAILING_DEF_EXP. So copiler would be able to default to this case for PREVAILING_DEF and we will also catch cases where the symbol is defined in current DSO as weak symbol, but the definition is not LTO. This would be also way to communicate -Bsymbolic[-functions] across the plugin API. 3) compiler knows there is going to be definition in the current DSO (by seeing a COMDAT function body or resolution info) that is interposable but because the function is inline or -fno-semantic-interposition happens, the semantics will not change. In this case it would be nice to arrange IP relative call to the hidden alias. This may require an extension both on compiler and linker side. I was thinking of doing so for comdats by adding hidden alias with fixed mangling, like __gnu_<function>.hiddenalias, and referring it. But I think it is not safe as linker may throw away section that is produced by GCC and prevail section that is not leaving to an undefined symbol? I think this is rather common case in C++ (never made any stats) because uninlined comdats are quite common. 4) compiler has no clue but linker may know better Here we traditionally always produce a PLT call. In cases the call is known to be hot in the program it makes sense to trade lazy binding for performance and produce call via GOT reference (-fno-plt). I also see that H.J.'s branch helps us to actually avoid the GOT reference in cases the symbol ends up binding locally. How the lazy binding with relaxation works? We may try to communicate down the information whether the symbol can or can not semantically interpose to the linker, so it can do -Bsymbolic by default for inline and COMDAT functions. Actually perhaps the linker can just default to this for all comdat defined symbols? I think it still make sense to work on non-LTO codegen improvements. As much as I would like everyone to LTO and FDO, most people don't. 5) Compiler knows it is generating call to external function. We do not special case this, but we could add binds_external_p and make it to determine this case from resolution info during LTO. I do not see if this case is any different from 4 from PIC codegen perspective except that perhaps the relax relocation will allow us to lazy bind? Honza