[LLVMdev] Vectors in structures

Bob Wilson bob.wilson at apple.com
Tue Sep 21 16:42:38 PDT 2010


On Sep 21, 2010, at 4:33 PM, Sandeep Patel wrote:

> On Tue, Sep 21, 2010 at 11:07 PM, Alasdair Grant <Alasdair.Grant at arm.com> wrote:
>> Bob Wilson writes:
>>> On Sep 21, 2010, at 9:33 AM, Renato Golin wrote:
>>>> I was checking NEON instructions this week and the vector types seem
>>>> to be inside structures. If vector types are considered proper types
>>>> in LLVM, why pack them inside structures?
>>> 
>>> Because that is what ARM has specified?  They define the vector types
>>> that are used with their NEON intrinsics as "containerized vectors".
>>> Perhaps someone on the list from ARM can explain why they did it that
>>> way.
>> 
>> "Containerized Vector" in the ARM AAPCS refers to fundamental data
>> types (machine types), it's the class of machine types comprising
>> the 64-bit and 128-bit NEON machine types.
>> 
>> The AAPCS defines how to pass containerized vectors and it defines
>> how the NEON user types map on to them.  Also it defines how to
>> mangle the NEON user types.  So it defines how to use NEON user
>> types in a public binary interface.
>> 
>> It also says that arm_neon.h "defines a set of internal structures
>> that describe the short vector types" which I guess could be read
>> as saying they are packed inside structures - but I don't think this
>> is the intention and it doesn't match implementations.
>> The arm_neon.h implementation in the ARM compiler defines the user
>> types in terms of C structs called __simd64_int8_t etc. and the
>> mangling originated as an artifact of this.  But the C structs aren't
>> wrapped vectors; they wrap double or a pair of doubles, to get the
>> size and alignment.  Their only purpose is to be recognized by name
>> by the front end and turned into a native register type.
>> In gcc's arm_neon.h the user types aren't structs at all, they're
>> defined using vector_size and the mangling is done as a special case.
>> 
>> So I think there's no need to wrap these types in LLVM.
> 
> They are defined as structures. The table in A.2 defines the exact
> structure names. There is a requirement to mangle them as those
> structures in A.2.1. The fields of the structure may be different in
> this implementation, but the net effect here is that llvm-gcc and
> clang avoid having to magically recognize NEON types and substitute
> the proper mangling for them the way GCC does.

Right.  The contents of the struct don't matter -- the spec is pretty clear about that -- so llvm uses vector types instead of doubles, but your spec definitely shows them being defined as structs.

Beyond that, if you want any sort of cross-compiler portability, you don't want to write code for GCC's implementation.  GCC lets you freely intermix vector types, or at least integer vector types, as long as they have the same total size.  Since ARM's definition says they are structs, if you want portable NEON code, you have to assume that your intrinsic arguments are compatible based on struct type compatibility, i.e., they have to match exactly, even down to signed vs. unsigned element types.  This is a huge hassle.  If you take code written for GCC, you typically end up inserting vreinterpret calls all over the place.  This was such a problem for llvm-gcc that we had to implement an optional GCC-compatibility mode, and we're planning to do something similar for clang using overloaded intrinsics.



More information about the llvm-dev mailing list