]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Use endianess-specific built-in function for gcc < 12 on PowerPC64
authorMika T. Lindqvist <postmaster@raasu.org>
Sun, 11 Jun 2023 22:18:12 +0000 (01:18 +0300)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 23 Jun 2023 17:43:34 +0000 (19:43 +0200)
* Add support for cross-compiling using clang 13 and later for PowerPC64 little-endian and big-endian
* Fix detection for availability of Power9 intrinsics

.github/workflows/cmake.yml
arch/power/chunkset_power8.c
arch/power/compare256_power9.c
arch/power/power_features.c
cmake/detect-intrinsics.cmake
cmake/toolchain-powerpc64-clang.cmake [new file with mode: 0644]
cmake/toolchain-powerpc64le-clang.cmake [new file with mode: 0644]
configure

index d00ecb4c41b96f9a53a12258c54a110f986f091e..752d628d9e89f62bc2fdf284d2cbbd1384e0ee12 100644 (file)
@@ -230,6 +230,11 @@ jobs:
             ldflags: -static
             codecov: ubuntu_gcc_ppc64_power9
 
+          - name: Ubuntu Clang PPC64 Power9
+            os: ubuntu-latest
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64-clang.cmake
+            packages: qemu qemu-user clang binutils-powerpc64-linux-gnu libc-dev-ppc64-cross libgcc-11-dev-ppc64-cross libstdc++-11-dev-ppc64-cross
+
           - name: Ubuntu GCC PPC64LE
             os: ubuntu-20.04
             cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake
@@ -248,6 +253,11 @@ jobs:
             packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross
             codecov: ubuntu_gcc_ppc64le_power9
 
+          - name: Ubuntu Clang PPC64LE Power9
+            os: ubuntu-latest
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le-clang.cmake
+            packages: qemu qemu-user clang binutils-powerpc64le-linux-gnu libc-dev-ppc64el-cross libgcc-11-dev-ppc64el-cross libstdc++-11-dev-ppc64el-cross
+
           - name: Ubuntu GCC SPARC64
             os: ubuntu-20.04
             cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake
index 443aae92f116f42d625a49258c3c1ee5c4c06776..7cbb8029b3b141834e05b69a579060f5e2813bdf 100644 (file)
@@ -29,7 +29,7 @@ static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) {
 static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) {
     uint64_t tmp;
     memcpy(&tmp, from, sizeof(tmp));
-    *chunk = (vector unsigned char)vec_splats(tmp);
+    *chunk = (vector unsigned char)vec_splats((unsigned long long)tmp);
 }
 
 static inline void loadchunk(uint8_t const *s, chunk_t *chunk) {
index be094350f886e16f68afebe209fca70b9631ac5a..9b0ddaf80045019126cdba4a12e608ad521bddbf 100644 (file)
 
 /* Older versions of GCC misimplemented semantics for these bit counting builtins.
  * https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3f30f2d1dbb3228b8468b26239fe60c2974ce2ac */
-#if defined(__GNUC__) && (__GNUC__ < 13)
-#  define zng_vec_vctzlsbb(vc, len) __asm__ volatile("vctzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc))
-#  define zng_vec_vclzlsbb(vc, len) __asm__ volatile("vclzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc))
-#else
+#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12)
+#if BYTE_ORDER == LITTLE_ENDIAN
 #  define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vctzlsbb(vc)
-#  define zng_vec_vclzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc)
+#else
+#  define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc)
+#endif
+#else
+#  define zng_vec_vctzlsbb(vc, len) len = vec_cntlz_lsbb(vc)
 #endif
 
 static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8_t *src1) {
@@ -34,11 +36,7 @@ static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8
         /* Since the index of matching bytes will contain only zeroes
          * on vc (since we used cmpne), counting the number of consecutive
          * bytes where LSB == 0 is the same as counting the length of the match. */
-#if BYTE_ORDER == LITTLE_ENDIAN
         zng_vec_vctzlsbb(vc, cmplen);
-#else
-        zng_vec_vclzlsbb(vc, cmplen);
-#endif
         if (cmplen != 16)
             return len + cmplen;
 
index 003a4c6e3cae44a5ece3bff8100c8b6c41c1bd33..f73503734b13d562d6e6805f307b7dcb586420ca 100644 (file)
@@ -34,9 +34,13 @@ void Z_INTERNAL power_check_features(struct power_cpu_features *features) {
     hwcap2 = getauxval(AT_HWCAP2);
 #endif
 
+#ifdef POWER8_VSX
     if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
         features->has_arch_2_07 = 1;
+#endif
+#ifdef POWER9
     if (hwcap2 & PPC_FEATURE2_ARCH_3_00)
         features->has_arch_3_00 = 1;
 #endif
+#endif
 }
index e9e6d36da85b54e0e8cfc8d727ff0c88c689233f..9cbc5908987ff91bc697ea29c15ed519b1d396a0 100644 (file)
@@ -393,8 +393,18 @@ macro(check_power9_intrinsics)
     # Check if we have what we need for POWER9 optimizations
     set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG}")
     check_c_source_compiles(
-        "int main() {
-            return 0;
+        "#include <sys/auxv.h>
+        #ifdef __FreeBSD__
+        #include <machine/cpu.h>
+        #endif
+        int main() {
+        #ifdef __FreeBSD__
+            unsigned long hwcap;
+            elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap));
+            return (hwcap & PPC_FEATURE2_ARCH_3_00);
+        #else
+            return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00);
+        #endif
         }"
         HAVE_POWER9_INTRIN
     )
diff --git a/cmake/toolchain-powerpc64-clang.cmake b/cmake/toolchain-powerpc64-clang.cmake
new file mode 100644 (file)
index 0000000..f986796
--- /dev/null
@@ -0,0 +1,16 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR ppc64)
+set(CMAKE_SYSTEM_VERSION 1)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_C_COMPILER_TARGET powerpc64-linux-gnu)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_CXX_COMPILER_TARGET powerpc64-linux-gnu)
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/toolchain-powerpc64le-clang.cmake b/cmake/toolchain-powerpc64le-clang.cmake
new file mode 100644 (file)
index 0000000..b3423c5
--- /dev/null
@@ -0,0 +1,16 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR ppc64le)
+set(CMAKE_SYSTEM_VERSION 1)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_C_COMPILER_TARGET powerpc64le-linux-gnu)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_CXX_COMPILER_TARGET powerpc64le-linux-gnu)
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
index a7ecc370b6bec8e813a76b7f6da21e788b5a0661..9c0ea34314231f7c16a872d5139e41e768a69e93 100755 (executable)
--- a/configure
+++ b/configure
@@ -1383,7 +1383,19 @@ EOF
 check_power9_intrinsics() {
     # Check whether features needed by POWER9 optimisations are available
     cat > $test.c << EOF
-int main() { return 0; }
+#ifdef __FreeBSD__
+#include <machine/cpu.h>
+#endif
+#include <sys/auxv.h>
+int main() {
+#ifdef __FreeBSD__
+  unsigned long hwcap;
+  elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap));
+  return (hwcap & PPC_FEATURE2_ARCH_3_00);
+#else
+  return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00);
+#endif
+}
 EOF
     if test $buildpower9 -eq 1 && try $CC -c $CFLAGS -mcpu=power9 $test.c; then
         HAVE_POWER9_INTRIN=1