On 06/06/12 12:14, Iain Buclaw wrote: > On 5 June 2012 00:24, Artur Skawina <art.08...@gmail.com> wrote: >> On 06/04/12 23:49, Iain Buclaw wrote: >>> On 4 June 2012 21:53, Artur Skawina <art.08...@gmail.com> wrote: >>>> On 06/04/12 21:48, Iain Buclaw wrote: >>>>> On 4 June 2012 19:49, Artur Skawina <art.08...@gmail.com> wrote: >>>>>> Would it be possible to allow give the gcc attribute as a string? >>>>>> So that it would be possible to express 'pragma(attribute, align(8))' etc >>>>>> >>>>>> Because right now you can not do this: >>>>>> >>>>>> pragma(attribute, pure) >>>>>> pragma(attribute, const) >>>> >>>>> You can use underscores as alternate syntax: >>>>> >>>>> pragma(attribute, __pure__) >>>>> pragma(attribute, __const__) >>>>> >>>> >>>> Works, thank you. >>>> >>>> And it even does the right thing - makes the compiler correctly optimize >>>> away calls to pure functions that take const ref/pointer args, which D's >>>> "pure" does not handle yet. >> >> I should probably add that, unlike the D "pure" attribute, GCC will assume >> that you know what you're doing, so it's possible to wrongly tag a function >> as pure using this pragma. >> >>> To get the equivalent of "pure", you need to mark the function as pure >>> nothrow in D. There is no equivalent of "const" yet, but we can >>> discuss ways to go about defining that. :) >> >> No, "pure nothrow" is unfortunately not enough; the only case where it works >> as one might expect if the function takes any pointer/ref arguments, is when >> these args are immutable. >> >> D's pure functions that do not have pointer/ref inputs should map pretty >> well do GCC "const", but from the little testing I did today, it seems >> this already works reasonably well, so the "const" attribute may not be >> needed, the compiler manages to eliminate redundant calls already. >> > > With help of the hints passed to the backend, it should be able to > determine that functions a) with no side effects and b) who's return > value is ignored - should safely discarded.
It should also improve CSE, hoisting out loop invariants etc. >> The problematic case is something like this: >> >> struct S { >> int a,b; >> int[64] c; >> pragma(attribute, noinline, __pure__) bool f() const pure nothrow { >> return a||b; >> } >> } >> >> Without the pragma the compiler will call f() twice when evaluating >> >> S s; auto r = s.f()+s.f(); /*...use r...*/ >> >> I'm told this is by design, which, if true, would prevent a lot of >> valid optimizations. >> >> The (long) story: http://d.puremagic.com/issues/show_bug.cgi?id=8185 >> > > I've just added a change which should give it a better mapping from > keyword to gcc attribute equivalents. > > D keyword -> D frontend representation (depends on function contents > however) -> gcc matched attribute > > pure -> PUREweak -> no vops > pure const -> PUREconst -> const > pure nothrow -> PUREstrong -> pure > > > This means that any pure functions should be guaranteed to be > evaluated once in the use case s.f()+s.f(); - will have a play around > with it though to check for safety / correctness. Hmm, is there a way to see the purity level determined by the frontend, w/o doing any compiler modifications? >> The "noinline", BTW, is for some reason required in both the D-pure >> and GCC-pure cases for the optimization to work. > > This is an optimisation I pulled from ISO C++ into gdc - that all > member functions defined within the body of a class (and in D, this > includes structs too) are to be marked inline. I know. What I'm saying is that omitting the "noinline" attribute causes the "pure" function, like s.f() above, to be called twice. Add the "noinline" back, with no other changes - and it gets called only once. This happens both for "strongly pure" D functions and gcc-pure-tagged functions. It seems that either the optimizer (CSE?) gets confused by the inlining or it treats the case when the function body is available differently. > However, this does not currently work with members outside the current > module we are compiling for. So the next step is to get cross-module > inlining working. That would be great, then i could stop writing code like int f(INLINE=this)(...) {...} :) artur