3

I create an application which make use of a SSE4.1 vector instructions. To better manage the vector types I've created templated helper struct vector_type as follows:

template <class T, int N>
struct vector_type {
   typedef T type __attribute__((vector_size(sizeof(T)*N)));
   using single_element_type = T;
   static constexpr int size = N;
   typedef union {
      type v;
      T s[N];
   } access_type;
   // some other implementation
};

This compiles perfectly with g++. Unfortunately the clang++ (I use clang++ in version 3.6) complains that 'vector_size' attribute requires an integer constant. I'm perfectly aware that this is a well known issue of clang, which is submitted as a Bug 16986. My question is rather is there a way to workaround the problem. I came up with the code:

template <class T, int ASize>
struct vector_type_impl;

template <>
struct vector_type_impl<int,16> {
   typedef int type __attribute__((vector_size(16)));
};

template <class T, int N>
struct vector_type: vector_type_impl<T, N*sizeof(T)> {
   using type = typename vector_type_impl<T, N*sizeof(T)>::type;
   using single_element_type = T;
   static constexpr int size = N;
   typedef union {
      type v;
      T s[N];
   } access_type;
   // some other implementation
};

But I can't believe there is no better way to do it.

W.F.
  • 13,888
  • 2
  • 34
  • 81

2 Answers2

3

I don't like macros either, but it works.

Live Demo

template <class T, int ASize>
struct vector_type_impl;

// Clang bug workaround
#ifdef CLANG_BUG_VECTORTYPE
#error CLANG_BUG_VECTORTYPE should not be defined
#endif

#define CLANG_BUG_VECTORTYPE(T) \
    template <> struct vector_type_impl<T,16> { \
        typedef T type __attribute__((vector_size(16))); \
    };

CLANG_BUG_VECTORTYPE(signed   char);
CLANG_BUG_VECTORTYPE(unsigned char);
CLANG_BUG_VECTORTYPE(signed   short);
CLANG_BUG_VECTORTYPE(unsigned short);
CLANG_BUG_VECTORTYPE(signed   int);
CLANG_BUG_VECTORTYPE(unsigned int);
CLANG_BUG_VECTORTYPE(std::int64_t);
CLANG_BUG_VECTORTYPE(std::uint64_t);
CLANG_BUG_VECTORTYPE(float);
CLANG_BUG_VECTORTYPE(double);

#undef CLANG_BUG_VECTORTYPE

template <class T, int N>
struct vector_type {
   using type = typename vector_type_impl<T, N*sizeof(T)>::type;
   using single_element_type = T;
   static constexpr int size = N;
   typedef union {
      type v;
      T s[N];
   } access_type;
   // some other implementation
};

I took the liberty to write up a typedef for each of the trait types and each of the actual vector types, for every 128-bit SSE vector layout.

typedef vector_type<signed char, 16> sbyte16_vec;
typedef vector_type<signed char, 16> ubyte16_vec;

typedef vector_type<signed short, 8> short8_vec;
typedef vector_type<unsigned short, 8> ushort8_vec;

typedef vector_type<signed int, 4> int4_vec;
typedef vector_type<unsigned int, 4> uint4_vec;

typedef vector_type<std::int64_t, 2> long2_vec;
typedef vector_type<std::uint64_t, 2> ulong2_vec;

typedef vector_type<float, 4> float4_vec;
typedef vector_type<double, 2> double2_vec;

typedef sbyte16_vec::type sbyte16;
typedef ubyte16_vec::type ubyte16;

typedef short8_vec::type short8;
typedef ushort8_vec::type ushort8;

typedef int4_vec::type int4;
typedef uint4_vec::type uint4;

typedef long2_vec::type long2;
typedef ulong2_vec::type ulong2;

typedef float4_vec::type float4;
typedef double2_vec::type double2;

The live demo above tests all of the SSE vector types.

Community
  • 1
  • 1
doug65536
  • 6,562
  • 3
  • 43
  • 53
  • Oh wait, `clang++` doesn't like it. I'll delete answer if I don't find a clang++ solution. – doug65536 May 20 '16 at 07:33
  • 1
    yes probably it's the only way one can achieve it in clang, let's hope they gonna work on it in future versions... – W.F. May 20 '16 at 07:48
2

You can use Clang's OpenCL vector extensions.

Here is a solution which works for GCC, Clang, and ICC.

template <class T, int N>
struct vector_type {
#if defined(__clang__)
  typedef T type __attribute__((ext_vector_type(N)));
#else
  typedef T type __attribute__((vector_size(sizeof(T)*N)));
#endif
  using single_element_type = T;
  static constexpr int size = N;
  typedef union {
    type v;
    T s[N];
  } access_type;
  // some other implementation
};

Clang like ICC only supports a small subset of the GCC vector extensions. But Clang's OpenCL vector extensions cover most of what the GCC vector extensions can do. I made a table here. With the exception of the vector = scalar operation GCC's vector extensions do everything Clang's OpenCL vector extension and more.

Z boson
  • 32,619
  • 11
  • 123
  • 226