Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

Integer vector literal initializer in ICC

emmetcaulfield
Beginner
1,200 Views

Is it possible to set the value of a vector of integers with a literal initializer?

For example, it is possible to do:

__m128 x={1.0f,2.0f,3.0f,4.0f};

... and the slots of x are successfully initialized to the values 1.0, 2.0, 3.0, and 4.0 as expected. However, if one attempts

__m128i x={1,2,3,4};

... one finds that the first slot of x is 0x04030201 and the other three slots are all zero. Obviously _mm_set_epi32() provides a fine solution for variables, but what about constants (and convenience)?

So, the question is, is it possible with ICC to do something like:

const __m128i x={1,2,3,4};

...having the obvious intended semantics (as in GCC), without having to do something like:

const __m128i x={1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0};

...or am I just plain out of luck?

0 Kudos
8 Replies
levicki
Valued Contributor I
1,200 Views

_mm_set_epi32() (or _mm_setr_epi32) will get replaced with a constant in data segment and a MOVDQA instruction - I really don't see a reason not to use it.

0 Kudos
emmetcaulfield
Beginner
1,200 Views
Quoting - Igor Levicki

_mm_set_epi32() (or _mm_setr_epi32) will get replaced with a constant in data segment and a MOVDQA instruction - I really don't see a reason not to use it.

Hi. Thanks for your suggestion.

I suppose the answer to my question is no, then.

I'd agree with you entirely except that the following construct is forbidden:

const foo=_mm_set_epi32(1,2,3,4);

I'm generating multithreaded code from XML with a lot of read-only constants that can be shared between threads. Heretofore, I've been able to #define them or declare them const and let gcc worry about it. I could, I suppose, declare them with file scope and then add an initialisation function (with a long series of foo=_mm_set_epi32(1,2,3,4);-like lines), called before the threads are created, but that's very ugly, and could conceivably frustrate some compiler optimisations that depend on constants being recognizable as such at compile-time. Unfortunately, it seems that there's no good solution that's portable between icc and gcc.

It turns out that supporting icc requires drastic refactoring for other reasons (icc not being able to use vectors as operands to regular arithmetic operators), which makes support for it (really just an experimental afterthought) a lot more trouble than it's worth for me, so the question is now moot anyway.

Thanks again.

Emmet.

0 Kudos
levicki
Valued Contributor I
1,200 Views

I am not sure how you came to the conclusion that such a construct is forbidden, but for me the following code compiled with icl /c /Od /FAs test.c:

#include 

void test(void)
{
	const __m128i x = _mm_set_epi32(1,2,3,4);
}

Compiles successfully and the assembler code looks like this:

...
        push      ebx
        mov       ebx, esp
        and       esp, -16
        push      ebp
        push      ebp
        mov       ebp, DWORD PTR [ebx+4]
        mov       DWORD PTR [esp+4], ebp
        mov       ebp, esp
        sub       esp, 24

;;; 	const __m128i x = _mm_set_epi32(1,2,3,4);

        movdqa    xmm0, XMMWORD PTR _set_pi_cnst$1
        movdqa    XMMWORD PTR [ebp-24], xmm0

        leave
        mov       esp, ebx
        pop       ebx
        ret
...
_RDATA	SEGMENT DWORD PUBLIC FLAT 'DATA'
_set_pi_cnst$1	DD	4
		DD	3
		DD	2
		DD	1
_RDATA	ENDS

I suggest you give it another try.

0 Kudos
emmetcaulfield
Beginner
1,200 Views

I honestly never thought of declaring the constants in function scope because they're used all over the place in the code. Both gcc and icc do complain about such a declaration in file scope. Right now, they're in macros that are used extensively in different functions, although that might not be very hard to work around. I wonder if I would get away with using _mm_set_epi32(1,2,3,4) instead of ((v4si){1,2,3,4}) as I do at the moment (for gcc). Off the top of my head, I can't see any reason why not, and it probably wouldn't be any worse than what I'm already doing.

Thanks again for your help and time: you've been very helpful.

0 Kudos
levicki
Valued Contributor I
1,200 Views

You are welcome.

It may be a problem if you have a need for global constants but there is also a way around that, namely:

// global scope (file level)
#define ALIGN	__declspec(align(16))
ALIGN	const int cvx[4] = { 1, 2, 3, 4 };

And then later in the code you write:

_mm_load_si128((__m128i*)&cvx)

In the place of yourx variable. It will generate the same MOVDQA instruction.

0 Kudos
Lars_Petter_E_1
Beginner
1,200 Views

Usually it is better for the compiler to decide which instructions to use and rely on automatic vectorization. If the code using the constant is automatically vectorized, no intrinsics are needed, because the constant is stored as a 128 bit value, like this

__declspec(align(16)) static const int cvx[4] = { 1, 2, 3, 4 };

movdqa xmm0, XMMWORD PTR cvx$301$0$0

In another case when code is not suitable for vector instructions, other isntructions may be preferred to load the data - let the compiler decide!

Best Regards,

Lars Petter Endresen

0 Kudos
levicki
Valued Contributor I
1,200 Views
Lars, if __m128i x={1,2,3,4}; was possible then he wouldn't have to chose on his own. I just presented him with several workarounds for his issue so he can pick the best one for his application instead of giving up on Intel compiler.
0 Kudos
annfisher
Beginner
1,200 Views

Usually it is better for the compiler to decide which instructions to use and rely on automatic vectorization. If the code using the constant is automatically vectorized, no intrinsics are needed, because the constant is stored as a 128 bit value, like this

__declspec(align(16)) static const int cvx[4] = { 1, 2, 3, 4 };

movdqa xmm0, XMMWORD PTR cvx$301$0$0

In another case when code is not suitable for vector instructions, other isntructions may be preferred to load the data - let the compiler decide!

Best Regards,

Lars Petter Endresen

0 Kudos
Reply