www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Alignment of struct containing SIMD field - GDC

reply Cecil Ward <d cecilward.com> writes:
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?
Feb 28 2017
parent reply Iain Buclaw <ibuclaw gdcproject.org> writes:
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.
Mar 01 2017
parent reply Johan Engelen <j j.nl> writes:
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
Mar 01 2017
parent reply Iain Buclaw <ibuclaw gdcproject.org> writes:
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
Mar 01 2017
next sibling parent Cecil Ward <d cecilward.com> writes:
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?
Mar 01 2017
prev sibling next sibling parent Cecil Ward <d cecilward.com> writes:
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_?)
Mar 01 2017
prev sibling parent reply Cecil Ward <d cecilward.com> writes:
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?
Mar 02 2017
parent Johan Engelen <j j.nl> writes:
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
Mar 02 2017