Are SSE / AVX static / static local variables blocking the xmm / ymm register?

When using the built-in SSE functions, zero vectors are often required. One way to avoid creating a null variable inside a function whenever a function is called (every time you actually call some vector xor statement), you should use a static local variable, as in

static inline __m128i negate(__m128i a)
{
   static __m128i zero = __mm_setzero_si128();
   return _mm_sub_epi16(zero, a);
}

It seems that the variable is only initialized when the function is called for the first time. (I checked this by calling the true function instead of the built-in _mm_setzero_si128 (). This, apparently, is only possible in C ++, not in C.)

(1) However, as soon as this initialization occurred: does the xmm register block the rest of the program?

(2) Even worse: if such a static local variable is used in several functions, will it block multiple xmm registers?

(3) Another way: if it does not block the xmm register, does the zero variable from memory always reload when the function is called? Then a static local variable would be pointless, since it would be faster to use _mm_setzero_si128 ().

As an alternative, I thought about putting zero in a global static variable that would be initialized when the program started:

static __m128i zero = _mm_setzero_si128();

(4) Will the global variable remain in the xmm register during program execution?

Many thanks for your help!

(Since this also applies to embedded AVX, I also added the AVX tag.)

+4
source share
4

, : . xor . x86 ; no ฮผop . , , - , .

( , ), setzero .

+9

, Stephen Canon,

static inline Vec8s operator - (Vec8s const & a) {
    return _mm_sub_epi16(_mm_setzero_si128(), a);
}

Agner Fog Vector Class Library.

, static. static, . ( .bss) .

#include <x86intrin.h>
extern "C" void foo2(__m128i a);

static const __m128i zero = _mm_setzero_si128();

static inline __m128i negate(__m128i a) {
    return _mm_sub_epi16(zero, a);
}

extern "C" void foo(__m128i a, __m128i b) {
    foo2(negate(a));
}

g++ -O3 -c static.cpp, . .bss _ZL4zero. , .bss.

.text.startup
    pxor    xmm0, xmm0
    movaps  XMMWORD PTR _ZL4zero[rip], xmm0
    ret

foo

    movdqa  xmm1, XMMWORD PTR _ZL4zero[rip]
    psubw   xmm1, xmm0
    movdqa  xmm0, xmm1

, GCC XMM . .

, _mm_sub_epi16(_mm_setzero_si128(),a)? GCC foo

    pxor    xmm1, xmm1
    psubw   xmm1, xmm0
    movdqa  xmm0, xmm1

Intel Sandy Bridge pxor "". . , , , , .

, _mm_sub_epi16(_mm_set1_epi32(-1),a). GCC

    pcmpeqd xmm1, xmm1
    psubw   xmm1, xmm0
    movdqa  xmm0, xmm1

pcmpeqd free , - , movdqa. , 0 -1 . _mm_sub_epi16(_mm_set1_epi32(1))? GCC foo

    movdqa  xmm1, XMMWORD PTR .LC0[rip]
    psubw   xmm1, xmm0
    movdqa  xmm0, xmm1

, ! , , .LC0 (.rodata).

: GCC .

register __m128i zero asm ( "xmm15" ) = _mm_set1_epi32 (1);

movdqa  xmm2, xmm15
psubw   xmm2, xmm0
movdqa  xmm0, xmm2
+5

, .

, , . . . , .

, , . , , , , . .

, . , .

+2

, , _mm_abs_ps().

static inline __m128 _mm_abs_ps_2(__m128 x) {
  __m128 signMask = _mm_set1_ps(-0.0F);
  return _mm_andnot_ps(signMask, x);
}

(Agner Fog VCL http://www.agner.org/optimize/#vectorclass set1, cast AND , )

float *p = data;
for (int i = 0; i < LEN; i += 4, p += 4)
  _mm_store_ps(p, _mm_abs_ps_2(_mm_load_ps(p)));

gcc (4.6.3, -O3) , _mm_set1_ps :

    vmovaps xmm1, XMMWORD PTR .LC1[rip] # tmp108,
    mov rax, rsp    # p,
.L3:
    vandnps xmm0, xmm1, XMMWORD PTR [rax]   # tmp102, tmp108, MEM[base: p_54, offset: 0B]
    vmovaps XMMWORD PTR [rax], xmm0 # MEM[base: p_54, offset: 0B], tmp102
    add rax, 16 # p,
    cmp rax, rbp    # p, D.7371
    jne .L3 #,
.LC1:
    .long   2147483648
    .long   2147483648
    .long   2147483648
    .long   2147483648

, , , xmm .

+2

All Articles