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