On 15 October 2012 16:34, jerro <span dir="ltr"><<a href="mailto:a@a.com" target="_blank">a@a.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Monday, 15 October 2012 at 12:19:47 UTC, Manu wrote:<br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">
On 15 October 2012 02:50, jerro <<a href="mailto:a@a.com" target="_blank">a@a.com</a>> wrote:<br>
<br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">
Speaking of test – are they available somewhere? Now that LDC at least<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
theoretically supports most of the GCC builtins, I'd like to throw some<br>
tests at it to see what happens.<br>
<br>
David<br>
<br>
</blockquote>
<br></div>
I have a fork of std.simd with LDC support at <a href="https://github.com/jerro/**" target="_blank">https://github.com/jerro/**</a><br>
phobos/tree/std.simd <<a href="https://github.com/jerro/phobos/tree/std.simd" target="_blank">https://github.com/jerro/<u></u>phobos/tree/std.simd</a>> and<br>
some tests for it at <a href="https://github.com/jerro/std.**simd-tests" target="_blank">https://github.com/jerro/std.*<u></u>*simd-tests</a><<a href="https://github.com/jerro/std.simd-tests" target="_blank">https://github.<u></u>com/jerro/std.simd-tests</a>>.<br>

<br>
</blockquote><div class="im">
<br>
Awesome. Pull request plz! :)<br>
</div></blockquote>
<br>
I did change an API for a few functions like loadUnaligned, though. In those cases the signatures needed to be changed because the functions used T or T* for scalar parameters and return types and Vector!T for the vector parameters and return types. This only compiles if T is a static array which I don't think makes much sense. I changed those to take the vector type as a template parameter. The vector type can not be inferred from the scalar type because you can use vector registers of different sizes simultaneously (with AVX, for example). Because of that the vector type must be passed explicitly for some functions, so I made it the first template parameter in those cases, so that Ver doesn't always need to be specified.<br>

<br>
There is one more issue that I need to solve (and that may be a problem in some cases with GDC too) - the pure, @safe and @nothrow attributes. Currently gcc builtin declarations in LDC have none of those attributes (I have to look into which of those can be added and if it can be done automatically). I've just commented out the attributes in my std.simd fork for now, but this isn't a proper solution.<div class="im">
<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
That said, how did you come up with a lot of these implementations? Some<br>
don't look particularly efficient, and others don't even look right.<br>
xor for instance:<br>
return cast(T) (cast(int4) v1 ^ cast(int4) v2);<br>
<br>
This is wrong for float types. x86 has separate instructions for doing this<br>
to floats, which make sure to do the right thing by the flags registers.<br>
Most of the LDC blocks assume that it could be any architecture... I don't<br>
think this will produce good portable code. It needs to be much more<br>
cafully hand-crafted, but it's a nice working start.<br>
</blockquote>
<br></div>
The problem is that LLVM doesn't provide intrinsics for those operations. The xor function does compile to a single xorps instruction when compiling with -O1 or higher, though. I have looked at the code generated for many (most, I think, but not for all possible types) of those LDC blocks and most of them compile to the appropriate single instruction when compiled with -O2 or -O3. Even the ones for which the D source code looks horribly inefficient like for example loadUnaligned.<br>

<br>
By the way, clang does those in a similar way. For example, here is what clang emits for a wrapper around _mm_xor_ps when compiled with -O1 -emit-llvm:<br>
<br>
define <4 x float> @foo(<4 x float> %a, <4 x float> %b) nounwind uwtable readnone {<br>
  %1 = bitcast <4 x float> %a to <4 x i32><br>
  %2 = bitcast <4 x float> %b to <4 x i32><br>
  %3 = xor <4 x i32> %1, %2<br>
  %4 = bitcast <4 x i32> %3 to <4 x float><br>
  ret <4 x float> %4<br>
}<br>
<br>
AFAICT, the only way to ensure that a certain instruction will be used with LDC when there is no LLVM intrinsic for it is to use inline assembly expressions. I remember having some problems with those in the past, but it could be that I was doing something wrong. Maybe we should look into that option too.<br>

</blockquote></div><br><div>Inline assembly usually ruins optimising (code reordering around inline asm blocks is usually considered impossible).</div><div>It's interesting that the x86 codegen makes such good sense of those sequences, but I'm rather more concerned about other platforms. I wonder if other platforms have a similarly incomplete subset of intrinsics? :/</div>