How to load a small constant into a vector?

131 views Asked by At

Please forgive my ignorance with the question below. We are supporting GCC 4.8 (and above) and IBM XL C/C++ 12 (and above). We are also supporting big and little-endian on AIX and Linux. The compilers and platforms have made the code fairly messy.

We want to load the constant 1 into a VSX register. This is the code we've been able to craft, but it seems wrong because its so complex. The macros XLC_VERSION, GCC_VERSION and LITTLE_ENDIAN have their customary meanings, so the additional preprocessor macros that lead to them have been omitted.

typedef __vector unsigned char      uint8x16_p8;
typedef __vector unsigned long long uint64x2_p8;

#if defined(XLC_VERSION)
    typedef uint8x16_p8 VectorType;
#elif defined(GCC_VERSION)
    typedef uint64x2_p8 VectorType;
#endif

#if defined(LITTLE_ENDIAN)
    const VectorType one = {1};
#else
    const VectorType one = (VectorType)((uint64x2_p8){0,1});
#endif

What's not apparent is, XL C/C++ supports all data arrangements and has a rich API set. The IBM compiler is a breeze to work with (when its not producing warnings and errors that are hard to understand).

GCC going back to 4.8 only supports the 64x2 arrangement and it only has a subset of the APIs. For example, GCC is missing IBM APIs for the 8x16 arrangement and GCC does not have vec_reve (which would make endian reversal easy).

What I really want to do is something like this and have it "just work" everywhere, but it fails to compile:

VectorType one = 1;

Is there a less complex way to load a small constant into a vector register?

2

There are 2 answers

0
Rafik Zurob On

You might want to check the BCD_INIT example here. It uses a macro to reverse the vector initialization.

Regarding vec_reve: It's syntactic sugar for vec_perm. You can implement it as an inline function in a header or as a library function and use it for compilers that don't have it.

0
Jeremy Kerr On

Your example of

VectorType one = 1;

is trying to assign a scalar to a vector. Try using a vector instead. For a 16-char vector, this would be:

vector char one = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

gcc-4.8 seems to compile this okay; I don't have a LE 4.8 handy, but works for big-endian at least:

   0:   10 41 03 0c     vspltisb v2,1

LE with gcc-5 works fine too.

   0:   0c 03 41 10     vspltisb v2,1