diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,6 +244,11 @@ if(NOT DEFINED X86CPU_ARCH AND ARCH STREQUAL "x86") include(DetectArchitecture) detect_x86_cpu_architecture(X86CPU_ARCH) + detect_x86_feature(avx2 HAVE_X86_AVX2_INSTRUCTIONS) +endif() +if(NOT HAVE_LIBMVEC_X86 AND ARCH STREQUAL "x86") + include(DetectVectorLibrary) + detect_libmvec_x86(HAVE_LIBMVEC_X86) endif() if(NOT DEFINED ENDIAN) include(TestBigEndian) diff --git a/SingleSource/UnitTests/Vectorizer/CMakeLists.txt b/SingleSource/UnitTests/Vectorizer/CMakeLists.txt --- a/SingleSource/UnitTests/Vectorizer/CMakeLists.txt +++ b/SingleSource/UnitTests/Vectorizer/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(Veclib) llvm_singlesource() set_property(TARGET runtime-checks PROPERTY CXX_STANDARD 17) diff --git a/SingleSource/UnitTests/Vectorizer/Veclib/CMakeLists.txt b/SingleSource/UnitTests/Vectorizer/Veclib/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Vectorizer/Veclib/CMakeLists.txt @@ -0,0 +1,9 @@ +if(HAVE_X86_AVX2_INSTRUCTIONS AND HAVE_LIBMVEC_X86) + check_c_compiler_flag(-fveclib=libmvec COMPILER_HAS_FVECLIB_LIBMVEC_FLAG) + if(COMPILER_HAS_FVECLIB_LIBMVEC_FLAG) + list(APPEND LDFLAGS -lm -fveclib=libmvec) + list(APPEND CFLAGS -fveclib=libmvec -O2 -march=native) + llvm_singlesource(PREFIX "Vectorizer-Veclib-libmvec-") + endif() +endif() +# Other vector math libraries may be added here... diff --git a/SingleSource/UnitTests/Vectorizer/Veclib/sincos.c b/SingleSource/UnitTests/Vectorizer/Veclib/sincos.c new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Vectorizer/Veclib/sincos.c @@ -0,0 +1,115 @@ +#define _GNU_SOURCE + +#include +#include + +// inner loop vectorization with linear access +void sincos_arr(double* sines, double* cosines, double* phases, int size) { + for (int i=0; i max_ulp_err * ulp) { + printf("%s,%s FAILED at %d: argument %g, value %g, reference %g, difference %g, (%g ULP).\n", + msg1, msg2, index, arg, val, ref, (val-ref), fabs(val-ref)/ulp); + return 1; + } + return 0; +} + +int check_arr(double* sines, double* coses, double* phases, int* indices, int size, int nests, double max_ulp_err, const char* msg) +{ + int fail = 0; + + for (int i = 0; i < size; i++) { + int j = indices ? indices[i] : i; + double ref_sin = sin(phases[j]); + double ref_cos = cos(phases[j]); + for (int k=0; k +#include + +void _ZGVdN4vvv_sincos(__m256d x, __m256i sinptr, __m256i cosptr); + +int main(void) { + __m256d x = _mm256_set_pd(0.0, 0.1, 0.2, 0.3); + union {__m256d vec; double arr[4];} sines, coses; + __m256i sinptr = _mm256_set_epi64x((uint64_t)&sines.arr[0], (uint64_t)&sines.arr[1], (uint64_t)&sines.arr[2], (uint64_t)&sines.arr[3]); + __m256i cosptr = _mm256_set_epi64x((uint64_t)&coses.arr[0], (uint64_t)&coses.arr[1], (uint64_t)&coses.arr[2], (uint64_t)&coses.arr[3]); + // use function from libmvec (the one we have a test for): + _ZGVdN4vvv_sincos(x, sinptr, cosptr); + // ensure the call cannot get optimized out: + __m256d sin_is_not_less_than_cos = _mm256_cmp_pd(sines.vec, coses.vec, _CMP_GE_OQ); + int result = !_mm256_testz_pd(sin_is_not_less_than_cos, sin_is_not_less_than_cos); + return result; +} diff --git a/cmake/modules/DetectVectorLibrary.cmake b/cmake/modules/DetectVectorLibrary.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/DetectVectorLibrary.cmake @@ -0,0 +1,28 @@ +##===- DetectVectorLibrary.cmake ------------------------------------------===## +# +# Performs a try_run to determine if a vector library is available. +# +##===----------------------------------------------------------------------===## + +# +# Performs a try_run to determine if libmvec-x86 is available +# + +function(detect_libmvec_x86 variable) + set(CMAKE_C_FLAGS -mavx2) + try_run(HAVE_RUN_${variable} HAVE_COMPILE_${variable} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/cmake/modules/DetectLibmvecX86.c + LINK_LIBRARIES -lmvec) + + if(HAVE_COMPILE_${variable} AND NOT (HAVE_RUN_${variable} STREQUAL FAILED_TO_RUN)) + set(HAVE_LIBMVEC_X86 YES) + else() + set(HAVE_LIBMVEC_X86 NO) + endif() + set(${variable} ${HAVE_LIBMVEC_X86} PARENT_SCOPE) + message(STATUS "Check libmvec X86 vector math library available: ${HAVE_LIBMVEC_X86}") + +endfunction(detect_libmvec_x86) + +# Add other vector libraries here... \ No newline at end of file diff --git a/cmake/modules/DetectX86FeatureFlag.c b/cmake/modules/DetectX86FeatureFlag.c new file mode 100644 --- /dev/null +++ b/cmake/modules/DetectX86FeatureFlag.c @@ -0,0 +1,14 @@ +#include + +#define xstr(s) str(s) +#define str(s) #s + +int main(void) { + __builtin_cpu_init(); + if (__builtin_cpu_supports(xstr(FEATURE_FLAG))) { + printf("YES"); + } else { + printf("NO"); + } + return 0; +}