I want to set two integer vectors and compare them with SIMD, and later on use this mask for a blend operation on packed floats. I produced the following code:
#include <immintrin.h>#include <stdio.h>#include <string.h>int main(){ __m256i is = _mm256_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8); __m256i js = _mm256_set1_epi32(1); __m256 mask = _mm256_cmp_ps(is,js, _CMP_EQ_OQ); float val[8]; memcpy(val, &mask, sizeof(val)); printf("%f %f %f %f %f %f %f %f \n", val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);}
which works fine with gcc -mavx mamight in.c
as well as clang -mavx main.c
and clang -O3 -mavx main.c
. However, when I use gcc -O3 -mavx main.c
I get the following error message:
main.c: In function ‘main’:main.c:9:33: error: incompatible type for argument 1 of ‘_mm256_cmp_ps’ 9 | __m256 mask = _mm256_cmp_ps(is,js, _CMP_EQ_OQ); | ^~ | | | __m256i {aka __vector(4) long long int}In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/immintrin.h:51, from main.c:1:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/avxintrin.h:404:23: note: expected ‘__m256’ {aka ‘__vector(8) float’} but argument is of type ‘__m256i’ {aka ‘__vector(4) long long int’} 404 | _mm256_cmp_ps (__m256 __X, __m256 __Y, const int __P) | ~~~~~~~^~~main.c:9:36: error: incompatible type for argument 2 of ‘_mm256_cmp_ps’ 9 | __m256 mask = _mm256_cmp_ps(is,js, _CMP_EQ_OQ); | ^~ | | | __m256i {aka __vector(4) long long int}In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/immintrin.h:51, from main.c:1:/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/include/avxintrin.h:404:35: note: expected ‘__m256’ {aka ‘__vector(8) float’} but argument is of type ‘__m256i’ {aka ‘__vector(4) long long int’} 404 | _mm256_cmp_ps (__m256 __X, __m256 __Y, const int __P) | ~~~~~~~^~~
I notice two things. First of all, the compiler seems to treat is
as __m256i {aka __vector(4) long long int}
whereas it contains 8 ints. Secondly, the compiler is correct to complain, because the intel intrinsics guide 1 shows the arguments as __m256
. I'm now confused why this code even worked at the beginning. And if it is indeed correct because the integers are casted to floats, then I don't understand why it doesn't work with gcc -O3
.
I did not want to use _mm256_cmpeq_epi32
which returns an __m256i
and there (seems to be no) is no blend_ps
instruction that accepts such a mask.
My specific questions therefore are, why do the compilers behave different, and what is the correct way to do this operation.
edit: Added compiler versions
$ gcc -vUsing built-in specs.COLLECT_GCC=gccCOLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0/lto-wrapperTarget: x86_64-pc-linux-gnuConfigured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-pkgversion='Arch Linux 9.3.0-1' --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto gdc_include_dir=/usr/include/dlang/gdcThread model: posixgcc version 9.3.0 (Arch Linux 9.3.0-1)
$ clang -vclang version 10.0.0 Target: x86_64-pc-linux-gnuThread model: posixInstalledDir: /usr/binFound candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/8.4.0Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/9.3.0Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.4.0Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.3.0Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/8.4.0Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/9.3.0Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/8.4.0Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/9.3.0Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.3.0Candidate multilib: .;@m64Candidate multilib: 32;@m32Selected multilib: .;@m64Found CUDA installation: /opt/cuda, version 10.1
[1] https://software.intel.com/sites/landingpage/IntrinsicsGuide/