Reference value of structs not optimized or inlined?

Jeremie Pelletier jeremiep at gmail.com
Wed Aug 26 11:01:21 PDT 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.



More information about the Digitalmars-d mailing list