Thread overview
Alignment of struct containing SIMD field - GDC
Mar 01, 2017
Cecil Ward
Mar 01, 2017
Iain Buclaw
Mar 01, 2017
Johan Engelen
Mar 01, 2017
Iain Buclaw
Mar 02, 2017
Cecil Ward
Mar 02, 2017
Cecil Ward
Mar 02, 2017
Cecil Ward
Mar 02, 2017
Johan Engelen
March 01, 2017
struct vec_struct {
    alias field this;
    bool b;
    int8 field;
    }

In this code when you look at the generated x64 code output by GDC it seems to be doing a nice job, because it has got the offset right for the 256-bit YMM 'field' correct.

Does D automatically propagate the alignment restrictions on the field to the allocation of static structs or structs on the stack?

In this case:

struct vec_struct {
    bool b2;
    struct {
        alias field this;
        bool b;
        int8 field;
        }
    }
it appears that the offset to 'field' is no longer aligned correctly - offset is 40 bytes in GDC. I don't suppose the compiler will use solely unaligned instructions? In any event, I could take the address of field and then pass that to someone expecting to pick up something with guaranteed correct alignment, if I have understood the D docs.

Please don't bite. I'm both new to D and I hope I have understood the x86 SIMD instructions' docs. (Very experienced professional asm and C programmer, but v out-of-date.)

Noob q: I notice that the GDC opcodes look a bit odd, for example the compiler generates a 256-bit unaligned fetch followed by an aligned binary operation (I think), eg a movdqu followed by a vpaddd r, ymm ptr blah - is the latter aligned-only? Apologies if I have got this wrong, need to read up. Would someone sanity-check me?
March 01, 2017
On Wednesday, 1 March 2017 at 06:04:32 UTC, Cecil Ward wrote:
> struct vec_struct {
>     alias field this;
>     bool b;
>     int8 field;
>     }
>
> In this code when you look at the generated x64 code output by GDC it seems to be doing a nice job, because it has got the offset right for the 256-bit YMM 'field' correct.
>
> Does D automatically propagate the alignment restrictions on the field to the allocation of static structs or structs on the stack?
>
> In this case:
>
> struct vec_struct {
>     bool b2;
>     struct {
>         alias field this;
>         bool b;
>         int8 field;
>         }
>     }
> it appears that the offset to 'field' is no longer aligned correctly - offset is 40 bytes in GDC. I don't suppose the compiler will use solely unaligned instructions? In any event, I could take the address of field and then pass that to someone expecting to pick up something with guaranteed correct alignment, if I have understood the D docs.
>

Yeah, it looks like the semantic analysis pass is defeating us here.  It's adding the anonymous struct offset to the aligned field, ignoring completely the original alignment.

Or... the anonymous struct alignment != largest field alignment, which probably is the more likely scenario.

Please raise a bug against DMD.

Simple test case would be:

struct vec_struct {
    bool b2;
    struct {
        bool b;
        int8 field;
    }
}

static assert(vec_struct.b.offsetof == 32);
static assert(vec_struct.field.offsetof == 64);


>
> Noob q: I notice that the GDC opcodes look a bit odd, for example the compiler generates a 256-bit unaligned fetch followed by an aligned binary operation (I think), eg a movdqu followed by a vpaddd r, ymm ptr blah - is the latter aligned-only? Apologies if I have got this wrong, need to read up. Would someone sanity-check me?

The x86 allows unaligned loads.  But if this is referencing the above data structure, you shouldn't be seeing this if the fields were correctly aligned.

March 01, 2017
On Wednesday, 1 March 2017 at 18:34:16 UTC, Iain Buclaw wrote:
>
> Simple test case would be:
>
> struct vec_struct {
>     bool b2;
>     struct {
>         bool b;
>         int8 field;
>     }
> }
>
> static assert(vec_struct.b.offsetof == 32);
> static assert(vec_struct.field.offsetof == 64);

With explicit align(32), it works:
https://godbolt.org/g/3GjOHW

- Johan
March 01, 2017
On Wednesday, 1 March 2017 at 19:09:24 UTC, Johan Engelen wrote:
> On Wednesday, 1 March 2017 at 18:34:16 UTC, Iain Buclaw wrote:
>>
>> Simple test case would be:
>>
>> struct vec_struct {
>>     bool b2;
>>     struct {
>>         bool b;
>>         int8 field;
>>     }
>> }
>>
>> static assert(vec_struct.b.offsetof == 32);
>> static assert(vec_struct.field.offsetof == 64);
>
> With explicit align(32), it works:
> https://godbolt.org/g/3GjOHW
>
> - Johan

Well obviously, because it adheres to explicit alignment.  The compiler just has the wrong idea of how default alignment should work.

Raised bug here, and I'm raising a PR now also. https://issues.dlang.org/show_bug.cgi?id=17237
March 02, 2017
On Wednesday, 1 March 2017 at 22:15:59 UTC, Iain Buclaw wrote:
> On Wednesday, 1 March 2017 at 19:09:24 UTC, Johan Engelen wrote:
>> On Wednesday, 1 March 2017 at 18:34:16 UTC, Iain Buclaw wrote:
>>>
>>> Simple test case would be:
>>>
>>> struct vec_struct {
>>>     bool b2;
>>>     struct {
>>>         bool b;
>>>         int8 field;
>>>     }
>>> }
>>>
>>> static assert(vec_struct.b.offsetof == 32);
>>> static assert(vec_struct.field.offsetof == 64);
>>
>> With explicit align(32), it works:
>> https://godbolt.org/g/3GjOHW
>>
>> - Johan
>
> Well obviously, because it adheres to explicit alignment.  The compiler just has the wrong idea of how default alignment should work.
>
> Raised bug here, and I'm raising a PR now also. https://issues.dlang.org/show_bug.cgi?id=17237

Thanks for your help Iain. And many thanks btw for all the general good work which is very much appreciated by this particular geriatric asm programmer.

I checked the case of XMM alignment, and it's fine.

I presume D does not yet support 512-bit zmm vector objects? (I have seen GDC doing a nice job generating auto-vectorised AVX512 code though - thanks.) The same bug would presumably bite again in that case otherwise?
March 02, 2017
On Wednesday, 1 March 2017 at 22:15:59 UTC, Iain Buclaw wrote:
> On Wednesday, 1 March 2017 at 19:09:24 UTC, Johan Engelen wrote:
>> On Wednesday, 1 March 2017 at 18:34:16 UTC, Iain Buclaw wrote:
>>>
>>> Simple test case would be:
>>>
>>> struct vec_struct {
>>>     bool b2;
>>>     struct {
>>>         bool b;
>>>         int8 field;
>>>     }
>>> }
>>>
>>> static assert(vec_struct.b.offsetof == 32);
>>> static assert(vec_struct.field.offsetof == 64);
>>
>> With explicit align(32), it works:
>> https://godbolt.org/g/3GjOHW
>>
>> - Johan
>
> Well obviously, because it adheres to explicit alignment.  The compiler just has the wrong idea of how default alignment should work.
>
> Raised bug here, and I'm raising a PR now also. https://issues.dlang.org/show_bug.cgi?id=17237

In a dream world where engineers have nothing better to do, it would of course be better to effectively delete the inner anonymous struct so that the two bools could be packed together adjacently. I presume that that is theoretically ok? In contrast, if the sub-struct were named, you could presumably take the address of the entire sub-struct, so the space-inefficient offset to it is something you are just stuck with of course.

A noob question: is it illegal to reorder the fields in a struct? (e.g. so as to optimise packing as far as correct alignment allows) - (C compatibility? Would perhaps need to be an _option_?)
March 02, 2017
On Wednesday, 1 March 2017 at 22:15:59 UTC, Iain Buclaw wrote:
> On Wednesday, 1 March 2017 at 19:09:24 UTC, Johan Engelen wrote:
>> On Wednesday, 1 March 2017 at 18:34:16 UTC, Iain Buclaw wrote:
>>>
>>> Simple test case would be:
>>>
>>> struct vec_struct {
>>>     bool b2;
>>>     struct {
>>>         bool b;
>>>         int8 field;
>>>     }
>>> }
>>>
>>> static assert(vec_struct.b.offsetof == 32);
>>> static assert(vec_struct.field.offsetof == 64);
>>
>> With explicit align(32), it works:
>> https://godbolt.org/g/3GjOHW
>>
>> - Johan
>
> Well obviously, because it adheres to explicit alignment.  The compiler just has the wrong idea of how default alignment should work.
>
> Raised bug here, and I'm raising a PR now also. https://issues.dlang.org/show_bug.cgi?id=17237

Iain, this of course is present in my version of LDC too. (I checked.) You couldn't poke David Nadlinger or whoever for me?
March 02, 2017
On Thursday, 2 March 2017 at 13:00:08 UTC, Cecil Ward wrote:
> 
>> Raised bug here, and I'm raising a PR now also. https://issues.dlang.org/show_bug.cgi?id=17237
>
> Iain, this of course is present in my version of LDC too. (I checked.) You couldn't poke David Nadlinger or whoever for me?

Poke received ;-)

Iain's fix is nicely small, so we can fast-forward it into LDC master.

(probably best to create a small LDC issue for this, so it's not forgotten. Thanks a lot.)

-Johan