<div dir="ltr">On 24 June 2013 22:03, bearophile <span dir="ltr"><<a href="mailto:bearophileHUGS@lycos.com" target="_blank">bearophileHUGS@lycos.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Lately I am playing a little with SIMD in D, and with the work in progress module std.simd, and I have added several related bug reports to Bugzilla.<br>
</blockquote><div><br></div><div>Good man! :)</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

This program compiles with no errors nor warnings with ldc2 on Windows32 bit:<br>
<br>
<br>
import core.simd;<br>
<br>
__gshared immutable int[16]<br>
    a = [ 1,  2,  3,  4,  5,  6,  7,  8, 9, 10, 11, 12, 13, 14, 15, 16],<br>
    b = [16, 15, 14, 13, 12, 11, 10,  9, 8,  7,  6,  5,  4,  3,  2,  1];<br>
__gshared int[16] c;<br>
<br>
void main() {<br>
    auto va = cast(int4[])a;<br>
    auto vb = cast(int4[])b;<br>
    auto vc = cast(int4[])c;<br>
    vc[0] = va[0] + vb[0];<br>
}<br>
<br>
<br>
ldc2 generates this main:<br>
<br>
__Dmain:<br>
    subl    $12, %esp<br>
    movl    $16, 8(%esp)<br>
    movl    $4, 4(%esp)<br>
    movl    $16, (%esp)<br>
    calll   __d_array_cast_len<br>
    movdqa  __D5test51ayG16i, %xmm0<br>
    paddd   __D5test51byG16i, %xmm0<br>
    movdqa  %xmm0, __D5test51cG16i<br>
    xorl    %eax, %eax<br>
    addl    $12, %esp<br>
    ret<br>
<br>
<br>
It uses the instruction movdqa, that assumes a,b and c to be aligned to 16 bytes. But I think there is no guarantee they are.<br></blockquote><div><br></div><div>Those int[16]'s aren't specified as aligned, but I bet LLVM has an optimisation which opportunistically aligns them given some criteria, and then generates code accordingly.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
This is the LL code generated using the -output-ll switch of ldc2 (it's a kind of nearly universal bytecode for llvm):<br>
<br>
@_D5test51ayG16i = global [16 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16]<br>
@_D5test51byG16i = global [16 x i32] [i32 16, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1]<br>
@_D5test51cG16i = global [16 x i32] zeroinitializer<br>
<br>
<br>
If I add a "align(16)" annotation to a, b, c it adds the align 16 annotation in the LL code too:<br></blockquote><div><br></div><div>And so it should, you have now made the alignment explicit. It's not an optimisation anymore, it's an explicit request.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
@_D5test51ayG16i = global [16 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16], align 16<br>
@_D5test51byG16i = global [16 x i32] [i32 16, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1], align 16<br>
@_D5test51cG16i = global [16 x i32] zeroinitializer, align 16<br>
<br>
<br>
Instead of array casts if I cast the pointers the result is similar, but there is no call to __d_array_cast_len (this is a raw cast, so I don't expect much help from the type system here...):<br>
<br>
    auto va = cast(int4*)a.ptr;<br>
    auto vb = cast(int4*)b.ptr;<br>
    auto vc = cast(int4*)c.ptr;<br>
<br>
<br>
I'd like to receive an alignment warning in those cast(int4[]), or the compiler should not use movdqa in such case.</blockquote><div><br></div><div>I suspect that LLVM scheduling a movdqa is permitted only because it has hard evidence during codegen that it is safe to do so.</div>
<div>Try the same thing with separate compilation across link units, see if the presumption of alignment goes away?</div><div><br></div><div>I'm not sure about the warning, it doesn't really sound right to me. Maybe it would be useful... or maybe it would be annoying.</div>
<div>A cast is a cast, it is a deliberate act of reinterpretation... the user needs to take some responsibility in this case.</div><div><br></div><div>Although on the other hand, a cast TO a __vector() (or any aligned type) pointer or array is absolutely useless unless the source pointer is aligned correctly. And in *some* circumstances, the compiler could statically prove this... but in many cases, it probably couldn't.</div>
<div>What happens if you do:</div><div>  int[16] a = [ 1,  2,  3,  4,  5,  6,  7,  8, 9, 10, 11, 12, 13, 14, 15, 16];</div><div>  auto va = cast(int4[])a[1..$]; // ?? .. the offset breaks the alignment. (and now it's too short)</div>
<div><br></div><div>The compiler doesn't only need to consider the alignment of the source pointer, but also the offset at any given time. This is probably impossible.  <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
 This means that maybe __d_array_cast_len should keep and transmit the alignment of its input pointer to the pointer in the output array. And maybe this means the D front-end should keep an alignment information for each pointer (or for pointers that will be used in situations where the alignment is important), integrating it in its type system (and perhaps perform alignment inference like the purity inference done for function templates).<br>

<br>
The alignment of pointers is important for the CPU, so maybe the type system of a system language should keep track of them, and enforce the correctness of the alignments. Maybe this could be done with no further annotation burden for the programmer. A potential problem is how to mix this alignment inference with the needs of separate compilation. I think the align() annotations suffice for that.<br>
</blockquote><div><br></div><div>Yes, kinda like I was saying above. It might be fine if you are explicit with align() statements, but whenever you are sharing pointers between link units, how can you ever retain the information the compiler needs?</div>
<div><br></div><div>I think it's a mistake to make it work in some cases and not others. So for this reason, I maintain that the user just needs to take responsibility for their casts...</div></div></div></div>