Jump to page: 1 2
Thread overview
Can the D compiler detect final and optimize?
Mar 13, 2020
IGotD-
Mar 13, 2020
rikki cattermole
Mar 13, 2020
IGotD-
Mar 13, 2020
Dennis
Dec 25, 2020
Daniel Kozak
Dec 27, 2020
Johan
Dec 27, 2020
Iain Buclaw
Dec 27, 2020
Johan Engelen
Dec 27, 2020
Gregor Mückl
Dec 25, 2020
Daniel Kozak
Dec 25, 2020
kindouchoud
March 13, 2020
A little bit related to that some want class methods to be final by default just like in C++. If I'm not mistaken one benefit of final as default is that the compiler will insert hard coded branches to the method as well as the possibility to do inlining. Are my assumptions correct?

Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself? Benefits would be that a programmer has the possibility to extend about all classes (in C++ would only be possible if class author makes all methods virtual). The final keyword would just mean that a class method is not allowed to be overridden.

Is this possible at all?
March 14, 2020
Why would this be needed?

With ldc -O3 the test function can be completely erased:

import std;
void main()
{
    Foo foo = new Foo;
    foo.x = 7;
    test(foo);
}

void test(Foo foo) {
    writeln(foo.get);
}

class Foo {
    int x;

    int get() { return x; }
}
March 13, 2020
On Friday, 13 March 2020 at 15:15:50 UTC, rikki cattermole wrote:
> Why would this be needed?
>
> With ldc -O3 the test function can be completely erased:
>
> import std;
> void main()
> {
>     Foo foo = new Foo;
>     foo.x = 7;
>     test(foo);
> }
>
> void test(Foo foo) {
>     writeln(foo.get);
> }
>
> class Foo {
>     int x;
>
>     int get() { return x; }
> }

The D programming language by Andrei Alexandrescu. Chapter 6.6.

"So final non-override methods are never subjected to indrect calls; instead they enjoy the same calling convention, low overhead and inlining opportunities as regular functions"

I think I saw a difference between DMD and LDC previously where LDC actually could in some cases infer that the method is final.

If the compiler can infer that a method is final (officially by language standard), then what would the argument for final as default be?

March 13, 2020
On Friday, 13 March 2020 at 15:08:34 UTC, IGotD- wrote:
> Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself?

The problem is that only at runtime are all the derived classes known, and by then the code is already compiled. I think the Java Virtual Machine can automatically elide virtual calls by virtue of being a JIT, but for D this would mean either telling the compiler 'assume all derived classes are present in the source files provided here' or doing fancy link-time optimization.
December 25, 2020
On Friday, 13 March 2020 at 15:08:34 UTC, IGotD- wrote:
> A little bit related to that some want class methods to be final by default just like in C++. If I'm not mistaken one benefit of final as default is that the compiler will insert hard coded branches to the method as well as the possibility to do inlining. Are my assumptions correct?
>
> Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself? Benefits would be that a programmer has the possibility to extend about all classes (in C++ would only be possible if class author makes all methods virtual). The final keyword would just mean that a class method is not allowed to be overridden.
>
> Is this possible at all?

The issue is that just at runtime are for the most part the inferred classes known, and by then the code is as of now arranged.
December 25, 2020
On Fri, Mar 13, 2020 at 5:15 PM Dennis via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On Friday, 13 March 2020 at 15:08:34 UTC, IGotD- wrote:
> > Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself?
>
> The problem is that only at runtime are all the derived classes known, and by then the code is already compiled. I think the Java Virtual Machine can automatically elide virtual calls by virtue of being a JIT, but for D this would mean either telling the compiler 'assume all derived classes are present in the source files provided here' or doing fancy link-time optimization.
>

I believe LTO could do that in some cases


December 25, 2020
On Fri, Dec 25, 2020 at 8:29 PM Daniel Kozak <kozzi11@gmail.com> wrote:

> On Fri, Mar 13, 2020 at 5:15 PM Dennis via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On Friday, 13 March 2020 at 15:08:34 UTC, IGotD- wrote:
>> > Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself?
>>
>> The problem is that only at runtime are all the derived classes known, and by then the code is already compiled. I think the Java Virtual Machine can automatically elide virtual calls by virtue of being a JIT, but for D this would mean either telling the compiler 'assume all derived classes are present in the source files provided here' or doing fancy link-time optimization.
>>
>
> I believe LTO could do that in some cases
>

https://news.ycombinator.com/item?id=17504370


December 27, 2020
On Friday, 25 December 2020 at 19:29:26 UTC, Daniel Kozak wrote:
> On Fri, Mar 13, 2020 at 5:15 PM Dennis via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On Friday, 13 March 2020 at 15:08:34 UTC, IGotD- wrote:
>> > Instead of having final as default, can't the compiler itself infer when a class is implicitly final and do the optimizations itself?
>>
>> The problem is that only at runtime are all the derived classes known, and by then the code is already compiled. I think the Java Virtual Machine can automatically elide virtual calls by virtue of being a JIT, but for D this would mean either telling the compiler 'assume all derived classes are present in the source files provided here' or doing fancy link-time optimization.
>>
>
> I believe LTO could do that in some cases

"Whole program optimization", indeed. Search for `fwhole-program` for GCC and Clang C++ compilers.
I don't know how it works for GDC (I think it may have an edge over LDC on this topic), but for LDC we don't tell the optimizer that our vtables are indeed vtables, so I'm not sure if devirtualization works as well as for Clang (which does inform the optimizer about vtables).

-Johan

December 27, 2020
On Friday, 25 December 2020 at 19:29:26 UTC, Daniel Kozak wrote:
> On Fri, Mar 13, 2020 at 5:15 PM Dennis via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> [...]
>>
>
> I believe LTO could do that in some cases

If LTO devirtualizes, then there is the implicit assumption that there is additional code load at runtime, right? So this breaks potentially if you e.g. use dlopen() to load a plugin?
December 27, 2020
On Sunday, 27 December 2020 at 00:25:54 UTC, Johan wrote:
> On Friday, 25 December 2020 at 19:29:26 UTC, Daniel Kozak wrote:
>>
>> I believe LTO could do that in some cases
>
> "Whole program optimization", indeed. Search for `fwhole-program` for GCC and Clang C++ compilers.
> I don't know how it works for GDC (I think it may have an edge over LDC on this topic), but for LDC we don't tell the optimizer that our vtables are indeed vtables, so I'm not sure if devirtualization works as well as for Clang (which does inform the optimizer about vtables).
>

When `scope` is used, the compiler does constant propagation of the vtable, because what the optimizer sees is:

    MyClass __scopeinit = MyClass.init;
    MyClass* var = &__scopeinit;
    (var.__vptr + 40)();

If the guts of _d_newclass were also made visible (such as, it was templatized in object.d), then such devirtualization through constant propagation would also occur for simple cases of classes new'd on the GC.

Other than that, I'm not sure about other ways to do full devirtualisation of method calls, you are more likely thinking of speculative devirtualization, which looks something like this:

    if ((&var.foo).funcptr is &MyClass.foo)
        MyClass.foo();
    else
        var.foo();

If the direct call is inlined, and if the condition is true, then the resulting code may run about 3-5x faster for simple functions.

Though these days, I think most CPUs have branch prediction for even indirect calls, so if no optimization happens, the speculative devirtualization like the above will just consume code space and branch prediction buffers.
« First   ‹ Prev
1 2