3
votes

I have a array containing some int values (those at [position%2=0] are negative and those at [position%2=1] are positive).

I want to load those values at a 4 step from the array to the register but I want them inverted (positive converted to negative and vice versa)

__m128i v1;
for (int k = 0; k < limit; k += 4) {
        v1 = _mm_load_si128((__m128i *) & myArray[position + k]);
}

The above SSE code loads the values into register as is: Is there a command to take v1 and inverse it? Can it be done in one step / command? Is it even possible to load the values directly inverted from the original array?

Any help will be appreciated. Thanks in advance.

2
if you want -1 to be 1 and 2 to be -2 then it's called "negation". Inversion is the bitwise not, i.e. invert all bits in the value, so -1 will become 0 - phuclv

2 Answers

4
votes

Assuming your integer elements are 32 bits then you can just subtract from 0, e.g.

v1 = _mm_load_si128(...);                   // load data
v1 = _mm_sub_epi32(_mm_set1_epi32(0), v1);  // negate all elements
2
votes

Another approach would be:

__m128i v1 = _mm_xor_si128(
    _mm_load_si128((__m128i *)&myArray[position + k]), 
    _mm_cmpeq_epi8(v1, v1)
);

Bascially we are doing this: x ^ -1 assuming we are using a machine with twos complement so -1 is a sequence of all ones ...

note the following, where ~ means inversion and ^ means exclusive or.

~0 == 1 == (0 ^ 1)
~1 == 0 == (1 ^ 1)

_mm_cmpeq_epi8(a, a) will set all 1s while you could use _mm_set1_epi32(-1), it may actually be slower since it may generate a memory access, I'd recommend profiling if performance is an issue ...