C: inline without forcing?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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!

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. 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().

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.

-Danielle



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux