Jump to page: 1 24  
Page
Thread overview
Reference value of structs not optimized or inlined?
Aug 26, 2009
Jeremie Pelletier
Aug 26, 2009
Bill Baxter
Aug 26, 2009
Jeremie Pelletier
Aug 26, 2009
Jeremie Pelletier
Aug 26, 2009
bearophile
Aug 26, 2009
Jeremie Pelletier
Aug 27, 2009
bearophile
Aug 28, 2009
Walter Bright
Aug 28, 2009
Jeremie Pelletier
Aug 28, 2009
Walter Bright
Aug 28, 2009
downs
Aug 28, 2009
Jeremie Pelletier
Aug 28, 2009
Walter Bright
Aug 28, 2009
Walter Bright
Aug 29, 2009
Ary Borenszweig
Aug 29, 2009
Bill Baxter
Aug 29, 2009
Walter Bright
Aug 29, 2009
Christopher Wright
Aug 29, 2009
Ary Borenszweig
Aug 29, 2009
Walter Bright
Aug 29, 2009
Jeremie Pelletier
Aug 29, 2009
davidl
Aug 29, 2009
Walter Bright
Aug 29, 2009
Walter Bright
Aug 30, 2009
davidl
Aug 30, 2009
Bill Baxter
Aug 29, 2009
Dominik
Aug 29, 2009
dsimcha
Aug 29, 2009
Walter Bright
Aug 28, 2009
Bill Baxter
Aug 28, 2009
Brad Roberts
Aug 29, 2009
Bill Baxter
Aug 30, 2009
Don
Aug 30, 2009
Jason House
Aug 30, 2009
Walter Bright
August 26, 2009
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
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
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
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
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
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
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
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
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
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.

« First   ‹ Prev
1 2 3 4