David Vandevoorde a écrit :> On Aug 27, 2009, at 3:07 AM, Cédric Venet wrote: > > >> David Vandevoorde a écrit : >> >>> I don't think those are _good_ reasons though: If one doesn't want >>> a C+ + function to be inlined, one shouldn't define it inline. >>> >>> >>> >> You must not have written a lot of C++ template then. >> > > (Ha!) >:) ok, your name didn't register at first, but I have read (part of) your book. sorry for the tone of my reply which was not very friendly (It happen often to me with mail, but this is not an excuse). I just didn't and still don't understand how you do it, but this is probably not the good place to discuses this. please accept my sincere apologies.> > I don't think that how standard library or STL headers _are_ written > determines how they _should be_ written. > > (Templates don't force us to write excessive inline functions: Leave > off the inline keyword and write a member function outside the class > template definition, and it's no longer an inline function.) >What about multiple translation unit then? because from my understanding, this will generate multiple definition of symbol, so you will never be able to link it (except with some strange link specification (weak or something like this) which seem less portable than declaring the function inline). From the standard: Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used. regards, Cédric
On Aug 27, 2009, at 9:53 AM, Cédric Venet wrote:> David Vandevoorde a écrit : >> On Aug 27, 2009, at 3:07 AM, Cédric Venet wrote: >> >> >>> David Vandevoorde a écrit : >>> >>>> I don't think those are _good_ reasons though: If one doesn't want >>>> a C+ + function to be inlined, one shouldn't define it inline. >>>> >>>> >>>> >>> You must not have written a lot of C++ template then. >>> >> >> (Ha!) >> > > :) ok, your name didn't register at first, but I have read (part of) > your book. sorry for the tone of my reply which was not very friendly > (It happen often to me with mail, but this is not an excuse). I just > didn't and still don't understand how you do it, but this is probably > not the good place to discuses this. > please accept my sincere apologies.Apology happily accepted -- no hard feelings! [...]>> I don't think that how standard library or STL headers _are_ written >> determines how they _should be_ written. >> >> (Templates don't force us to write excessive inline functions: Leave >> off the inline keyword and write a member function outside the class >> template definition, and it's no longer an inline function.) >> > > What about multiple translation unit then? because from my > understanding, this will generate multiple definition of symbol, so > you > will never be able to link it (except with some strange link > specification (weak or something like this) which seem less portable > than declaring the function inline).The most common practice nowadays is indeed "some strange link specification": Linkable template instances are placed in comdat sections, and the linker (or loader) ignores duplicate sections. That's a theoretically lousy solution (e.g., different instances might have been compiled differently), but in practice I haven't seen many problems or complaints. (Note that all this is transparently handled by the compiler.) (Comdat sections are also useful for other C++ compilation artifacts, such as spilled inline functions, and certain virtual function tables and typeinfo data structures.) There are other ways to deal with the issue. Our (EDG) product comes with a "prelinker" that assigns instances to a particular object file (rerunning the compiler to generate instances): In practice I find it not as efficient as the comdat approach, but those customers that cannot have linker support have a way forward with it. Sun also had a neat alternative solution to the issue using an instance database of sorts, but it doesn't work well will traditional build systems and they ended up switching to a comdat-like scheme as well. See section 10.4 in "C++ Templates -- The complete guide".> From the standard: > > Every program shall contain exactly one definition of every > non-inline function or object that is used in that > program; no diagnostic required. The definition can appear > explicitly in the program, it can be found in the > standard or a user-defined library, or (when appropriate) it is > implicitly defined (see 12.1, 12.4 and 12.8). > An inline function shall be defined in every translation unit in > which it is used.Those are requirements on source code (essentially); not on implementation. (Note also: function != function template.) Daveed
Cédric Venet wrote:> I just > didn't and still don't understand how you do it, but this is probably > not the good place to discuses this. > > > What about multiple translation unit then? because from my > understanding, this will generate multiple definition of symbol, so you > will never be able to link it (except with some strange link > specification (weak or something like this) which seem less portable > than declaring the function inline).The standard requires the compiler/linker to be able to handle non-inline template functions defined in headers, because without them, implicit instantiation simply wouldn't work. Therefore, it's always possible to define function templates out-of-line, but still in the headers - it's just sometimes incredibly ugly, especially when you have member templates of class templates. (Also, some ancient compilers don't support the out-of-line definition syntax.) It's also common to move these out-of-line definitions to their own file, which is included at the bottom of the header file, so as to not clutter the declaration file. Sebastian
When I started this, I deliberately restricted the question to what should go in the IR. The fact of recording hints in the IR should not be controversial; it can't be better not to have them than to have them. Unfortunately, others used this as a springboard for discussing whether and how the inliner should use those hints. We aren't really ready to have that discussion, because nobody has any data on how well that would work in llvm. (We do have some data on well it worked on other compilers; I have worked on 2 others, and ignoring "inline" did not work well in either. David Vandevoorde evidently has similar experience.) I should probably comment on this, since nobody seems to get it:> Dale comes at this from the premise that the inliner will always > make the wrong decision in some cases and therefore it is useful to > give the user some way to influence the inliners heuristic (other > than attr(noinline/alwaysinline)).On a theoretical basis, this is not a premise, it is a fact. Which calls it is beneficial to inline depends on which calls get executed. The compiler can't know that (barring profile-based feedback), the user can. Any heuristic based on information available to a compiler cannot get it right in all cases. Really, hints and the noinline/ alwaysinline attributes are not enough either; users need something they can put on individual calls. It is frequently the case that some calls to a function get executed more, and therefore benefit from inlining more, than others. Perhaps we should make alwaysinline/ noinline work on calls. (There is code around here where users have inlined functions by hand, or forced them into macros, because they didn't have fine-grained control of the compiler's inlining. We don't want to encourage either of those practices, I'm sure.) Now whether user hints can be trusted in practice in real code is, evidently, debatable, but I can point to my experience and David Vandevoorde's with other compilers as evidence that the theoretical considerations apply in practice as well. (It is also probably true that people who declare things inline in C/ObjC should be taken more seriously than those using C++; Apple's gcc has an adjustment to the inlining parameters that does this, which works well in practice on our code.)