Jump to page: 1 213  
Page
Thread overview
What does 'inline' mean?
Jun 08, 2020
Manu
Jun 08, 2020
evilrat
Jun 08, 2020
Walter Bright
Jun 09, 2020
Manu
Jun 09, 2020
Stanislav Blinov
Jun 09, 2020
Manu
Jun 09, 2020
rikki cattermole
Jun 09, 2020
Patrick Schluter
Jun 09, 2020
Dukc
Jun 09, 2020
Stefan Koch
Jun 09, 2020
Manu
Jun 08, 2020
Basile B.
Jun 08, 2020
Stefan Koch
Jun 08, 2020
Basile B.
Jun 08, 2020
Basile B.
Jun 08, 2020
Manu
Jun 08, 2020
Dukc
Jun 08, 2020
Stefan Koch
Jun 08, 2020
Manu
Jun 08, 2020
Walter Bright
Jun 08, 2020
Jan Hönig
Jun 08, 2020
John Colvin
Jun 09, 2020
Walter Bright
Jun 08, 2020
Manu
Jun 08, 2020
jmh530
Jun 09, 2020
Walter Bright
Jun 09, 2020
Stefan Koch
Jun 09, 2020
Patrick Schluter
Jun 09, 2020
Manu
Jun 09, 2020
Walter Bright
Jun 10, 2020
H. S. Teoh
Jun 10, 2020
Stefan Koch
Jun 10, 2020
kinke
Jun 10, 2020
kinke
Jun 11, 2020
Walter Bright
Jun 11, 2020
Stefan Koch
Jun 11, 2020
Walter Bright
Jun 11, 2020
kinke
Jun 11, 2020
Walter Bright
Jun 12, 2020
Manu
Jun 12, 2020
Manu
Jun 12, 2020
Avrina
Jun 12, 2020
Avrina
Jun 13, 2020
Manu
Jun 13, 2020
Walter Bright
Jun 13, 2020
Manu
Jun 13, 2020
welkam
Jun 13, 2020
Manu
Jun 09, 2020
Avrina
Jun 12, 2020
Patrick Schluter
Jun 08, 2020
H. S. Teoh
Jun 08, 2020
Stanislav Blinov
Jun 09, 2020
Walter Bright
Jun 09, 2020
Stanislav Blinov
Jun 09, 2020
Walter Bright
Jun 09, 2020
Stanislav Blinov
Jun 09, 2020
Walter Bright
Jun 09, 2020
Manu
Jun 10, 2020
Walter Bright
Jun 10, 2020
Avrina
Jun 10, 2020
jmh530
Jun 10, 2020
Walter Bright
Jun 10, 2020
matheus
Jun 10, 2020
Walter Bright
Jun 10, 2020
Stefan Koch
Jun 10, 2020
Stanislav Blinov
Jun 10, 2020
Walter Bright
Jun 08, 2020
Jonathan M Davis
Jun 09, 2020
Atila Neves
Jun 09, 2020
Walter Bright
Jun 09, 2020
Manu
Jun 10, 2020
Walter Bright
Jun 09, 2020
Manu
Jun 09, 2020
Manu
Jun 09, 2020
Manu
Jun 10, 2020
Walter Bright
Jun 08, 2020
kinke
Jun 08, 2020
Manu
Jun 08, 2020
kinke
Jun 11, 2020
kinke
Jun 12, 2020
Manu
Jun 13, 2020
Walter Bright
Jun 13, 2020
Manu
Jun 13, 2020
Walter Bright
Jun 13, 2020
Walter Bright
Jun 08, 2020
Walter Bright
Jun 08, 2020
Dukc
Jun 09, 2020
9il
Jun 12, 2020
Johan
Jun 13, 2020
Walter Bright
Jun 13, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Walter Bright
Jun 13, 2020
Manu
Jun 13, 2020
Walter Bright
Jun 13, 2020
Johannes Pfau
Jun 21, 2020
Iain Buclaw
Jun 13, 2020
Walter Bright
Jun 14, 2020
Manu
Jun 14, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Manu
Jun 13, 2020
Johannes Pfau
June 08, 2020
Inline has been bugging me forever, it's usually not what I want. The spec says this-or-that, but I think we should take a step back, ignore what's written there, look at the problem space, determine the set of things that we want, and then make sure they're expressed appropriately.

I think a first part of the conversation to understand, is that since D doesn't really have first-class `inline` (just a pragma, assumed to be low-level compiler control), I think most people bring their conceptual definition over from C/C++, and that definition is a little odd (although it is immensely useful), but it's not like what D does.

In C/C++, inline says that a function will be emit to the binary only when
it is called, and the function is marked with internal linkage (it is not
visible to the linker from the symbol table)
By this definition; what inline REALLY means is that the function is not
placed in the binary where it is defined, it is placed in the binary where
it is CALLED, and each CU that calls an inline function receives their own
copy of the function. From here; optimisers will typically inline the call
if they determine it's an advantage to do so.

Another take on inline, and perhaps a more natural take (if your mind is not poisoned by other native languages), is that the function is not actually emit to an object anywhere, it is rather wired directly inline into the AST instead of 'called'. Essentially a form of AST macro.

I reach for inline in C/C++ for various different reasons at different times, and I'd like it if we were able to express each of them:

1. I only want the function to be present in the CALLING binary. I do not want an inline function present in the local binary where it was defined (unless it was called internally). I do not want a linker to see the inline function symbols and be able to link to them externally. [This is about linkage and controlling the binary or distribution environment]

2. I am unhappy that the optimiser chose to not inline a function call, and I want to override that judgement. [This is about micro-optimisation]

3. I want to treat the function like an AST macro; I want the function inserted at the callsite, and I want to have total confidence in this mechanic. [This is about articulate mechanical control over code-gen; ie, I know necessary facts about the execution context/callstack that I expect to maintain]

I think these are the 3 broad categories of behaviour I have ever wanted
control over.
Personally speaking, I am perfectly happy with C/C++'s choice to conflate 1
& 2 into a thing called `inline`, and that's what I want the word 'inline'
to do at an absolute minimum.
The 3rd thing I would term something like `force inline` or perhaps
pragma(inline, force).

D's inline today doesn't do any of those things. It doesn't implement a mechanic that I have ever wanted or known a use for.

Are there non-theoretical use cases I've missed that people have encountered?


June 08, 2020
On Monday, 8 June 2020 at 06:14:44 UTC, Manu wrote:
>
> I think a first part of the conversation to understand, is that since D doesn't really have first-class `inline` (just a pragma, assumed to be low-level compiler control), I think most people bring their conceptual definition over from C/C++, and that definition is a little odd (although it is immensely useful), but it's not like what D does.
>
> In C/C++, inline says that a function will be emit to the binary only when
> it is called, and the function is marked with internal linkage (it is not
> visible to the linker from the symbol table)
> By this definition; what inline REALLY means is that the function is not
> placed in the binary where it is defined, it is placed in the binary where
> it is CALLED, and each CU that calls an inline function receives their own
> copy of the function. From here; optimisers will typically inline the call
> if they determine it's an advantage to do so.
>

Sorry for sticking in my nose, but in result inline in C++ simply tells the linker "this symbol could be present multiple times, just pick whichever one of them and done with it" so it won't complain about multiple symbols anymore.
And that's why you have to slap inline to functions that have body in header in order to build.

But I'm not very certain if that's all about it, not using C++ that much since then, and never to that truly deep extent where any loose bit can destroy performance, not beyond fixing the client's code and some crappy pet projects.
June 08, 2020
On Monday, 8 June 2020 at 06:14:44 UTC, Manu wrote:
> Inline has been bugging me forever, it's usually not what I want. The spec says this-or-that, but I think we should take a step back, ignore what's written there, look at the problem space, determine the set of things that we want, and then make sure they're expressed appropriately.
>
> I think a first part of the conversation to understand, is that since D doesn't really have first-class `inline` (just a pragma, assumed to be low-level compiler control), I think most people bring their conceptual definition over from C/C++, and that definition is a little odd (although it is immensely useful), but it's not like what D does.
>
> In C/C++, inline says that a function will be emit to the binary only when
> it is called, and the function is marked with internal linkage (it is not
> visible to the linker from the symbol table)
> By this definition; what inline REALLY means is that the function is not
> placed in the binary where it is defined, it is placed in the binary where
> it is CALLED, and each CU that calls an inline function receives their own
> copy of the function. From here; optimisers will typically inline the call
> if they determine it's an advantage to do so.
>
> Another take on inline, and perhaps a more natural take (if your mind is not poisoned by other native languages), is that the function is not actually emit to an object anywhere, it is rather wired directly inline into the AST instead of 'called'. Essentially a form of AST macro.

No. I rather see "inline" as a hint for the backend.
DMD is peculiar with its way of inlining.

> I reach for inline in C/C++ for various different reasons at different times, and I'd like it if we were able to express each of them:
>
> 1. I only want the function to be present in the CALLING binary. I do not want an inline function present in the local binary where it was defined (unless it was called internally). I do not want a linker to see the inline function symbols and be able to link to them externally. [This is about linkage and controlling the binary or distribution environment]

what if the function address is took in a delegate ?
It still needs to be there, in the object matching to the CU where it is declared, otherwise there will be surprises, e.g &func in a CU and &func in another will have different addresses.


June 08, 2020
On Monday, 8 June 2020 at 08:45:02 UTC, Basile B. wrote:

> what if the function address is took in a delegate ?
> It still needs to be there, in the object matching to the CU where it is declared, otherwise there will be surprises, e.g &func in a CU and &func in another will have different addresses.

I have _never_ compared addresses of inline functions from different CUs.
How would I even do that?
by storing the function pointer in a global which is visible from multiple translation units?
Is that a valid concern?
Will _any_ project out there break because of that?
June 08, 2020
On Monday, 8 June 2020 at 08:47:36 UTC, Stefan Koch wrote:
> On Monday, 8 June 2020 at 08:45:02 UTC, Basile B. wrote:
>
>> what if the function address is took in a delegate ?
>> It still needs to be there, in the object matching to the CU where it is declared, otherwise there will be surprises, e.g &func in a CU and &func in another will have different addresses.
>
> I have _never_ compared addresses of inline functions from different CUs.
> How would I even do that?
> by storing the function pointer in a global which is visible from multiple translation units?
> Is that a valid concern?
> Will _any_ project out there break because of that?

It's a detail. I just meant that in case where the address of function that is marked for inlining is took then it must still be emitted in the object matching to the declaration unit.
June 08, 2020
On Monday, 8 June 2020 at 09:08:33 UTC, Basile B. wrote:
> On Monday, 8 June 2020 at 08:47:36 UTC, Stefan Koch wrote:
>> On Monday, 8 June 2020 at 08:45:02 UTC, Basile B. wrote:
>>
>>> [...]
>>
>> I have _never_ compared addresses of inline functions from different CUs.
>> How would I even do that?
>> by storing the function pointer in a global which is visible from multiple translation units?
>> Is that a valid concern?
>> Will _any_ project out there break because of that?
>
> It's a detail. I just meant that in case where the address of function that is marked for inlining is took then it must still be emitted in the object matching to the declaration unit.

but of course inlined where it is used as-is.
June 08, 2020
On 6/7/2020 11:14 PM, Manu wrote:
> I think a first part of the conversation to understand, is that since D doesn't really have first-class `inline` (just a pragma, assumed to be low-level compiler control), I think most people bring their conceptual definition over from C/C++, and that definition is a little odd (although it is immensely useful), but it's not like what D does.

C/C++ inline has always been a hint to the compiler, not a command.


> In C/C++, inline says that a function will be emit to the binary only when it is called, and the function is marked with internal linkage (it is not visible to the linker from the symbol table)
> By this definition; what inline REALLY means is that the function is not placed in the binary where it is defined, it is placed in the binary where it is CALLED, and each CU that calls an inline function receives their own copy of the function.

Why does it matter where it is emitted? Why would you want multiple copies of the same function in the binary?


> Another take on inline, and perhaps a more natural take (if your mind is not poisoned by other native languages), is that the function is not actually emit to an object anywhere, it is rather wired directly inline into the AST instead of 'called'. Essentially a form of AST macro.

The problem with this is what is inlined and what isn't is rather fluid, i.e. it varies depending on circumstances and which compiler you use. For example, if you recursively call a function, it's going to have to give up on inlining it. Changes in the compiler can expand or contract inlining opportunities. Having it inline or issue an error is disaster for compiling existing code without constantly breaking it.


> I reach for inline in C/C++ for various different reasons at different times, and I'd like it if we were able to express each of them:
> 
> 1. I only want the function to be present in the CALLING binary. I do not want an inline function present in the local binary where it was defined (unless it was called internally). I do not want a linker to see the inline function symbols and be able to link to them externally. [This is about linkage and controlling the binary or distribution environment]

Why? What is the problem with the emission of one copy where it was defined?


> 2. I am unhappy that the optimiser chose to not inline a function call, and I want to override that judgement. [This is about micro-optimisation]

It's not always possible to inline a function.


> 3. I want to treat the function like an AST macro; I want the function inserted at the callsite, and I want to have total confidence in this mechanic. [This is about articulate mechanical control over code-gen; ie, I know necessary facts about the execution context/callstack that I expect to maintain]

The PR I have on this makes it an informational warning. You can choose to be notified if inlining fails.


> Are there non-theoretical use cases I've missed that people have encountered?

At its root, inlining is an optimization, like deciding which variables go into registers.
June 08, 2020
On 6/8/2020 1:42 AM, evilrat wrote:
> Sorry for sticking in my nose, but in result inline in C++ simply tells the linker "this symbol could be present multiple times, just pick whichever one of them and done with it" so it won't complain about multiple symbols anymore.
> And that's why you have to slap inline to functions that have body in header in order to build.

You're right that the linker expected to combine multiple copies into one.

A more advanced linker will remove unreferenced functions.
June 08, 2020
On Monday, 8 June 2020 at 06:14:44 UTC, Manu wrote:
> D's inline today doesn't do any of those things. It doesn't implement a mechanic that I have ever wanted or known a use for.

We've had this discussion a while back. As of the latest LDC beta, `pragma(inline, true)` functions are now properly emitted into each referencing CU, and will be inlined in most cases (`alwaysinline` LLVM function attribute), even at -O0.

In modules other than the owning one, the function 'copy' is emitted as `available_externally`, meaning that it's *only* available for inlining at the IR level, it will never make it to the assembler and object file.

In its owning module, the function is emitted as a regular function, as a fallback for non-inlined cases (and for when people take its address etc.). Our opinions diverge wrt. whether that's a problem - to me it's clearly no big deal, as the function is a) most likely small, and b) subject to linker stripping if unreferenced.

Wrt. control of which CUs contain which functions, that's totally out of hand anyway due to the way templates are emitted.
June 08, 2020
On 6/7/2020 11:14 PM, Manu wrote:
> [...]

Please provide URLs to the bugzilla issue(s) you have on this topic.

As I've mentioned before, it's easier if you keep a text file of the bugzilla issues that are important to you, so you can copy/paste them where appropriate. Otherwise, both of our times are wasted with "did you file a bugzilla issue for this?"
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11