Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optimized crc32 for Power 8+ processors #478

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Preparation for Power optimizations
Optimized functions for Power will make use of GNU indirect functions,
an extension to support different implementations of the same function,
which can be selected during runtime. This will be used to provide
optimized functions for different processor versions.

Since this is a GNU extension, we placed the definition of the Z_IFUNC
macro under `contrib/gcc`. This can be reused by other archs as well.

Author: Matheus Castanho <msc@linux.ibm.com>
Author: Rogerio Alves <rcardoso@linux.ibm.com>
  • Loading branch information
Rogerio Alves authored and mscastanho committed Apr 6, 2022
commit 85ccfa14e6f65df6fe3c17cedc6cd8dbd76fa83d
67 changes: 67 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(VERSION "1.2.12.1")

option(ASM686 "Enable building i686 assembly implementation")
option(AMD64 "Enable building amd64 assembly implementation")
option(POWER "Enable building power implementation")

set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
Expand Down Expand Up @@ -140,6 +141,72 @@ if(CMAKE_COMPILER_IS_GNUCC)
add_definitions(-DASMV)
set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
endif()

# test to see if we can use a GNU indirect function to detect and load optimized code at runtime
CHECK_C_SOURCE_COMPILES("
static int test_ifunc_native(void)
{
return 1;
}
static int (*(check_ifunc_native(void)))(void)
{
return test_ifunc_native;
}
int test_ifunc(void) __attribute__ ((ifunc (\"check_ifunc_native\")));
int main(void)
{
return 0;
}
" HAS_C_ATTR_IFUNC)

if(HAS_C_ATTR_IFUNC)
add_definitions(-DHAVE_IFUNC)
set(ZLIB_PRIVATE_HDRS ${ZLIB_PRIVATE_HDRS} contrib/gcc/zifunc.h)
endif()

if(POWER)
# Test to see if we can use the optimizations for Power
CHECK_C_SOURCE_COMPILES("
#ifndef _ARCH_PPC
#error \"Target is not Power\"
#endif
#ifndef __BUILTIN_CPU_SUPPORTS__
#error \"Target doesn't support __builtin_cpu_supports()\"
#endif
int main() { return 0; }
" HAS_POWER_SUPPORT)

if(HAS_POWER_SUPPORT AND HAS_C_ATTR_IFUNC)
add_definitions(-DZ_POWER_OPT)

set(CMAKE_REQUIRED_FLAGS -mcpu=power8)
CHECK_C_SOURCE_COMPILES("int main(void){return 0;}" POWER8)

if(POWER8)
add_definitions(-DZ_POWER8)
set(ZLIB_POWER8 )

set_source_files_properties(
${ZLIB_POWER8}
PROPERTIES COMPILE_FLAGS -mcpu=power8)
endif()

set(CMAKE_REQUIRED_FLAGS -mcpu=power9)
CHECK_C_SOURCE_COMPILES("int main(void){return 0;}" POWER9)

if(POWER9)
add_definitions(-DZ_POWER9)
set(ZLIB_POWER9 )

set_source_files_properties(
${ZLIB_POWER9}
PROPERTIES COMPILE_FLAGS -mcpu=power9)
endif()

set(ZLIB_PRIVATE_HDRS ${ZLIB_PRIVATE_HDRS} contrib/power/power.h)
set(ZLIB_SRCS ${ZLIB_SRCS} ${ZLIB_POWER8} ${ZLIB_POWER9})
endif()
endif()
endif()

if(MSVC)
Expand Down
66 changes: 66 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,72 @@ EOF
fi
fi

# test to see if we can use a gnu indirection function to detect and load optimized code at runtime
echo >> configure.log
cat > $test.c <<EOF
static int test_ifunc_native(void)
{
return 1;
}

static int (*(check_ifunc_native(void)))(void)
{
return test_ifunc_native;
}

int test_ifunc(void) __attribute__ ((ifunc ("check_ifunc_native")));
EOF

if tryboth $CC -c $CFLAGS $test.c; then
SFLAGS="${SFLAGS} -DHAVE_IFUNC"
CFLAGS="${CFLAGS} -DHAVE_IFUNC"
echo "Checking for attribute(ifunc) support... Yes." | tee -a configure.log
else
echo "Checking for attribute(ifunc) support... No." | tee -a configure.log
fi

# Test to see if we can use the optimizations for Power
echo >> configure.log
cat > $test.c <<EOF
#ifndef _ARCH_PPC
#error "Target is not Power"
#endif
#ifndef HAVE_IFUNC
#error "Target doesn't support ifunc"
#endif
#ifndef __BUILTIN_CPU_SUPPORTS__
#error "Target doesn't support __builtin_cpu_supports()"
#endif
EOF

if tryboth $CC -c $CFLAGS $test.c; then
echo "int main(void){return 0;}" > $test.c

if tryboth $CC -c $CFLAGS -mcpu=power8 $test.c; then
POWER8="-DZ_POWER8"
PIC_OBJC="${PIC_OBJC}"
OBJC="${OBJC}"
echo "Checking for -mcpu=power8 support... Yes." | tee -a configure.log
else
echo "Checking for -mcpu=power8 support... No." | tee -a configure.log
fi

if tryboth $CC -c $CFLAGS -mcpu=power9 $test.c; then
POWER9="-DZ_POWER9"
PIC_OBJC="${PIC_OBJC}"
OBJC="${OBJC}"
echo "Checking for -mcpu=power9 support... Yes." | tee -a configure.log
else
echo "Checking for -mcpu=power9 support... No." | tee -a configure.log
fi

SFLAGS="${SFLAGS} ${POWER8} ${POWER9} -DZ_POWER_OPT"
CFLAGS="${CFLAGS} ${POWER8} ${POWER9} -DZ_POWER_OPT"
echo "Checking for Power optimizations support... Yes." | tee -a configure.log
else
echo "Checking for Power optimizations support... No." | tee -a configure.log
fi

# show the results in the log
echo >> configure.log
echo ALL = $ALL >> configure.log
Expand Down
8 changes: 8 additions & 0 deletions contrib/README.contrib
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
blast/ by Mark Adler <madler@alumni.caltech.edu>
Decompressor for output of PKWare Data Compression Library (DCL)

gcc/ by Matheus Castanho <msc@linux.ibm.com>
and Rogerio Alves <rcardoso@linux.ibm.com>
Optimization helpers using GCC-specific extensions

delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
Support for Delphi and C++ Builder

Expand Down Expand Up @@ -42,6 +46,10 @@ minizip/ by Gilles Vollant <info@winimage.com>
pascal/ by Bob Dellaca <bobdl@xtra.co.nz> et al.
Support for Pascal

power/ by Matheus Castanho <msc@linux.ibm.com>
and Rogerio Alves <rcardoso@linux.ibm.com>
Optimized functions for Power processors

puff/ by Mark Adler <madler@alumni.caltech.edu>
Small, low memory usage inflate. Also serves to provide an
unambiguous description of the deflate format.
Expand Down
60 changes: 60 additions & 0 deletions contrib/gcc/zifunc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* Copyright (C) 2019 Matheus Castanho <msc@linux.ibm.com>, IBM
* 2019 Rogerio Alves <rogerio.alves@ibm.com>, IBM
* For conditions of distribution and use, see copyright notice in zlib.h
*/

#ifndef Z_IFUNC_H_
#define Z_IFUNC_H_

/* Helpers for arch optimizations */

#define Z_IFUNC(fname) \
typeof(fname) fname __attribute__ ((ifunc (#fname "_resolver"))); \
local typeof(fname) *fname##_resolver(void)
/* This is a helper macro to declare a resolver for an indirect function
* (ifunc). Let's say you have function
*
* int foo (int a);
*
* for which you want to provide different implementations, for example:
*
* int foo_clever (int a) {
* ... clever things ...
* }
*
* int foo_smart (int a) {
* ... smart things ...
* }
*
* You will have to declare foo() as an indirect function and also provide a
* resolver for it, to choose between foo_clever() and foo_smart() based on
* some criteria you define (e.g. processor features).
*
* Since most likely foo() has a default implementation somewhere in zlib, you
* may have to rename it so the 'foo' symbol can be used by the ifunc without
* conflicts.
*
* #define foo foo_default
* int foo (int a) {
* ...
* }
* #undef foo
*
* Now you just have to provide a resolver function to choose which function
* should be used (decided at runtime on the first call to foo()):
*
* Z_IFUNC(foo) {
* if (... some condition ...)
* return foo_clever;
*
* if (... other condition ...)
* return foo_smart;
*
* return foo_default;
* }
*
* All calls to foo() throughout the code can remain untouched, all the magic
* will be done by the linker using the resolver function.
*/

#endif /* Z_IFUNC_H_ */
4 changes: 4 additions & 0 deletions contrib/power/power.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Copyright (C) 2019 Matheus Castanho <msc@linux.ibm.com>, IBM
* 2019 Rogerio Alves <rogerio.alves@ibm.com>, IBM
* For conditions of distribution and use, see copyright notice in zlib.h
*/