From: Joel Rosdahl Date: Sat, 30 Mar 2024 09:02:27 +0000 (+0100) Subject: refactor: Implement AVX2 runtime detection instead of using blake3's X-Git-Tag: v4.10~42^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=14a60d8099abcd028eede92a7a7634af99662fb8;p=thirdparty%2Fccache.git refactor: Implement AVX2 runtime detection instead of using blake3's --- diff --git a/ci/build b/ci/build index 4ed04ebb9..f86ca82c0 100755 --- a/ci/build +++ b/ci/build @@ -35,12 +35,17 @@ else ;; esac + if [ -x ccache ]; then + ./ccache --version + elif command -v wine >/dev/null && [ -f ccache.exe ]; then + wine ccache.exe --version + fi + case "${RUN_TESTS:-all}" in all) CC="${TEST_CC}" ctest --output-on-failure -j"${JOBS}" "$@" ;; unittest-in-wine) - wine ccache.exe --version wine unittest/unittest.exe ;; none) diff --git a/cmake/GenerateConfigurationFile.cmake b/cmake/GenerateConfigurationFile.cmake index 7caf21b58..a3d24cb7f 100644 --- a/cmake/GenerateConfigurationFile.cmake +++ b/cmake/GenerateConfigurationFile.cmake @@ -1,5 +1,6 @@ include(CheckIncludeFile) set(include_files + cpuid.h dirent.h linux/fs.h pwd.h @@ -70,8 +71,8 @@ include(CheckCXXSourceCompiles) check_cxx_source_compiles( [=[ #include - #ifndef _MSC_VER // MSVC does not need explicit enabling of AVX2. - void func() __attribute__((target("avx2"))); + #ifndef _MSC_VER + __attribute__((target("avx2"))) #endif void func() { _mm256_abs_epi8(_mm256_set1_epi32(42)); } int main() diff --git a/cmake/config.h.in b/cmake/config.h.in index 44027dfb8..24f2038f2 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -69,6 +69,9 @@ // === Header files === +// Define if you have the header file. +#cmakedefine HAVE_CPUID_H + // Define if you have the header file. #cmakedefine HAVE_DIRENT_H diff --git a/src/ccache/core/mainoptions.cpp b/src/ccache/core/mainoptions.cpp index 28d34e07b..f180dccf7 100644 --- a/src/ccache/core/mainoptions.cpp +++ b/src/ccache/core/mainoptions.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -417,8 +418,13 @@ parse_compression_level(std::string_view level) static std::string get_version_text(const std::string_view ccache_name) { + auto features = storage::get_features(); + if (util::cpu_supports_avx2()) { + features.emplace_back("avx2"); + } + std::sort(features.begin(), features.end()); return FMT( - VERSION_TEXT, ccache_name, CCACHE_VERSION, storage::get_features()); + VERSION_TEXT, ccache_name, CCACHE_VERSION, util::join(features, " ")); } std::string diff --git a/src/ccache/hashutil.cpp b/src/ccache/hashutil.cpp index c22f7b344..e5c9a2489 100644 --- a/src/ccache/hashutil.cpp +++ b/src/ccache/hashutil.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -36,8 +37,6 @@ # include "InodeCache.hpp" #endif -#include - #ifdef HAVE_UNISTD_H # include #endif @@ -112,14 +111,12 @@ check_for_temporal_macros_bmh(std::string_view str, size_t start = 0) } #ifdef HAVE_AVX2 -# ifndef _MSC_VER // MSVC does not need explicit enabling of AVX2. -HashSourceCodeResult check_for_temporal_macros_avx2(std::string_view str) - __attribute__((target("avx2"))); -# endif - // The following algorithm, which uses AVX2 instructions to find __DATE__, // __TIME__ and __TIMESTAMP__, is heavily inspired by // . +# ifndef _MSC_VER +__attribute__((target("avx2"))) +# endif HashSourceCodeResult check_for_temporal_macros_avx2(std::string_view str) { @@ -222,7 +219,7 @@ HashSourceCodeResult check_for_temporal_macros(std::string_view str) { #ifdef HAVE_AVX2 - if (blake3_cpu_supports_avx2()) { + if (util::cpu_supports_avx2()) { return check_for_temporal_macros_avx2(str); } #endif diff --git a/src/ccache/storage/Storage.cpp b/src/ccache/storage/Storage.cpp index 1149940c9..3d6f82f5a 100644 --- a/src/ccache/storage/Storage.cpp +++ b/src/ccache/storage/Storage.cpp @@ -60,7 +60,7 @@ const std::unordered_map get_features() { std::vector features; @@ -69,8 +69,7 @@ get_features() k_remote_storage_implementations.end(), std::back_inserter(features), [](auto& entry) { return FMT("{}-storage", entry.first); }); - std::sort(features.begin(), features.end()); - return util::join(features, " "); + return features; } // Representation of one shard configuration. diff --git a/src/ccache/storage/Storage.hpp b/src/ccache/storage/Storage.hpp index 3d46486d0..49733e990 100644 --- a/src/ccache/storage/Storage.hpp +++ b/src/ccache/storage/Storage.hpp @@ -37,7 +37,7 @@ namespace storage { constexpr auto k_redacted_password = "********"; -std::string get_features(); +std::vector get_features(); struct RemoteStorageBackendEntry; struct RemoteStorageEntry; diff --git a/src/ccache/util/CMakeLists.txt b/src/ccache/util/CMakeLists.txt index 63c936b3f..085494910 100644 --- a/src/ccache/util/CMakeLists.txt +++ b/src/ccache/util/CMakeLists.txt @@ -12,6 +12,7 @@ set( Tokenizer.cpp UmaskScope.cpp assertions.cpp + cpu.cpp environment.cpp error.cpp file.cpp diff --git a/src/ccache/util/cpu.cpp b/src/ccache/util/cpu.cpp new file mode 100644 index 000000000..18408a683 --- /dev/null +++ b/src/ccache/util/cpu.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2024 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include "cpu.hpp" + +#ifdef _MSC_VER +# include +#endif + +#ifdef HAVE_CPUID_H +# include +#endif + +namespace util { + +bool +cpu_supports_avx2() +{ + // CPUID with EAX=7 ECX=0 returns AVX2 support in bit 5 of EBX. + int registers[4]; // EAX, EBX, ECX, EDX +#if defined(_MSC_VER) && defined(_M_X64) + __cpuidex(registers, 7, 0); +#elif defined(HAVE_CPUID_H) + __cpuid_count(7, 0, registers[0], registers[1], registers[2], registers[3]); +#elif __x86_64__ + __asm__ __volatile__("cpuid" + : "=a"(registers[0]), + "=b"(registers[1]), + "=c"(registers[2]), + "=d"(registers[3]) + : "a"(7), "c"(0)); +#else + registers[1] = 0; +#endif + return registers[1] & (1 << 5); +} + +} // namespace util diff --git a/src/ccache/util/cpu.hpp b/src/ccache/util/cpu.hpp new file mode 100644 index 000000000..3a065b097 --- /dev/null +++ b/src/ccache/util/cpu.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2024 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#pragma once + +namespace util { + +// --- Interface --- + +bool cpu_supports_avx2(); + +} // namespace util diff --git a/src/third_party/blake3/CMakeLists.txt b/src/third_party/blake3/CMakeLists.txt index 1d4ad9442..7ab255f21 100644 --- a/src/third_party/blake3/CMakeLists.txt +++ b/src/third_party/blake3/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(dep_blake3 STATIC blake3.c blake3_dispatch_ccache.c blake3_portable.c) +add_library(dep_blake3 STATIC blake3.c blake3_dispatch.c blake3_portable.c) target_include_directories(dep_blake3 INTERFACE "${CMAKE_SOURCE_DIR}/src/third_party/blake3") target_link_libraries(dep_blake3 PRIVATE standard_settings) diff --git a/src/third_party/blake3/blake3_cpu_supports_avx2.h b/src/third_party/blake3/blake3_cpu_supports_avx2.h deleted file mode 100644 index 5d52caee4..000000000 --- a/src/third_party/blake3/blake3_cpu_supports_avx2.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef BLAKE3_CPU_SUPPORTS_AVX2_H -#define BLAKE3_CPU_SUPPORTS_AVX2_H - -// This file is a ccache modification to BLAKE3 - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -bool blake3_cpu_supports_avx2(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/third_party/blake3/blake3_dispatch_ccache.c b/src/third_party/blake3/blake3_dispatch_ccache.c deleted file mode 100644 index 86496e73a..000000000 --- a/src/third_party/blake3/blake3_dispatch_ccache.c +++ /dev/null @@ -1,10 +0,0 @@ -// This file is a ccache modification to BLAKE3 - -#include "blake3_dispatch.c" - -#include "blake3_cpu_supports_avx2.h" - -bool blake3_cpu_supports_avx2() -{ - return get_cpu_features() & AVX2; -}