3d619b
From 14730a26e830eb2b09d1f7097910616f23c1476e Mon Sep 17 00:00:00 2001
3d619b
From: Ilya Leoshkevich <iii@linux.ibm.com>
3d619b
Date: Thu, 2 Feb 2023 19:40:32 +0100
3d619b
Subject: [PATCH] 0001-PATCH-Preparation-for-Power-optimizations.patch
3d619b
3d619b
---
3d619b
 CMakeLists.txt         | 67 ++++++++++++++++++++++++++++++++++++++++++
3d619b
 configure              | 66 +++++++++++++++++++++++++++++++++++++++++
3d619b
 contrib/README.contrib |  8 +++++
3d619b
 contrib/gcc/zifunc.h   | 60 +++++++++++++++++++++++++++++++++++++
3d619b
 contrib/power/power.h  |  4 +++
3d619b
 5 files changed, 205 insertions(+)
3d619b
 create mode 100644 contrib/gcc/zifunc.h
3d619b
 create mode 100644 contrib/power/power.h
3d619b
3d619b
diff --git a/CMakeLists.txt b/CMakeLists.txt
3d619b
index 0fe939d..e762023 100644
3d619b
--- a/CMakeLists.txt
3d619b
+++ b/CMakeLists.txt
3d619b
@@ -7,6 +7,7 @@ set(VERSION "1.2.11")
3d619b
 
3d619b
 option(ASM686 "Enable building i686 assembly implementation")
3d619b
 option(AMD64 "Enable building amd64 assembly implementation")
3d619b
+option(POWER "Enable building power implementation")
3d619b
 
3d619b
 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
3d619b
 set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
3d619b
@@ -140,6 +141,72 @@ if(CMAKE_COMPILER_IS_GNUCC)
3d619b
 		add_definitions(-DASMV)
3d619b
 		set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
3d619b
 	endif()
3d619b
+
3d619b
+    # test to see if we can use a GNU indirect function to detect and load optimized code at runtime
3d619b
+    CHECK_C_SOURCE_COMPILES("
3d619b
+    static int test_ifunc_native(void)
3d619b
+    {
3d619b
+       return 1;
3d619b
+    }
3d619b
+    static int (*(check_ifunc_native(void)))(void)
3d619b
+    {
3d619b
+       return test_ifunc_native;
3d619b
+    }
3d619b
+    int test_ifunc(void) __attribute__ ((ifunc (\"check_ifunc_native\")));
3d619b
+    int main(void)
3d619b
+    {
3d619b
+       return 0;
3d619b
+    }
3d619b
+    " HAS_C_ATTR_IFUNC)
3d619b
+
3d619b
+    if(HAS_C_ATTR_IFUNC)
3d619b
+        add_definitions(-DHAVE_IFUNC)
3d619b
+        set(ZLIB_PRIVATE_HDRS ${ZLIB_PRIVATE_HDRS} contrib/gcc/zifunc.h)
3d619b
+    endif()
3d619b
+
3d619b
+    if(POWER)
3d619b
+        # Test to see if we can use the optimizations for Power
3d619b
+        CHECK_C_SOURCE_COMPILES("
3d619b
+        #ifndef _ARCH_PPC
3d619b
+            #error \"Target is not Power\"
3d619b
+        #endif
3d619b
+        #ifndef __BUILTIN_CPU_SUPPORTS__
3d619b
+            #error \"Target doesn't support __builtin_cpu_supports()\"
3d619b
+        #endif
3d619b
+        int main() { return 0; }
3d619b
+        " HAS_POWER_SUPPORT)
3d619b
+
3d619b
+        if(HAS_POWER_SUPPORT AND HAS_C_ATTR_IFUNC)
3d619b
+            add_definitions(-DZ_POWER_OPT)
3d619b
+
3d619b
+            set(CMAKE_REQUIRED_FLAGS -mcpu=power8)
3d619b
+            CHECK_C_SOURCE_COMPILES("int main(void){return 0;}" POWER8)
3d619b
+
3d619b
+            if(POWER8)
3d619b
+                add_definitions(-DZ_POWER8)
3d619b
+                set(ZLIB_POWER8 )
3d619b
+
3d619b
+                set_source_files_properties(
3d619b
+                    ${ZLIB_POWER8}
3d619b
+                    PROPERTIES COMPILE_FLAGS -mcpu=power8)
3d619b
+            endif()
3d619b
+
3d619b
+            set(CMAKE_REQUIRED_FLAGS -mcpu=power9)
3d619b
+            CHECK_C_SOURCE_COMPILES("int main(void){return 0;}" POWER9)
3d619b
+
3d619b
+            if(POWER9)
3d619b
+                add_definitions(-DZ_POWER9)
3d619b
+                set(ZLIB_POWER9 )
3d619b
+
3d619b
+                set_source_files_properties(
3d619b
+                    ${ZLIB_POWER9}
3d619b
+                    PROPERTIES COMPILE_FLAGS -mcpu=power9)
3d619b
+            endif()
3d619b
+
3d619b
+            set(ZLIB_PRIVATE_HDRS ${ZLIB_PRIVATE_HDRS} contrib/power/power.h)
3d619b
+            set(ZLIB_SRCS ${ZLIB_SRCS} ${ZLIB_POWER8} ${ZLIB_POWER9})
3d619b
+        endif()
3d619b
+    endif()
3d619b
 endif()
3d619b
 
3d619b
 if(MSVC)
3d619b
diff --git a/configure b/configure
3d619b
index d026b35..0538d58 100755
3d619b
--- a/configure
3d619b
+++ b/configure
3d619b
@@ -846,6 +846,72 @@ else
3d619b
     echo "Checking for sys/sdt.h ... No." | tee -a configure.log
3d619b
 fi
3d619b
 
3d619b
+# test to see if we can use a gnu indirection function to detect and load optimized code at runtime
3d619b
+echo >> configure.log
3d619b
+cat > $test.c <
3d619b
+static int test_ifunc_native(void)
3d619b
+{
3d619b
+  return 1;
3d619b
+}
3d619b
+
3d619b
+static int (*(check_ifunc_native(void)))(void)
3d619b
+{
3d619b
+  return test_ifunc_native;
3d619b
+}
3d619b
+
3d619b
+int test_ifunc(void) __attribute__ ((ifunc ("check_ifunc_native")));
3d619b
+EOF
3d619b
+
3d619b
+if tryboth $CC -c $CFLAGS $test.c; then
3d619b
+  SFLAGS="${SFLAGS} -DHAVE_IFUNC"
3d619b
+  CFLAGS="${CFLAGS} -DHAVE_IFUNC"
3d619b
+  echo "Checking for attribute(ifunc) support... Yes." | tee -a configure.log
3d619b
+else
3d619b
+  echo "Checking for attribute(ifunc) support... No." | tee -a configure.log
3d619b
+fi
3d619b
+
3d619b
+# Test to see if we can use the optimizations for Power
3d619b
+echo >> configure.log
3d619b
+cat > $test.c <
3d619b
+#ifndef _ARCH_PPC
3d619b
+  #error "Target is not Power"
3d619b
+#endif
3d619b
+#ifndef HAVE_IFUNC
3d619b
+  #error "Target doesn't support ifunc"
3d619b
+#endif
3d619b
+#ifndef __BUILTIN_CPU_SUPPORTS__
3d619b
+  #error "Target doesn't support __builtin_cpu_supports()"
3d619b
+#endif
3d619b
+EOF
3d619b
+
3d619b
+if tryboth $CC -c $CFLAGS $test.c; then
3d619b
+  echo "int main(void){return 0;}" > $test.c
3d619b
+
3d619b
+  if tryboth $CC -c $CFLAGS -mcpu=power8 $test.c; then
3d619b
+    POWER8="-DZ_POWER8"
3d619b
+    PIC_OBJC="${PIC_OBJC}"
3d619b
+    OBJC="${OBJC}"
3d619b
+    echo "Checking for -mcpu=power8 support... Yes." | tee -a configure.log
3d619b
+  else
3d619b
+    echo "Checking for -mcpu=power8 support... No." | tee -a configure.log
3d619b
+  fi
3d619b
+
3d619b
+  if tryboth $CC -c $CFLAGS -mcpu=power9 $test.c; then
3d619b
+    POWER9="-DZ_POWER9"
3d619b
+    PIC_OBJC="${PIC_OBJC}"
3d619b
+    OBJC="${OBJC}"
3d619b
+    echo "Checking for -mcpu=power9 support... Yes." | tee -a configure.log
3d619b
+  else
3d619b
+    echo "Checking for -mcpu=power9 support... No." | tee -a configure.log
3d619b
+  fi
3d619b
+
3d619b
+  SFLAGS="${SFLAGS} ${POWER8} ${POWER9} -DZ_POWER_OPT"
3d619b
+  CFLAGS="${CFLAGS} ${POWER8} ${POWER9} -DZ_POWER_OPT"
3d619b
+  echo "Checking for Power optimizations support... Yes." | tee -a configure.log
3d619b
+else
3d619b
+  echo "Checking for Power optimizations support... No." | tee -a configure.log
3d619b
+fi
3d619b
+
3d619b
 # show the results in the log
3d619b
 echo >> configure.log
3d619b
 echo ALL = $ALL >> configure.log
3d619b
diff --git a/contrib/README.contrib b/contrib/README.contrib
3d619b
index b4d3b18..2a53f90 100644
3d619b
--- a/contrib/README.contrib
3d619b
+++ b/contrib/README.contrib
3d619b
@@ -19,6 +19,10 @@ asm686/     by Brian Raiter <breadbox@muppetlabs.com>
3d619b
 blast/      by Mark Adler <madler@alumni.caltech.edu>
3d619b
         Decompressor for output of PKWare Data Compression Library (DCL)
3d619b
 
3d619b
+gcc/        by Matheus Castanho <msc@linux.ibm.com>
3d619b
+            and Rogerio Alves <rcardoso@linux.ibm.com>
3d619b
+        Optimization helpers using GCC-specific extensions
3d619b
+
3d619b
 delphi/     by Cosmin Truta <cosmint@cs.ubbcluj.ro>
3d619b
         Support for Delphi and C++ Builder
3d619b
 
3d619b
@@ -63,6 +67,10 @@ minizip/    by Gilles Vollant <info@winimage.com>
3d619b
 pascal/     by Bob Dellaca <bobdl@xtra.co.nz> et al.
3d619b
         Support for Pascal
3d619b
 
3d619b
+power/      by Matheus Castanho <msc@linux.ibm.com>
3d619b
+            and Rogerio Alves <rcardoso@linux.ibm.com>
3d619b
+        Optimized functions for Power processors
3d619b
+
3d619b
 puff/       by Mark Adler <madler@alumni.caltech.edu>
3d619b
         Small, low memory usage inflate.  Also serves to provide an
3d619b
         unambiguous description of the deflate format.
3d619b
diff --git a/contrib/gcc/zifunc.h b/contrib/gcc/zifunc.h
3d619b
new file mode 100644
3d619b
index 0000000..daf4fe4
3d619b
--- /dev/null
3d619b
+++ b/contrib/gcc/zifunc.h
3d619b
@@ -0,0 +1,60 @@
3d619b
+/* Copyright (C) 2019 Matheus Castanho <msc@linux.ibm.com>, IBM
3d619b
+ *               2019 Rogerio Alves    <rogerio.alves@ibm.com>, IBM
3d619b
+ * For conditions of distribution and use, see copyright notice in zlib.h
3d619b
+ */
3d619b
+
3d619b
+#ifndef Z_IFUNC_H_
3d619b
+#define Z_IFUNC_H_
3d619b
+
3d619b
+/* Helpers for arch optimizations */
3d619b
+
3d619b
+#define Z_IFUNC(fname) \
3d619b
+    typeof(fname) fname __attribute__ ((ifunc (#fname "_resolver"))); \
3d619b
+    local typeof(fname) *fname##_resolver(void)
3d619b
+/* This is a helper macro to declare a resolver for an indirect function
3d619b
+ * (ifunc). Let's say you have function
3d619b
+ *
3d619b
+ *    int foo (int a);
3d619b
+ *
3d619b
+ * for which you want to provide different implementations, for example:
3d619b
+ *
3d619b
+ *    int foo_clever (int a) {
3d619b
+ *      ... clever things ...
3d619b
+ *    }
3d619b
+ *
3d619b
+ *    int foo_smart (int a) {
3d619b
+ *      ... smart things ...
3d619b
+ *    }
3d619b
+ *
3d619b
+ * You will have to declare foo() as an indirect function and also provide a
3d619b
+ * resolver for it, to choose between foo_clever() and foo_smart() based on
3d619b
+ * some criteria you define (e.g. processor features).
3d619b
+ *
3d619b
+ * Since most likely foo() has a default implementation somewhere in zlib, you
3d619b
+ * may have to rename it so the 'foo' symbol can be used by the ifunc without
3d619b
+ * conflicts.
3d619b
+ *
3d619b
+ *    #define foo foo_default
3d619b
+ *    int foo (int a) {
3d619b
+ *      ...
3d619b
+ *    }
3d619b
+ *    #undef foo
3d619b
+ *
3d619b
+ * Now you just have to provide a resolver function to choose which function
3d619b
+ * should be used (decided at runtime on the first call to foo()):
3d619b
+ *
3d619b
+ *    Z_IFUNC(foo) {
3d619b
+ *        if (... some condition ...)
3d619b
+ *          return foo_clever;
3d619b
+ *
3d619b
+ *        if (... other condition ...)
3d619b
+ *          return foo_smart;
3d619b
+ *
3d619b
+ *        return foo_default;
3d619b
+ *    }
3d619b
+ *
3d619b
+ * All calls to foo() throughout the code can remain untouched, all the magic
3d619b
+ * will be done by the linker using the resolver function.
3d619b
+ */
3d619b
+
3d619b
+#endif /* Z_IFUNC_H_ */
3d619b
diff --git a/contrib/power/power.h b/contrib/power/power.h
3d619b
new file mode 100644
3d619b
index 0000000..b42c7d6
3d619b
--- /dev/null
3d619b
+++ b/contrib/power/power.h
3d619b
@@ -0,0 +1,4 @@
3d619b
+/* Copyright (C) 2019 Matheus Castanho <msc@linux.ibm.com>, IBM
3d619b
+ *               2019 Rogerio Alves    <rogerio.alves@ibm.com>, IBM
3d619b
+ * For conditions of distribution and use, see copyright notice in zlib.h
3d619b
+ */
3d619b
-- 
3d619b
2.39.1
3d619b