7 ms·
Of course C easily allows you to directly write SIMD routines via intrinsic instructions or inline assembly: ``` generic type T is private; Aligne
by exitcode0000 2y ago
Of course C easily allows you to directly write SIMD routines via intrinsic instructions or inline assembly:
```
generic
type T is private;
Aligned : Bool := True;
function Inverse_Sqrt_T (V : T) return T;
function Inverse_Sqrt_T (V : T) return T is
Result : aliased T;
THREE : constant Real := 3.0;
NEGATIVE_HALF : constant Real := -0.5;
VMOVPS : constant String := (if Aligned then "vmovaps" else "vmovups");
begin
Asm (Clobber => "xmm0, xmm1, xmm2, xmm3, memory",
Inputs => (Ptr'Asm_Input ("r", Result'Address),
Ptr'Asm_Input ("r", V'Address),
Ptr'Asm_Input ("r", THREE'Address),
Ptr'Asm_Input ("r", NEGATIVE_HALF'Address)),
Template => VMOVPS & " (%1), %%xmm0 " & E & -- xmm0 ← V
" vrsqrtps %%xmm0, %%xmm1 " & E & -- xmm1 ← Reciprocal sqrt of xmm0
" vmulps %%xmm1, %%xmm1, %%xmm2 " & E & -- xmm2 ← xmm1 \* xmm1
" vbroadcastss (%2), %%xmm3 " & E & -- xmm3 ← NEGATIVE_HALF
" vfmsub231ps %%xmm2, %%xmm0, %%xmm3 " & E & -- xmm3 ← (V - xmm2) \* NEGATIVE_HALF
" vbroadcastss (%3), %%xmm0 " & E & -- xmm0 ← THREE
" vmulps %%xmm0, %%xmm1, %%xmm0 " & E & -- xmm0 ← THREE \* xmm1
" vmulps %%xmm3, %%xmm0, %%xmm0 " & E & -- xmm0 ← xmm3 \* xmm0
VMOVPS & " %%xmm0, (%0) "); -- Result ← xmm0
return Result;
end;
function Inverse_Sqrt is new Inverse_Sqrt_T (Vector_2D, Aligned => False);
function Inverse_Sqrt is new Inverse_Sqrt_T (Vector_3D, Aligned => False);
function Inverse_Sqrt is new Inverse_Sqrt_T (Vector_4D);
```
```C
vector_3d vector_inverse_sqrt(const vector_3d\* v) {
...
vector_4d vector_inverse_sqrt(const vector_4d\* v) {
vector_4d out;
static const float THREE = 3.0f; // 0x40400000
static const float NEGATIVE_HALF = -0.5f; // 0xbf000000
__asm__ (
// Load the input vector into xmm0
"vmovaps (%1), %%xmm0\n\t"
"vrsqrtps %%xmm0, %%xmm1\n\t"
"vmulps %%xmm1, %%xmm1, %%xmm2\n\t"
"vbroadcastss (%2), %%xmm3\n\t"
"vfmsub231ps %%xmm2, %%xmm0, %%xmm3\n\t"
"vbroadcastss (%3), %%xmm0\n\t"
"vmulps %%xmm0, %%xmm1, %%xmm0\n\t"
"vmulps %%xmm3, %%xmm0, %%xmm0\n\t"
"vmovups %%xmm0, (%0)\n\t" // Output operand
:
: "r" (&out), "r" (v), "r" (&THREE), "r" (&NEGATIVE_HALF) // Input operands
: "xmm0", "xmm1", "xmm2", "memory" // Clobbered registers
);
return out;
}
```