Skip to content

Commit 36594a1

Browse files
iii-ifneddy
andcommitted
s390x: vectorize crc32
Use vector extensions when compiling for s390x and binutils knows about them. At runtime, check whether kernel supports vector extensions (it has to be not just the CPU, but also the kernel) and choose between the regular and the vectorized implementations. Co-authored-by: Eduard Stefes <[email protected]>
1 parent 5a82f71 commit 36594a1

File tree

10 files changed

+436
-0
lines changed

10 files changed

+436
-0
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ if(NOT ZLIB_CONF_WRITTEN)
7676
mark_as_advanced(ZLIB_CONF_WRITTEN)
7777
endif(NOT ZLIB_CONF_WRITTEN)
7878

79+
#
80+
# Add contrib code
81+
#
82+
add_subdirectory(contrib/s390x)
7983
#
8084
# Check to see if we have large file support
8185
#
@@ -201,6 +205,7 @@ if(ZLIB_BUILD_SHARED)
201205
UNIX
202206
AND NOT APPLE
203207
AND NOT (CMAKE_SYSTEM_NAME STREQUAL AIX))
208+
target_link_libraries(zlib PRIVATE $<TARGET_NAME_IF_EXISTS:zlib_crc32_vx>)
204209
endif(ZLIB_BUILD_SHARED)
205210

206211
if(ZLIB_BUILD_STATIC)
@@ -223,6 +228,7 @@ if(ZLIB_BUILD_STATIC)
223228
set_target_properties(
224229
zlibstatic PROPERTIES EXPORT_NAME ZLIBSTATIC OUTPUT_NAME
225230
z${zlib_static_suffix})
231+
target_link_libraries(zlibstatic PRIVATE $<TARGET_NAME_IF_EXISTS:zlib_crc32_vx>)
226232
endif(ZLIB_BUILD_STATIC)
227233

228234
if(ZLIB_INSTALL)

Makefile.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ LDFLAGS=
2727
TEST_LIBS=-L. libz.a
2828
LDSHARED=$(CC)
2929
CPP=$(CC) -E
30+
VGFMAFLAG=
3031

3132
STATICLIB=libz.a
3233
SHAREDLIB=libz.so
@@ -164,6 +165,9 @@ adler32.o: $(SRCDIR)adler32.c
164165
crc32.o: $(SRCDIR)crc32.c
165166
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c
166167

168+
crc32_vx.o: $(SRCDIR)contrib/s390x/crc32_vx.c
169+
$(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/s390x/crc32_vx.c
170+
167171
deflate.o: $(SRCDIR)deflate.c
168172
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c
169173

@@ -214,6 +218,11 @@ crc32.lo: $(SRCDIR)crc32.c
214218
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c
215219
-@mv objs/crc32.o $@
216220

221+
crc32_vx.lo: $(SRCDIR)contrib/s390x/crc32_vx.c
222+
-@mkdir objs 2>/dev/null || test -d objs
223+
$(CC) $(SFLAGS) $(VGFMAFLAG) $(ZINC) -DPIC -c -o objs/crc32_vx.o $(SRCDIR)contrib/s390x/crc32_vx.c
224+
-@mv objs/crc32_vx.o $@
225+
217226
deflate.lo: $(SRCDIR)deflate.c
218227
-@mkdir objs 2>/dev/null || test -d objs
219228
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c
@@ -406,6 +415,7 @@ infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.
406415
inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
407416
inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
408417
trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
418+
crc32_vx.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/s390x/crc32_vx_hooks.h
409419

410420
adler32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
411421
zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
@@ -417,3 +427,4 @@ infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftree
417427
inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
418428
inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
419429
trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
430+
crc32_vx.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/s390x/crc32_vx_hooks.h

configure

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ debug=0
9393
address=0
9494
memory=0
9595
unknown=0
96+
enable_crcvx=1
9697
old_cc="$CC"
9798
old_cflags="$CFLAGS"
9899
OBJC='$(OBJZ) $(OBJG)'
@@ -120,6 +121,7 @@ case "$1" in
120121
echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log
121122
echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
122123
echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
124+
echo ' [--disable-crcvx]' | tee -a configure.log
123125
exit 0 ;;
124126
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
125127
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
@@ -146,6 +148,7 @@ case "$1" in
146148
--sanitize) address=1; shift ;;
147149
--address) address=1; shift ;;
148150
--memory) memory=1; shift ;;
151+
--disable-crcvx) enable_crcvx=0; shift ;;
149152
*) unknown=1; echo "unknown option ignored: $1" | tee -a configure.log; shift;;
150153
esac
151154
done
@@ -870,6 +873,70 @@ EOF
870873
fi
871874
fi
872875

876+
# check for ibm s390x build
877+
HAVE_S390X=0
878+
cat > $test.c << EOF
879+
#ifndef __s390x__
880+
#error
881+
#endif
882+
EOF
883+
if try $CC -c $CFLAGS $test.c; then
884+
echo "Checking for s390x build ... Yes." | tee -a configure.log
885+
HAVE_S390X=1
886+
else
887+
echo "Checking for s390x build ... No." | tee -a configure.log
888+
fi
889+
890+
# check for ibm s390x vx vector extensions
891+
HAVE_S390X_VX=0
892+
if test $HAVE_S390X -eq 1 && test $enable_crcvx -eq 1 ; then
893+
# preset the compiler specific flags
894+
if test $clang -eq 1; then
895+
VGFMAFLAG=-fzvector
896+
else
897+
VGFMAFLAG=-mzarch
898+
fi
899+
900+
cat > $test.c <<EOF
901+
#ifndef __s390x__
902+
#error
903+
#endif
904+
#include <vecintrin.h>
905+
int main(void) {
906+
unsigned long long a __attribute__((vector_size(16))) = { 0 };
907+
unsigned long long b __attribute__((vector_size(16))) = { 0 };
908+
unsigned char c __attribute__((vector_size(16))) = { 0 };
909+
c = vec_gfmsum_accum_128(a, b, c);
910+
return c[0];
911+
}
912+
EOF
913+
914+
# cflags already contains a valid march
915+
if try $CC -c $CFLAGS $VGFMAFLAG $test.c; then
916+
echo "Checking for s390x vx vector extension ... Yes." | tee -a configure.log
917+
HAVE_S390X_VX=1
918+
# or set march for our compile units
919+
elif try $CC -c $CFLAGS $VGFMAFLAG -march=z13 $test.c; then
920+
echo "Checking for s390x vx vector extension (march=z13) ... Yes." | tee -a configure.log
921+
HAVE_S390X_VX=1
922+
VGFMAFLAG="$VGFMAFLAG -march=z13"
923+
# else we are not on s390x
924+
else
925+
echo "Checking for s390x vx vector extension ... No." | tee -a configure.log
926+
fi
927+
928+
# prepare compiling for s390x
929+
if test $HAVE_S390X_VX -eq 1; then
930+
CFLAGS="$CFLAGS -DHAVE_S390X_VX"
931+
SFLAGS="$SFLAGS -DHAVE_S390X_VX"
932+
OBJC="$OBJC crc32_vx.o"
933+
PIC_OBJC="$PIC_OBJC crc32_vx.lo"
934+
else
935+
# target has no vx extension
936+
VGFMAFLAG=""
937+
fi
938+
fi
939+
873940
# show the results in the log
874941
echo >> configure.log
875942
echo ALL = $ALL >> configure.log
@@ -901,6 +968,9 @@ echo mandir = $mandir >> configure.log
901968
echo prefix = $prefix >> configure.log
902969
echo sharedlibdir = $sharedlibdir >> configure.log
903970
echo uname = $uname >> configure.log
971+
echo HAVE_S390X = $HAVE_S390X >> configure.log
972+
echo HAVE_S390X_VX = $HAVE_S390X_VX >> configure.log
973+
echo VGFMAFLAG = $VGFMAFLAG >> configure.log
904974

905975
# update Makefile with the configure results
906976
sed < ${SRCDIR}Makefile.in "

contrib/README.contrib

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ puff/ by Mark Adler <[email protected]>
4646
Small, low memory usage inflate. Also serves to provide an
4747
unambiguous description of the deflate format.
4848

49+
s390x/ by Ilya Leoshkevich <[email protected]>
50+
Hardware-accelerated CRC32 on IBM Z with Z13 VX extension.
51+
4952
testzlib/ by Gilles Vollant <[email protected]>
5053
Example of the use of zlib
5154

contrib/hooks.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef Z_HOOKS_H__
2+
#define Z_HOOKS_H__
3+
4+
#ifdef HAVE_S390X_VX
5+
#include "s390x/crc32_vx_hooks.h"
6+
#endif
7+
8+
#endif

contrib/s390x/CMakeLists.txt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
option(ZLIB_CRC32VX "Enable building S390-CRC32VX implementation" ON)
2+
3+
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
4+
5+
#
6+
# check if we compile for IBM s390x
7+
#
8+
CHECK_C_SOURCE_COMPILES("
9+
#ifndef __s390x__
10+
#error
11+
#endif
12+
" HAS_S390X_SUPPORT)
13+
14+
#
15+
# Check for IBM S390X - VX extensions
16+
#
17+
if(ZLIB_CRC32VX AND HAS_S390X_SUPPORT)
18+
# preset the compiler specific flags
19+
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
20+
set(VGFMAFLAG "-fzvector")
21+
else()
22+
set(VGFMAFLAG "-mzarch")
23+
endif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
24+
25+
set(S390X_VX_TEST
26+
"#ifndef __s390x__ \n\
27+
#error \n\
28+
#endif \n\
29+
#include <vecintrin.h> \n\
30+
int main(void) { \
31+
unsigned long long a __attribute__((vector_size(16))) = { 0 }; \
32+
unsigned long long b __attribute__((vector_size(16))) = { 0 }; \
33+
unsigned char c __attribute__((vector_size(16))) = { 0 }; \
34+
c = vec_gfmsum_accum_128(a, b, c); \
35+
return c[0]; \
36+
}")
37+
38+
# cflags already contains a valid march
39+
set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG}")
40+
check_c_source_compiles("${S390X_VX_TEST}" HAS_S390X_VX_SUPPORT)
41+
unset(CMAKE_REQUIRED_FLAGS)
42+
43+
# or set march for our compile units
44+
if(NOT HAS_S390X_VX_SUPPORT)
45+
set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG} -march=z13")
46+
check_c_source_compiles("${S390X_VX_TEST}" HAS_Z13_S390X_VX_SUPPORT)
47+
unset(CMAKE_REQUIRED_FLAGS )
48+
list(APPEND VGFMAFLAG "-march=z13")
49+
endif(NOT HAS_S390X_VX_SUPPORT)
50+
51+
# prepare compiling for s390x
52+
if(HAS_S390X_VX_SUPPORT OR HAS_Z13_S390X_VX_SUPPORT)
53+
add_library(zlib_crc32_vx OBJECT
54+
crc32_vx.c
55+
crc32_vx_hooks.h)
56+
set_source_files_properties(
57+
crc32_vx.c
58+
PROPERTIES COMPILE_OPTIONS "${VGFMAFLAG}")
59+
target_compile_definitions(zlib_crc32_vx PUBLIC HAVE_S390X_VX=1)
60+
endif(HAS_S390X_VX_SUPPORT OR HAS_Z13_S390X_VX_SUPPORT)
61+
endif(ZLIB_CRC32VX AND HAS_S390X_SUPPORT)

contrib/s390x/README

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
IBM Z mainframes starting from version z13 provide vector instructions, which
2+
allows vectorization of crc32. This extension is build by default when targeting
3+
ibm s390x. However this extension can disabled if desired:
4+
5+
# for configure build
6+
$ ./configure --disable-crcvx
7+
8+
# for cmake build
9+
$ cmake .. -DZLIB_CRC32VX=off

0 commit comments

Comments
 (0)