summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/CheckCxxTarget.cmake35
-rw-r--r--CMake/config.h.in4
-rw-r--r--CMakeLists.txt5
-rw-r--r--apt-pkg/pkgcache.cc8
4 files changed, 50 insertions, 2 deletions
diff --git a/CMake/CheckCxxTarget.cmake b/CMake/CheckCxxTarget.cmake
new file mode 100644
index 000000000..373c0be4c
--- /dev/null
+++ b/CMake/CheckCxxTarget.cmake
@@ -0,0 +1,35 @@
+# CMake support for target-based function multiversioning
+#
+# Copyright (C) 2019 Canonical Ltd
+#
+# Author: Julian Andres Klode <jak@debian.org>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+function(check_cxx_target var target code)
+ check_cxx_source_compiles(
+ "
+ __attribute__((target(\"${target}\"))) static int foo() { ${code} return 1; }
+ __attribute__((target(\"default\"))) static int foo() { ${code} return 0; }
+ int main() { return foo(); }
+ " ${var})
+endfunction()
diff --git a/CMake/config.h.in b/CMake/config.h.in
index bd0da8649..98a81ad6c 100644
--- a/CMake/config.h.in
+++ b/CMake/config.h.in
@@ -81,3 +81,7 @@
/* unrolling is faster combined with an optimizing compiler */
#define SHA2_UNROLL_TRANSFORM
+
+/* defined if __builtin_ia32_crc32{s,d}i() exists in an sse4.2 target */
+#define HAVE_FMV_SSE42_AND_CRC32
+#define HAVE_FMV_SSE42_AND_CRC32DI
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b3cc73de..599c7ec1a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -180,6 +180,11 @@ else()
set(RESOLV_LIBRARIES -lresolv)
endif()
+# Check multiversioning
+include(CheckCxxTarget)
+check_cxx_target(HAVE_FMV_SSE42_AND_CRC32 "sse4.2" "__builtin_ia32_crc32si(0, 1llu);")
+check_cxx_target(HAVE_FMV_SSE42_AND_CRC32DI "sse4.2" "__builtin_ia32_crc32di(0, 1llu);")
+
# Configure some variables like package, version and architecture.
set(PACKAGE ${PROJECT_NAME})
set(PACKAGE_MAIL "APT Development Team <deity@lists.debian.org>")
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 041f0b957..80dd1d1fa 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -231,15 +231,16 @@ map_id_t pkgCache::sHash(const char *Str) const
return Hash % HeaderP->GetHashTableSize();
}
-#if defined(__GNUC__) && defined(__x86_64__) && defined(__ELF__)
+#if defined(HAVE_FMV_SSE42_AND_CRC32)
-#if defined(__x86_64__)
+#ifdef HAVE_FMV_SSE42_AND_CRC32
__attribute__((target("sse4.2"))) static uint32_t hash32(uint32_t crc32, const unsigned char *input, size_t size)
{
if (input == nullptr)
return 0;
crc32 ^= 0xffffffffU;
+#ifdef HAVE_FMV_SSE42_AND_CRC32DI
while (size >= 8) {
crc32 = __builtin_ia32_crc32di(crc32, *(uint64_t *)input);
input += 8;
@@ -247,6 +248,9 @@ __attribute__((target("sse4.2"))) static uint32_t hash32(uint32_t crc32, const u
}
if (size >= 4) {
+#else
+ while (size >= 4) {
+#endif
crc32 = __builtin_ia32_crc32si(crc32, *(uint32_t *)input);
input += 4;
size -= 4;