Siehe auch Set all bits in CPU register to 1 efficiently, die AVX, AVX2 und AVX512 zmm und k (Masken) Register umfasst.
Sie haben offensichtlich nicht einmal an der asm Ausgang schauen, was zu tun ist trivial:
#include <immintrin.h>
__m256i all_ones(void) { return _mm256_set1_epi64x(-1); }
compiles to
vpcmpeqd ymm0, ymm0, ymm0
ret
mit gcc6.1 und clang3.8.
Die erste Version von gcc zur Unterstützung von avx2 wusste genug, um diese Optimierung zu tun. Mit -mavx -mno-avx2
lädt gcc einen Vektor von Einsen aus dem Speicher. Clang erstellt ein 128bit All-Ones und verwendet vinsertf128
.
Wie der Vektor-Abschnitt von Agner Fog's optimizing assembly guide beschrieben, billig ist diese Art und Weise Konstanten on the fly zu generieren. Es benötigt immer noch eine Vektorausführungseinheit, um die Einsen zu erzeugen (unlike _mm_setzero
), aber es ist besser als jede mögliche Zwei-Befehlsfolge und normalerweise besser als eine Last. Siehe auch das x86 Tag-Wiki.
Compiler mögen nicht generate more complex constants on the fly, auch solche, die von all-one mit einer einfachen Verschiebung erzeugt werden könnten. Selbst wenn Sie es versuchen, indem Sie __m128i float_signbit_mask = _mm_srli_epi32(_mm_set1_epi16(-1), 1)
schreiben, führen Compiler typischerweise eine konstante Propagierung durch und setzen den Vektor in den Speicher. Dies ermöglicht es ihnen, sie in einen Speicheroperanden zu falten, wenn sie später in Fällen verwendet werden, in denen es keine Schleife gibt, die die Konstante ausheben kann.
Und ich kann nicht scheinen, eine einfache bitweise NOT-Operation in AVX zu finden?
Sie tun das durch XORing mit All-Einsen.
In früheren Zeiten verwendeten die Leute 'pcmpeqd xmm0, xmm0' dafür, vermutlich gibt es eine äquivalente Operation in AVX {2}? – njuffa
@njuffa 'vpcmpeqd' in AVX2. Clang scheint die '_mm256_set1_epi64x (-1);' zu optimieren, das gleiche wie '_mm256_cmpeq_epi64 (_mm256_setzero_si256(), _mm256_setzero_si256());' –
Siehe auch: http://stackoverflow.com/q/35085059/555045 – harold