Missed optimisation case - internal use of STCin

Iain Buclaw via Digitalmars-d digitalmars-d at puremagic.com
Sat Apr 19 07:21:09 PDT 2014


On 19 April 2014 14:33, Artur Skawina via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
> On 04/19/14 14:37, Iain Buclaw via Digitalmars-d wrote:
>> On 19 April 2014 13:02, Artur Skawina via Digitalmars-d
>> <digitalmars-d at puremagic.com> wrote:
>>> On 04/19/14 13:03, Iain Buclaw via Digitalmars-d wrote:
>>>> On Saturday, 19 April 2014 at 10:49:22 UTC, Iain Buclaw wrote:
>>>>> Hi,
>>>>>
>>>>> I'm currently testing out a GCC optimisation that allows you to set call argument flags.  The current assumptions being:
>>>>>
>>>>> in parameters  =>  Assume no escape, no clobber (read-only).
>>>>> ref parameters, classes and pointers  =>  Assume worst case.
>>>>> default  =>  Assume no escape.
>>>>>
>>>>
>>>> That should read:
>>>>
>>>> ref parameters, inout parameters, classes and pointers.
>>>>
>>>> The default of assuming no escape is an experiment - I may limit this to only scalar types, and parameters marked as 'scope'  (So long as no one plans on deprecating it soon :)
>>>
>>> What does "assume no escape" actually mean?
>>> [The above list doesn't really make sense. W/o context, it's
>>> hard to even tell why, hence the question.]
>>>
>>
>> Actually, I might change the default to assume worst case.  I've just
>> tried this out, which is still valid.
>>
>> class C {
>>    int * p;
>>    this(int x) {
>>      p = &x; // escapes the address of the parameter.
>>    }
>> }
>
> This might be currently accepted, but it is clearly invalid
> (escapes local; the only way to make it work safely would
> be to silently copy 'x' to the GC-managed heap, which would be
> way too costly).
>
>
>    A f(A a) { g(&a); return a; } // likewise with ref instead of pointer.
>
> This is OK (even if ideally 'g' should be forbidden from escaping 'a').
>
> Similarly:
>
>    A f(A a) {
>       auto o = register(&a); // can modify 'a'
>       o.blah();              // ditto
>       doneWith(o);           // ditto
>       return a;
>    }
>
>
> What I was wondering was things like whether that "assume no escape"
> property was transitive; if /locally/ escaping was disallowed, and
> to what extent. What does "assume no escape" mean at all? In your
> examples you're mentioning refs together with pointers, that would
> only make sense if no-escape were transitive -- but then treating all
> args as no-escape would be very wrong.
>
>
>> Worse, scope doesn't error on the general case either.
>>
>> class D {
>>    int * p;
>>    this(scope int x) {
>>      p = &x; // escapes the address of the scope parameter.
>>    }
>> }
>
> D's "scope" isn't enforced in any way right now, which means
> that code could exist that is invalid, but currently works. It
> would break silently(!) when compiled with a decent compiler,
> which still doesn't enforce scope.
>

People should get bug fixing soon then.  =)


>> Do these examples give you a good example?
>
> I'm worried about a) invalid assumptions making it into GDC;
> b) certain valid assumptions making into GDC. The latter because
> it could mean that code that's incorrect, but still accepted by
> the other compilers could silently break when compiled with GDC.
>

Invalid assumptions rarely make it into GDC.  The testsuite is a good
bench for this, as well as several projects (now I've got dub set-up)
to test it in the wild.

Saying that, we have had to revert some optimisation cases as D's
schizophrenic nature of enforcing attributes and behaviours is
becoming increasingly dismal.

eg:
- nothrow has *no* guarantee, period, because it still allows
unrecoverable errors being thrown, and allows people to catch said
unrecoverable errors.
- pure is a tough nut to crack also.  The theory should allow you to
be able to cache return values, but in practise...
- The nature of debug statements breaks guarantees of both nothrow and
pure, possibly many more.
- Defining reliable strict aliasing rules, it turns out, is not that
simple (this is something that Walter has mentioned about D should
have good guarantees for, ie: D arrays).

I'm just in investigating all avenues, as I usually do.  There is no
reason why 'in' shouldn't have more powerful guarantees IMO, and what
I've found is not a problem with user code, it's a problem with the
compiler implementation.


For reference, this is the declaration of _adSort in rt.qsort:

extern (C) void[] _adSort(void[], TypeInfo);

This is how the compiler frontend defines the function internally for
its own use:

extern (C) T[] _adSort(in void[], in TypeInfo);


More information about the Digitalmars-d mailing list