On Sun, 2021-05-30 at 20:34 -0400, Danielle Church via Gcc-help wrote: > Hi, > > I'm trying to figure out how to get GCC 9.3 to obey some very > particular > semantics, in a large multi-file library project, relating to function > inlining. Let's say I have two files with one function each, one of > which > calls the other: > > ===foo.c=== > int foo(int x) { return x * 2; } > > ===bar.c=== > int bar(int x) { return foo(x + 1); } > > foo and bar are, in this case, functions that are global to library > code > (though perhaps not exported from the output library). If I compile > these > separately into foo.o and bar.o, then link them into foobar.so, I'll > end up > with two function declarations, one of which executes a call > instruction to > the other, as written. > > On the other hand, if I concatenate these files and compile them as a > single translation unit, I'll still end up with two functions in my > library, but if foo() is simple enough, the bar() implementation will > probably inline it rather than emitting a call instruction. Better! Negative. In this case ELF spec mandates to call foo() via PLT. The compiler can't inline it since the inlining will break semantic interposition, unless -fno-semantic-interposition is explicitly used. > It means I have to lump foo.c and bar.c (which of course have lots of > other > unrelated code) together, though, slowing down compilation times > considerably. What I'd really like to do is make some subset of > foo.c's > function definitions available to bar.c in case GCC decides it's > worthwhile > to inline them, but not compile any of these as standalone. C99 > provides > *almost* the exact semantics I'm looking for: > > ===foo.c is unchanged, or:=== > extern inline int foo(int x) { return x * 2; } > > ===bar.c=== > inline int foo(int x) { return x * 2; } > int bar(int x) { return foo(x + 1); } > > The only problem is that GCC is now significantly more likely to > inline > foo(), regardless of whether it's a good idea or not. I'm not trying > to > "force" the optimizer to do the inlining, or even "suggest" it. I > could > declare the bar.c copy of the function as static, but then if it > doesn't > get inlined, there will be a second anonymous definition in the final > library. The problem here is the compiler doesn't know the two definitions of "foo" are same, so it can do nothing; the linker doesn't know there is nobody taking the two foo's addresses, so it can not merge them (C99 mandates the address of two different functions different). > I could give the bar.c copy __attribute__((weak)), which is, > again, *almost* right; the weak copy in bar.o will get overridden by > the > strong copy from foo.o, but now it won't work with a PGO pipeline > because > the final output is missing bar.o::foo(). In this case (with weak attribute) the compiler won't attempt to inline it at all. It's illegal to persume a weak definition having exactly same behavior with another "strong" definition, like the case of semantic interposition. > Help? Is there any way to do what I'm trying to do? It feels like it > should > be a simple enough task to give the compiler a function definition in > an > "informative" (vs "normative") context, but I can't figure it out. I think the only rational way is using -fno-semantic-interposition, and put the definition of foo & bar into the same TU (or using -flto). -- Xi Ruoyao <xry111@xxxxxxxxxxxxxxxx> School of Aerospace Science and Technology, Xidian University