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.
Bob Wilson writes:> 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.It _says_ they are defined as structs - but it doesn't show them in use, i.e. it doesn't show how a user of the NEON intrinsics is supposed to be able to make any use of the fact that the types are defined as structs rather than some completely opaque type. All it does is explain why the mangling rule looks the way it does. And whatever the effect of them being structs on the NEON intrinsics programmer might be, it surely wouldn't prevent them being lowered to native types when the struct-ness no longer mattered. And I'd have thought that would be in the front end.> 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.Yes, other problem cases might be int16x4_t x = { 1, 2, 3, 4 }; // gcc only? struct float4: float32x4_t { ... }; // armcc only? We ought to be more specific about the portable subset, and give more guidance on potential portability issues. Probably that would start with a common specification for the NEON intrinsics, independent of any given ARM or GNU compiler release. Al -- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
On Sep 21, 2010, at 6:32 PM, Alasdair Grant wrote:> Bob Wilson writes: >> 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. > > It _says_ they are defined as structs - but it doesn't show them > in use, i.e. it doesn't show how a user of the NEON intrinsics is > supposed to be able to make any use of the fact that the types > are defined as structs rather than some completely opaque type. > All it does is explain why the mangling rule looks the way it does.We can deal with the mangling rule in other ways if necessary. I don't read the mangling rule as necessarily implying anything about the actual data types. The fact remains that ARM's documentation defines these types as structs. A user should NOT be able to take advantage of that -- the types are intentionally opaque.> > And whatever the effect of them being structs on the NEON intrinsics > programmer might be, it surely wouldn't prevent them being lowered > to native types when the struct-ness no longer mattered. And I'd > have thought that would be in the front end.Where that lowering is done is an implementation detail of the compiler, isn't it? The big question is in regard to "whatever the effect of them being structs". As I pointed out, if you follow ARM's approach of making them structs, that has big implications for what types you can use for intrinsic arguments. Most of the vreinterpret intrinsics are only needed if you define the NEON types as structs. If they are GCC-style vectors, you can omit most of the vreinterpret calls.> >> 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. > > Yes, other problem cases might be > > int16x4_t x = { 1, 2, 3, 4 }; // gcc only? > > struct float4: float32x4_t { ... }; // armcc only?Yes, definitely. These are the sorts of things that caused us to define a GCC backward-compatibility option.> > We ought to be more specific about the portable subset, and give > more guidance on potential portability issues. Probably that would > start with a common specification for the NEON intrinsics, independent > of any given ARM or GNU compiler release.That would be great. My experience has been that the using the struct types as defined by ARM is a big nuisance, so if you can find a way to relax your specification to allow other implementations, that would be most welcome.> > Al > > -- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.