August 26, 2009 Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
I just noticed that when a method has a ref parameter for a struct, it doesn't get inlined:
union Matrix4x4 {
struct { float _11, _12, ...}
float[4][4] m;
float[16] v;
Matrix4x4 opMul(const ref Matrix4x4 m) const { ... }
void opMulAssign(const ref Matrix4x4 m) { this = opMul(m); }
void Translate(float x, float y, float z) {
const m = GetTranslation(x, y, z);
opMulAssign(m);
}
static Matrix4x4 GetTranslation(float x, float y, float z) { ... }
}
// RVO and inlining works like a charm here
Matrix4x4 m1 = Matrix4x4.GetTranslation(10, 0, 0);
// No inlining whatsoever here
m1.Translate(0, 1, 0);
I know in C++ when passing by reference (const Matrix4x4& m) the code gets inlned.
It's even worse when using the in (I know it means const scope) storage class for these members:
Matrix4x4 opMul(in Matrix4x4 m) const { ... }
void opMulAssign(in Matrix4x4 m) { this = opMul(m); }
void Translate(float x, float y, float z) {
opMulAssign(GetTranslation(x, y, z));
}
Not only does it not get inlined, but the whole 64bytes of the struct is copied into every stack frame using a bunch of MOVS instructions.
Isn't there a way to implement RVO to work on parameters (PVO?) too if the storage is const? The compiler could even detect that GetTranslation() is going to write to the stack frame of opMulAssign and inline the entire sequence. Even in debug compiles you could skip the whole data copy thing.
For now I pass all my references to any struct larger than 8bytes in my code by explicitely dereferencing (in Matrix4x4* m) to get the inline to work, but that kind of kills the newer syntax of D for such things. I think this should be left for compatibility with C and get the D storage classes working properly to prevent having to use pointers all over D too.
| ||||
August 26, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | On Wed, Aug 26, 2009 at 11:01 AM, Jeremie Pelletier<jeremiep@gmail.com> wrote: > I just noticed that when a method has a ref parameter for a struct, it doesn't get inlined: Here's the bug you want to vote up: http://d.puremagic.com/issues/show_bug.cgi?id=2008 It is indeed a sad situation. --bb | |||
August 26, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter Wrote:
> On Wed, Aug 26, 2009 at 11:01 AM, Jeremie Pelletier<jeremiep@gmail.com> wrote:
> > I just noticed that when a method has a ref parameter for a struct, it doesn't get inlined:
>
> Here's the bug you want to vote up:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=2008
>
> It is indeed a sad situation.
>
> --bb
Just voted, it should be marked as urgent, I can't even begin to imagine the amount of code that will need to be converted back to D syntax once it is fixed.
Thanks.
| |||
August 26, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | Jeremie Pelletier Wrote:
> Bill Baxter Wrote:
>
> > On Wed, Aug 26, 2009 at 11:01 AM, Jeremie Pelletier<jeremiep@gmail.com> wrote:
> > > I just noticed that when a method has a ref parameter for a struct, it doesn't get inlined:
> >
> > Here's the bug you want to vote up:
> >
> > http://d.puremagic.com/issues/show_bug.cgi?id=2008
> >
> > It is indeed a sad situation.
> >
> > --bb
>
> Just voted, it should be marked as urgent, I can't even begin to imagine the amount of code that will need to be converted back to D syntax once it is fixed.
>
> Thanks.
Just to stress out how important this is; I have a small loop calculating a 3x2 rotation matrix used with either Direct2D or Cairo every 10ms which transform the text "Hello World" in a window. CPU usage drops by 7-10% when using C style pointers instead of D storage classes. I haven't even optimized with SSE and whatnot yet, just removing the stack frame initialization overhead.
It would be way worse with the out storage class since the memory also has to be zero filled, which is overkill to me since its much better to just throw an error "out variable x used before initialization".
| |||
August 26, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | Jeremie Pelletier:
> Just to stress out how important this is; I have a small loop calculating a 3x2 rotation matrix used with either Direct2D or Cairo every 10ms which transform the text "Hello World" in a window. CPU usage drops by 7-10% when using C style pointers instead of D storage classes. I haven't even optimized with SSE and whatnot yet, just removing the stack frame initialization overhead.<
Are you in a situation where you use the LDC compiler?
Bye,
bearophile
| |||
August 26, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote:
> Jeremie Pelletier:
>
> > Just to stress out how important this is; I have a small loop calculating a 3x2 rotation matrix used with either Direct2D or Cairo every 10ms which transform the text "Hello World" in a window. CPU usage drops by 7-10% when using C style pointers instead of D storage classes. I haven't even optimized with SSE and whatnot yet, just removing the stack frame initialization overhead.<
>
> Are you in a situation where you use the LDC compiler?
>
> Bye,
> bearophile
DMD 2.031 here on windows 7 x64, I'm writing a Direct2D backend for my display package. I don't mind not having 64-bit support for now, but I definitely care about being on the bleeding edge of the D2 language. I also use the same compiler on Ubuntu.
I use a customized runtime forked from D1 in '06 and almost entirely rewritten kepping up to date with every new D release. I dropped support for D1 last year. Last I heard LDC only supported D1 under unix, haven't checked it in a while.
| |||
August 27, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | Jeremie Pelletier:
> DMD 2.031 here on windows 7 x64, I'm writing a Direct2D backend for my display package. I don't mind not having 64-bit support for now, but I definitely care about being on the bleeding edge of the D2 language. I also use the same compiler on Ubuntu.
>
> I use a customized runtime forked from D1 in '06 and almost entirely rewritten kepping up to date with every new D release. I dropped support for D1 last year. Last I heard LDC only supported D1 under unix, haven't checked it in a while.<
OK, I'm really impressed now.
Bye,
bearophile
| |||
August 28, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | Jeremie Pelletier wrote:
> Isn't there a way to implement RVO to work on parameters (PVO?) too
> if the storage is const?
No, and it doesn't work for C++ either. Consider:
struct S { int a; }
void foo(const ref S s)
{
assert(s.a == 3);
bar();
assert(s.a == 3); // OOPS!
}
S g;
void bar()
{
g.a = 4;
}
void main()
{
foo(g);
}
| |||
August 28, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright Wrote:
> Jeremie Pelletier wrote:
> > Isn't there a way to implement RVO to work on parameters (PVO?) too
> > if the storage is const?
>
> No, and it doesn't work for C++ either. Consider:
>
> struct S { int a; }
>
> void foo(const ref S s)
> {
> assert(s.a == 3);
> bar();
> assert(s.a == 3); // OOPS!
> }
>
> S g;
>
> void bar()
> {
> g.a = 4;
> }
>
> void main()
> {
> foo(g);
> }
Yes but that would be a logic error from the programmer, as it would be possible to do the very same thing had foo been declared as void foo(in S* s).
Isn't it possible to make 'const ref S' or 'in S' generate the same machine code as 'in S*'? To me it would seem the semantics of the two are the same, with 'const S*' being useful syntax for C compatibility while 'in S' and 'const ref S' are both D syntax.
I don't use ref and out whatsoever in D because of their overhead and inability to inline, which is sad because the first time I read about D I pictured having every single parameter in my programs having at least one of in, ref or out and finally saying bye bye to pointers.
| |||
August 28, 2009 Re: Reference value of structs not optimized or inlined? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jeremie Pelletier | Jeremie Pelletier wrote:
> Isn't it possible to make 'const ref S' or 'in S' generate the same
> machine code as 'in S*'? To me it would seem the semantics of the two
> are the same, with 'const S*' being useful syntax for C compatibility
> while 'in S' and 'const ref S' are both D syntax.
The thing about const is it only specifies a read only view of an object, it does *not* specify that the referenced object will not change. That is why pass by value cannot be "optimized" to be pass by reference.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply