Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 04, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 4 June 2012 19:49, Artur Skawina <art.08.09@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) > > And I just realized that i need these attributes. :) > > Something like > > pragma(attribute, gcc("pure")) > > maybe? > > artur You can use underscores as alternate syntax: pragma(attribute, __pure__) pragma(attribute, __const__) Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0'; |
June 04, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 06/04/12 21:48, Iain Buclaw wrote: > On 4 June 2012 19:49, Artur Skawina <art.08.09@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. Thanks, artur |
June 04, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 4 June 2012 21:53, Artur Skawina <art.08.09@gmail.com> wrote: > On 06/04/12 21:48, Iain Buclaw wrote: >> On 4 June 2012 19:49, Artur Skawina <art.08.09@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. > 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. :) -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0'; |
June 04, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 06/04/12 23:49, Iain Buclaw wrote: > On 4 June 2012 21:53, Artur Skawina <art.08.09@gmail.com> wrote: >> On 06/04/12 21:48, Iain Buclaw wrote: >>> On 4 June 2012 19:49, Artur Skawina <art.08.09@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. 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 The "noinline", BTW, is for some reason required in both the D-pure and GCC-pure cases for the optimization to work. artur |
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 5 June 2012 00:24, Artur Skawina <art.08.09@gmail.com> wrote: > On 06/04/12 23:49, Iain Buclaw wrote: >> On 4 June 2012 21:53, Artur Skawina <art.08.09@gmail.com> wrote: >>> On 06/04/12 21:48, Iain Buclaw wrote: >>>> On 4 June 2012 19:49, Artur Skawina <art.08.09@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. > 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. > 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. 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. Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0'; |
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 06/06/12 12:14, Iain Buclaw wrote: > On 5 June 2012 00:24, Artur Skawina <art.08.09@gmail.com> wrote: >> On 06/04/12 23:49, Iain Buclaw wrote: >>> On 4 June 2012 21:53, Artur Skawina <art.08.09@gmail.com> wrote: >>>> On 06/04/12 21:48, Iain Buclaw wrote: >>>>> On 4 June 2012 19:49, Artur Skawina <art.08.09@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 |
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 06/06/12 17:03, Artur Skawina wrote:
> 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.
What i mean by "called" in this case is of course that the code runs twice when inlined. I was testing with impure bodies, did another test right now, and it seems that it may only happen in that case. But it's hard to tell, as the compiler manages to optimize the really pure inlined parts well. It's just surprising that program behavior changes depending on the availability of function bodies. If this only happens for "illegal" code it's of course not a problem. It does mean that things like debug output change based on inlining decisions though.
artur
|
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 6 June 2012 16:03, Artur Skawina <art.08.09@gmail.com> wrote: > On 06/06/12 12:14, Iain Buclaw wrote: >> On 5 June 2012 00:24, Artur Skawina <art.08.09@gmail.com> wrote: >>> On 06/04/12 23:49, Iain Buclaw wrote: >>>> On 4 June 2012 21:53, Artur Skawina <art.08.09@gmail.com> wrote: >>>>> On 06/04/12 21:48, Iain Buclaw wrote: >>>>>> On 4 June 2012 19:49, Artur Skawina <art.08.09@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'; |
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 06/06/12 18:02, Iain Buclaw wrote: > On 6 June 2012 16:03, Artur Skawina <art.08.09@gmail.com> wrote: >> 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. Thanks. So far, i've been trying not to look inside the compiler at all. ;) >>>> 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. Yes, this was exactly what i was testing with, so that i wouldn't have to look at the generated code each time. Doing things like logging every call to a function, while still wanting it to be treated as pure for optimization purposes can sometimes make sense; it was surprising that program behavior (ie whether the impure logging functions were called or not) depended on inlining decisions. I can't right now think of a test case that does not embed non-pure code inside pure; the truly pure portions could be optimized _after_ the inlining happens, so it is hard to tell if the pure-based CSE worked or not; since in my tests the impure portions remained, I was assuming it did not. If I wanted to try your changes I would need to use the gcc4.8 based tree, right? artur |
June 06, 2012 Re: pragma attribute syntax | ||||
---|---|---|---|---|
| ||||
On 6 June 2012 17:43, Artur Skawina <art.08.09@gmail.com> wrote: > On 06/06/12 18:02, Iain Buclaw wrote: >> On 6 June 2012 16:03, Artur Skawina <art.08.09@gmail.com> wrote: >>> 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. > > Thanks. So far, i've been trying not to look inside the compiler at all. ;) > > >>>>> 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. > > Yes, this was exactly what i was testing with, so that i wouldn't have to look at the generated code each time. > > Doing things like logging every call to a function, while still wanting > it to be treated as pure for optimization purposes can sometimes make > sense; it was surprising that program behavior (ie whether the impure > logging functions were called or not) depended on inlining decisions. > I can't right now think of a test case that does not embed non-pure code > inside pure; the truly pure portions could be optimized _after_ the > inlining happens, so it is hard to tell if the pure-based CSE worked > or not; since in my tests the impure portions remained, I was assuming > it did not. > > If I wanted to try your changes I would need to use the gcc4.8 based tree, right? > > artur Yeah, I go off snapshots rather than getting the source off svn or git (takes far too long). ie: ftp://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/snapshots/LATEST-4.8/ -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0'; |
Copyright © 1999-2021 by the D Language Foundation