January 05, 2012
Jesse Phillips:

> > class Foo {
> >   string name = "c1";
> >   static void foo() {}
> > }
> > class Bar : Foo {
> >   string name = "c2";
> >   static void foo() {} // silent method hiding
> > }
> > void main() {}
> 
> Should we just disallow this?

Sometimes it's an useful idiom, and probably some D code in the wild is using it already, so I don't think we should disallow it.

I was just asking to force it to be syntactically explicit, just like override will do in D2. It seems Delphi too does the same thing using a different keyword (this is not too much surprising, the language designers are partially the same).

So far I have seen no arguments against the requirement (initially just a warning if you compile with -w) to use a keywords as "new" there, while I have reasons for it in both my object oriented code and C# language design :-)


> If the function wasn't static it would just override foo. Or is that changing once override is required?

Override usage is going to be (hopefully soon) compulsory in D (currently you need -w to see an error). So that code without both static and override is going to be refused :-)

Bye,
bearophile
January 05, 2012
On 5/01/12 10:17 PM, Iain Buclaw wrote:
> On 5 January 2012 22:11, Manu<turkeyman@gmail.com>  wrote:
>> So regarding my assumptions about translating the D front end expressions to
>> GCC? Is that all simpler than I imagine?
>> Do you think GDC generates optimal code comparable to C code?
>>
>> What about pure functions, can you make good on optimisations like caching
>> results of pure functions, moving them outside loops, etc?
>>
>>
>
> I think you are confusing the pure with memoization.  I could be wrong
> however... :)
>

I think Manu is right:

void foo(int x)
{
    int[10] a;
    foreach (ref e; a)
        e = bar(x);
}

If bar is pure then you can safely transform this into:

void foo(int x)
{
    int[10] a;
    auto barx = bar(x);
    foreach (ref e; a)
        e = barx;
}
January 05, 2012
On 5/01/12 10:17 PM, Iain Buclaw wrote:
> On 5 January 2012 22:11, Manu<turkeyman@gmail.com>  wrote:
>> So regarding my assumptions about translating the D front end expressions to
>> GCC? Is that all simpler than I imagine?
>> Do you think GDC generates optimal code comparable to C code?
>>
>> What about pure functions, can you make good on optimisations like caching
>> results of pure functions, moving them outside loops, etc?
>>
>>
>
> I think you are confusing the pure with memoization.  I could be wrong
> however... :)
>

I think Manu is right:

void foo(int x)
{
    int[10] a;
    foreach (ref e; a)
        e = bar(x);
}

If bar is pure then you can safely transform this into:

void foo(int x)
{
    int[10] a;
    auto barx = bar(x);
    foreach (ref e; a)
        e = barx;
}

If bar is not pure then this transformation would be unsafe.
January 05, 2012
On 5 January 2012 23:40, Peter Alexander <peter.alexander.au@gmail.com> wrote:
> On 5/01/12 10:17 PM, Iain Buclaw wrote:
>>
>> On 5 January 2012 22:11, Manu<turkeyman@gmail.com>  wrote:
>>>
>>> So regarding my assumptions about translating the D front end expressions to
>>>
>>> GCC? Is that all simpler than I imagine?
>>> Do you think GDC generates optimal code comparable to C code?
>>>
>>> What about pure functions, can you make good on optimisations like
>>> caching
>>> results of pure functions, moving them outside loops, etc?
>>>
>>>
>>
>> I think you are confusing the pure with memoization.  I could be wrong however... :)
>>
>
> I think Manu is right:
>
> void foo(int x)
> {
>    int[10] a;
>    foreach (ref e; a)
>        e = bar(x);
> }
>
> If bar is pure then you can safely transform this into:
>
> void foo(int x)
> {
>    int[10] a;
>    auto barx = bar(x);
>    foreach (ref e; a)
>        e = barx;
> }
>
> If bar is not pure then this transformation would be unsafe.

Yes, it will do something like that, though the loop will be unrolled - and given that gdc supports vectorisation, I think that above example will likely be vectorised too.  So off the top of my head:

void foo(int x)
{
   auto barx = bar(x);
   vector(4) vect = { barx, barx, barx, barx };
   *[&a] = vect;
   *[&a+16] = vect;
   a[9] = barx;
   a[10] = barx;
}



Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
January 05, 2012
On 1/5/2012 1:58 PM, Manu wrote:
> On 5 January 2012 23:34, Walter Bright <newshound2@digitalmars.com
> <mailto:newshound2@digitalmars.com>> wrote:
>
>     On 1/5/2012 3:58 AM, Manu wrote:
>
>         How is this possible, when all functions are virtual, without whole program
>         optimisation?
>
>
>     Only public non-final class member functions are virtual. Furthermore, as in
>     C++, the compiler can sometimes determine that a virtual function is being
>     called directly, and will do so (or inline it).
>
>
> Can you define 'sometimes'?

In C++, it does it if it's a.foo() rather than pa->foo(). In D, it can be done if flow analysis proves that whatever is calling foo() is really an a, and not something derived from a. Also, if you qualify the member call with the class name, it gets called directly, as in a.C.foo().
January 05, 2012
On 1/5/2012 2:57 PM, Sean Kelly wrote:
> For the record, some compilers do optimize across asm blocks.  It's simply
> DMD/DMC that doesn't.  Though the lack of "volatile" makes doing this unsafe
> in D as a general rule.

dmd does keep track of register usage within asm blocks.
January 05, 2012
Peter Alexander:

> void foo(int x)
> {
>      int[10] a;
>      foreach (ref e; a)
>          e = bar(x);
> }
> 
> If bar is pure then you can safely transform this into:
> 
> void foo(int x)
> {
>      int[10] a;
>      auto barx = bar(x);
>      foreach (ref e; a)
>          e = barx;
> }

If bar is pure, but it throws exceptions, the two versions of the code behave differently, so it's a wrong optimization. You need bar to be pure nothrow.

Moving pure nothrow functions out of loops is an easy optimization, and even simple D compilers are meant to do it. Aggressively optimizing D compilers are also free to memoize some results of pure (and probably nothrow too) functions.

-------

Regarding the discussion about virtual functions, show me a D compiler able to de-virtualize very well, as the Oracle JVM does :-)
Time ago I have asked LLVM devs to improve this situation for LDC, they have now fixed most of my bug reports, so I think they will eventually fix this too (maybe partially):
http://llvm.org/bugs/show_bug.cgi?id=3100

Bye,
bearophile
January 06, 2012
On 1/5/2012 1:03 PM, Manu wrote:
>     That is the case with overriding a non-virtual function - the compiler will
>     compile it anyway, and most of the time it will work. That's what makes it
>     so eeevil.
>
>
> I saw today, or last night, someone suggesting a keyword to make non-virtual
> override explicit, and error otherwise. Which actually sounded like a really
> good idea to me, and also addresses this problem.

That's correct, it does address it. But not for C++.

>     The right thing should be the default.
> But I fundamentally disagree your choice is 'right'..

Sure.

> This is obviously subjective, so I don't think that's a fair assertion.

By 'right', I don't necessarily mean 'the most efficient'. I mean that the code should be correct. It's ok if extra work is involved in creating the most efficient version. For example:

    int a;

automatically initializes a to zero. This is correct. If you want it to remain uninitialized,

    int a = void;

which will be faster in the cases where the compiler cannot optimize away a redundant initialization of a. But, it is dangerous because the compiler cannot always prove that a is initialized before use, hence it is not the default.


> But as I've previously said, I understand this can't change now, I've let it go :P

I understand, I'm just explaining my point of view, and you're just explaining yours.
January 06, 2012
On 1/5/2012 1:43 PM, Manu wrote:
> On 5 January 2012 23:30, Walter Bright <newshound2@digitalmars.com
> <mailto:newshound2@digitalmars.com>> wrote:
>
>     On 1/5/2012 8:49 AM, Manu wrote:
>
>         I also wonder if the D language provides some opportunities for optimisation
>         that aren't expressible in other languages,
>
>
>     There are some. One that is currently being exploited by the optimizer and
>     back end is the existence of pure functions.
>
>
> Does GDC currently support these same optimisations, or is this a DMD special power?

I don't know what GDC does.
January 06, 2012
On 6 January 2012 00:03, Walter Bright <newshound2@digitalmars.com> wrote:
> On 1/5/2012 1:43 PM, Manu wrote:
>>
>> On 5 January 2012 23:30, Walter Bright <newshound2@digitalmars.com
>>
>> <mailto:newshound2@digitalmars.com>> wrote:
>>
>>    On 1/5/2012 8:49 AM, Manu wrote:
>>
>>        I also wonder if the D language provides some opportunities for
>> optimisation
>>        that aren't expressible in other languages,
>>
>>
>>    There are some. One that is currently being exploited by the optimizer
>> and
>>    back end is the existence of pure functions.
>>
>>
>> Does GDC currently support these same optimisations, or is this a DMD special power?
>
>
> I don't know what GDC does.

GDC ties D optimisations to function attributes of GCC, so you'll have do you some reading up on the meaning. :)

There are three levels of purity, these are matched to are const, pure and novops attributes.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';