Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use both SSE2 intrinsics and gcc inline assembler

I have tried to mix SSE2 intrinsics and inline assembler in gcc. But if I specify a variable as xmm0/register as input then in some cases I get a compiler error. Example:

#include <emmintrin.h>
int main() {
  __m128i test = _mm_setzero_si128(); 
  asm ("pxor %%xmm0, %%xmm0" : : "xmm0" (test) : );
}

When compiled with gcc version 4.6.1 I get:

>gcc asm_xmm.c
asm_xmm.c: In function ‘main’:
asm_xmm.c:10:3: error: matching constraint references invalid operand number
asm_xmm.c:7:5: error: matching constraint references invalid operand number

The strange thing is that in same cases where I have other input variables/registers then it suddenly works with xmm0 as input but not xmm1, etc. And in another case I was able to specify xmm0-xmm4 but not above. A little confused/frustrated about this :S

Thanks :)

like image 663
Jens Schwarzer Avatar asked Jan 27 '12 21:01

Jens Schwarzer


1 Answers

You should let the compiler do the register assignment. Here's an example of pshufb (for gcc too old to have tmmintrin for SSSE3):

static inline __m128i __attribute__((always_inline))
_mm_shuffle_epi8(__m128i xmm, __m128i xmm_shuf)
{
    __asm__("pshufb %1, %0" : "+x" (xmm) : "xm" (xmm_shuf));
    return xmm;
}

Note the "x" qualifier on the arguments and simply %0 in the assembly itself, where the compiler will substitute in the register it selected.

Be careful to use the right modifiers. "+x" means xmm is both an input and an output parameter. If you are sloppy with these modifiers (eg using "=x" meaning output only when you needed "+x") you will run into cases where it sometimes works and sometimes doesn't.

like image 85
Ben Jackson Avatar answered Nov 19 '22 11:11

Ben Jackson