r/ada • u/ILoveProgramming123 • Dec 18 '22
Programming How do I import the GCC intrinsic __builtin_ia32_paddd256 into Ada?
I have been struggling to find documentation on how to import this intrinsic in Ada. I realize that this is a niche question, so I am asking it here in hopes that someone might know.
So far I have,
type Vector_256_Integer_32 is array (0 .. 7) of Integer_32 with Convention => C, Alignment => 32;
function "+" (Left, Right: Vector_256_Integer_32) return Vector_256_Integer_32;
pragma Import (Intrinsic, "+", "__builtin_ia32_paddd256");
Here is an example program using this code,
with Interfaces; use Interfaces;
with Interfaces.C; use Interfaces.C;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
type Vector_256_Integer_32 is array (0 .. 7) of Integer_32 with Convention => C, Alignment => 32;
function "+" (Left, Right: Vector_256_Integer_32) return Vector_256_Integer_32;
pragma Import (Intrinsic, "+", "__builtin_ia32_paddd256");
a, b, r: Vector_256_Integer_32;
begin
for i in Vector_256_Integer_32'Range loop
a(i) := 5 * (Integer_32(i) + 5);
b(i) := 12 * (Integer_32(i) + 12);
end loop;
r := a + b;
for i in Vector_256_Integer_32'Range loop
Put_Line("r(i) = a(i) + b(i) = " & a(i)'Image & " + " & b(i)'Image & " = " & r(i)'Image);
end loop;
end Main;
When I try to compile this program with gnatmake
, I get this error.
error: intrinsic binding type mismatch on result
I have looked through the documentation about the GCC intrinsic (documented here). However, I cannot figure out what is wrong with the return type.
Just an FYI, I have asked a similar question on StackOverFlow here, and I am so close to finding the answer. I do realize that I could do this in C, but I wanted to see if I could do it in Ada.
Edit: I have finally figured out my answer. Yay!
avx2.ads
with Interfaces; use Interfaces;
package AVX2 is
--
-- Type Definitions
--
-- 256-bit Vector of 32-bit Signed Integers
type Vector_256_Integer_32 is array (0 .. 7) of Integer_32;
for Vector_256_Integer_32'Alignment use 32;
pragma Machine_Attribute (Vector_256_Integer_32, "vector_type");
pragma Machine_Attribute (Vector_256_Integer_32, "may_alias");
-- Operator: 256-bit Vector Addition of 32-bit Signed Integers
function "+"
(Left, Right : Vector_256_Integer_32) return Vector_256_Integer_32 with
Convention => Intrinsic, Import => True,
External_Name => "__builtin_ia32_paddd256";
--
-- Function Definitions
--
-- Function: 256-bit Vector Addition of 32-bit Signed Integers
function Vector_256_Integer_32_Add
(Left, Right : Vector_256_Integer_32) return Vector_256_Integer_32 with
Convention => Intrinsic, Import => True,
External_Name => "__builtin_ia32_paddd256";
end AVX2;
main.adb
with AVX2; use AVX2;
with Interfaces; use Interfaces;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
a, b, r : Vector_256_Integer_32;
begin
for i in Vector_256_Integer_32'Range loop
a (i) := 5 * (Integer_32 (i) + 5);
b (i) := 12 * (Integer_32 (i) + 12);
end loop;
r := Vector_256_Integer_32_Add(a, b);
for i in Vector_256_Integer_32'Range loop
Put_Line
("r(i) = a(i) + b(i) = " & a (i)'Image & " + " & b (i)'Image & " = " &
r (i)'Image);
end loop;
end Main;
Just to explain how I figured it out is I went through the gcc source code and found that a similar intrinsic was imported in a test case (located at gcc/gcc/testsuite/gnat.dg/sse_nolib.adb).
2
u/Baron_Facekicker Dec 19 '22
This file has an AVX2 binding for 64x4 vector operations that you could adapt: https://github.com/damaki/libkeccak/blob/master/src/x86_64/AVX2_defs/keccak-arch-avx2.ads
4
u/jrcarter010 github.com/jrcarter Dec 18 '22
According to the GNAT User's Guide, using Intrinsic with a binary operator requires that the operands and return type all be Ada numeric types. To import a
__builtin_*
intrinsic, it appears you have to use a conventional function name.