Re: C: inline without forcing?

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

 



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




[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