On 6 June 2012 16:03, Artur Skawina <art.08...@gmail.com> wrote: > 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? > >
Unfortunately not. I can tell you that the modification would be to d-decls.cc:(FuncDeclaration::toSymbol) - adding a fprintf(stderr) with the purity value - hint, it's an enum. >>> 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. > Could you provide some examples? I can only think of this occurring for functions that have arbituary side effects. ie: if you insert debug printf statements into pure functions. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';