rsimd

Make SIMD instruction sets easier to use
git clone git://git.meso-star.fr/rsimd.git
Log | Files | Refs | README | LICENSE

commit 829bddd3166109fff8f122fd174f9b76846f53f5
parent 2d151ca93128a8e01479e1bcec350b73f07aafd4
Author: vaplv <vaplv@free.fr>
Date:   Fri, 17 Mar 2023 11:57:40 +0100

Write a POSIX Makefile as an alternative to CMake

Diffstat:
M.gitignore | 13++++++++-----
AMakefile | 177+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.mk | 36++++++++++++++++++++++++++++++++++++
Amake.sh | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arsimd.pc.in | 12++++++++++++
5 files changed, 415 insertions(+), 5 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,10 +1,13 @@ .gitignore -CMakeCache.txt -CMakeFiles -Makefile -tmp [Bb]uild* *.sw[po] -*.[ao] +*.[aod] +*.so *~ tags +test* +!test*.[ch] +.test +.simd +.pkg +rsimd.pc diff --git a/Makefile b/Makefile @@ -0,0 +1,177 @@ +# Copyright (C) 2014-2019, 2021, 2023 Vincent Forest (vaplv@free.fr) +# +# This CMake script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This CMake script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this CMake script. If not, see <http://www.gnu.org/licenses/>. + +.POSIX: +.SUFFIXES: # Clean up default inference rules + +include config.mk + +################################################################################ +# RSys building +################################################################################ +SRC = $(SRC_SIMD)\ + src/aosf44.c\ + src/aosq.c\ + src/math4.c + +OBJ = $(SRC:.c=.o) +DEP = $(SRC:.c=.d) + +build_library: .simd .pkg $(DEP) + @$(MAKE) -f.simd -fMakefile $$(for i in $(DEP); do echo -f $${i}; done) librsimd.so + +$(OBJ): config.mk + +librsimd.so: $(OBJ) + @echo "LD $@" + @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) + +.simd: make.sh config.mk + @$(SHELL) make.sh config_simd > $@ + +.pkg: make.sh config.mk + @$(SHELL) make.sh config_pkg && echo "pkg done" > $@ || exit 1 + +.SUFFIXES: .c .d .o +.c.d: + @$(CC) $(CFLAGS) $(INCS) -MM -MT "$(@:.d=.o) $@" $< -MF $@ + +.c.o: + @echo "CC $@" + @$(CC) $(CFLAGS) $(INCS) -DRSIMD_SHARED_BUILD -c $< -o $@ + +################################################################################ +# Miscellaneous targets +################################################################################ +all: build_library build_tests + +clean: .simd + @$(MAKE) -f.simd -fMakefile clean__ + +clean__: clean_test + @rm -f $(OBJ) $(TEST_OBJ) librsimd.so rsimd.pc .pkg .simd + +distclean: clean + @rm -f $(DEP) $(TEST_DEP) .test + +################################################################################ +# Installation +################################################################################ +API_REGULAR=\ + src/aosf33.h\ + src/aosf44.h\ + src/aosq.h\ + src/math.h\ + src/mathX.h\ + src/math4.h\ + src/math8.h\ + src/rsimd.h\ + src/soaXfY.h\ + src/soaXfY_begin.h\ + src/soaXfY_end.h\ + src/soaXf2.h\ + src/soaXf3.h\ + src/soa4f2.h\ + src/soa4f3.h\ + src/soa4f4.h\ + src/soa8f2.h\ + src/soa8f3.h\ + src/soa8f4.h\ + src/vXf_begin.h\ + src/vXf_end.h +API_AVX=\ + src/avx/avx.h\ + src/avx/avxf.h\ + src/avx/avxi.h +API_SSE=\ + src/sse/sse.h\ + src/sse/ssef.h\ + src/sse/ssei.h\ + src/sse/sse_swz.h + +pkg: .simd + @$(MAKE) -f.simd -fMakefile pkg__ + +pkg__: + @echo "Setup rsimd.pc" + @sed -e 's#@PREFIX@#$(PREFIX)#g' \ + -e 's#@VERSION@#$(VERSION)#g' \ + -e 's#@SLEEF_VERSION@#$(SLEEF_VERSION)#g' \ + -e 's#@RSYS_VERSION@#$(RSYS_VERSION)#g' \ + -e 's#@CFLAGS_SIMD@#$(CFLAGS_SIMD)#g' \ + rsimd.pc.in > rsimd.pc + +install: build_library pkg + mkdir -p $(DESTDIR)$(PREFIX)/lib + mkdir -p $(DESTDIR)$(PREFIX)/lib/pkgconfig + mkdir -p $(DESTDIR)$(PREFIX)/include/rsimd/avx + mkdir -p $(DESTDIR)$(PREFIX)/include/rsimd/sse + mkdir -p $(DESTDIR)$(PREFIX)/share/doc/rsimd + cp librsimd.so $(DESTDIR)$(PREFIX)/lib + cp rsimd.pc $(DESTDIR)$(PREFIX)/lib/pkgconfig + cp COPYING README.md $(DESTDIR)$(PREFIX)/share/doc/rsimd + cp $(API_REGULAR) $(DESTDIR)$(PREFIX)/include/rsimd + cp $(API_AVX) $(DESTDIR)$(PREFIX)/include/rsimd/avx + cp $(API_SSE) $(DESTDIR)$(PREFIX)/include/rsimd/sse + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/lib/librsimd.so + rm -f $(DESTDIR)$(PREFIX)/lib/pkgconfig/rsimd.pc + rm -f $(DESTDIR)$(PREFIX)/share/doc/rsimd/COPYING + rm -f $(DESTDIR)$(PREFIX)/share/doc/rsimd/README.md + rm -f $$(echo $(API_REGULAR) | sed 's,src\/,$(DESTDIR)$(PREFIX)\/include\/rsimd\/,g') + rm -f $$(echo $(API_AVX) | sed 's,src\/,$(DESTDIR)$(PREFIX)\/include\/rsimd\/,g') + rm -f $$(echo $(API_SSE) | sed 's,src\/,$(DESTDIR)$(PREFIX)\/include\/rsimd\/,g') + +################################################################################ +# Tests +################################################################################ +TEST_SSE2 =\ + test_aosf33\ + test_aosf44\ + test_aosq\ + test_math4\ + test_soa4f2\ + test_soa4f3\ + test_soa4f4\ + test_v4f\ + test_v4i +TEST_AVX =\ + test_math8\ + test_soa8f2\ + test_soa8f3\ + test_soa8f4 +TEST_SSE4_1 =\ + test_v4f_sse4_1\ + test_v4i_sse4_1 +TEST_FMA =\ + test_v4f_fma\ + test_soa8f2_fma\ + test_soa8f3_fma\ + test_soa8f4_fma + +TEST = $(TEST_SSE2) $(TEST_AVX) $(TEST_SSE4_1) $(TEST_FMA) + +test: build_tests + @$(SHELL) make.sh run_test $(TEST) + +build_tests: build_library .test + @$(MAKE) -fMakefile -f.test test_bin + +.test: make.sh config.mk + @$(SHELL) make.sh config_test $(TEST) > $@ + +clean_test: + @$(SHELL) make.sh clean_test $(TEST) diff --git a/config.mk b/config.mk @@ -0,0 +1,36 @@ +VERSION = 0.3.0 # Library version + +PREFIX = /usr/local +PKG_CONFIG = pkg-config + +################################################################################ +# Dependencies +################################################################################ +RSYS_VERSION = 0.12 +RSYS_INC = $$($(PKG_CONFIG) --cflags rsys) +RSYS_LIB = $$($(PKG_CONFIG) --libs rsys) + +SLEEF_VERSION = 3.6 +SLEEF_INC = $$($(PKG_CONFIG) --cflags sleef) +SLEEF_LIB = $$($(PKG_CONFIG) --libs sleef) + +INCS = $(RSYS_INC) $(SLEEF_INC) +LIBS = $(RSYS_LIB) $(SLEEF_LIB) + +################################################################################ +# Compilation options +################################################################################ +CC = cc # Compiler + +CPPFLAGS = -DNDEBUG +WFLAGS =\ + -Wall\ + -Wconversion\ + -Wextra\ + -Wmissing-declarations\ + -Wmissing-prototypes\ + -Wshadow + +CFLAGS = -O2 -std=c99 -pedantic -fPIC -fvisibility=hidden -fstrict-aliasing\ + -Wl,--no-undefined $(WFLAGS) $(CPPFLAGS) $(CFLAGS_SIMD)# Compiler options +LDFLAGS = -shared # Linker options diff --git a/make.sh b/make.sh @@ -0,0 +1,182 @@ +#!/bin/sh -e + +# Copyright (C) 2014-2019, 2021, 2023 Vincent Forest (vaplv@free.fr) +# +# This CMake script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This CMake script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this CMake script. If not, see <http://www.gnu.org/licenses/>. + +################################################################################ +# Helper functions +################################################################################ +# Print the value of a variable in config.mk +showvar() +{ + # To avoid messages from Make being displayed instead of the value of the + # queried variable, we redirect its output to /dev/null and open a new file + # descriptor to stdout to print the variable +<< EOF make -f 3>&1 1>/dev/null 2>&1 - || kill -HUP $$ +.POSIX: +include config.mk +showvar: + @1>&3 echo \$(${1}) +EOF + exec 3<&- # Close file descriptor 3 +} + +check_cpuflag() +{ + sed -n "/^flags[[:blank:]]\{1,\}:/{p;q}" /proc/cpuinfo \ +| sed "s/.*[[:blank:]]\{1,\}\($1\)[[:blank:]]\{1,\}.*/\1/" +} + +################################################################################ +# Main functions +################################################################################ +run_test() +{ + n=0 + + for i in "$@"; do + printf "%s " "${i}" + if ./"${i}" > /dev/null 2>&1; then + printf "\e[1;32mOK\e[m\n" + else + printf "\e[1;31mErreur\e[m\n" + n=$((n+1)) + fi + done + + if [ "${n}" -ne 0 ]; then + printf "%d errors\n" "${n}" + exit 1 + fi +} + +clean_test() +{ + for i in "$@"; do + rm -f "${i}" + done +} + +config_simd() +{ + cflags="" + src="" + + sse2="$(check_cpuflag sse2)" + sse4_1="$(check_cpuflag sse4_1)" + avx="$(check_cpuflag avx)" + fma="$(check_cpuflag fma)" + + if [ -z "${sse2}" ]; then + >&2 echo "The SSE2 instruction set must be supported." + exit 1 + else + >&2 echo "Use the SSE2 instruction set" + cflags="${cflags} -msse2" + fi + + if [ -n "${sse4_1}" ]; then + >&2 echo "Use the SSE4.1 instruction set" + cflags="${cflags} -msse4.1" + fi + + if [ -n "${avx}" ]; then + >&2 echo "Use the AVX instruction set" + cflags="${cflags} -mavx" + src="${src} src/math8.c" + fi + + if [ -n "${fma}" ]; then + >&2 echo "Use the FMA instruction set" + cflags="${cflags} -mfma" + fi + + printf "CFLAGS_SIMD = %s\n" "${cflags}" + printf "SRC_SIMD = %s\n" "${src}" +} + +config_test() +{ + sse4_1="$(check_cpuflag sse4_1)" + avx="$(check_cpuflag avx)" + fma="$(check_cpuflag fma)" + + cc="$(showvar CC)" + cflags="$(showvar CFLAGS)" + incs="$(showvar INCS)" + + for i in "$@"; do + cflags="" + case "${i}" in + *_sse4_1) + [ -z "${sse4_1}" ] && continue + prefix=$(echo "${i}" | sed 's/_sse4_1//') + cflags="-msse4.1" + ;; + *_fma) + [ -z "${fma}" ] && continue + prefix=$(echo "${i}" | sed 's/_fma//') + cflags="-mfma" + ;; + test_soa8* | test_math8) + [ -z "${avx}" ] && continue + prefix="${i}" + cflags="-mavx" + ;; + *) + prefix="${i}" + cflags="-msse2" + ;; + esac + + printf "%s: librsimd.so\n" "${i}" + + # shellcheck disable=SC2086 + ${cc} ${cflags} ${incs} -MM -MT "${i}" "src/${prefix}.c" -MF - + + printf "\t@echo \"CC \$@\"\n" + printf "\t@\$(CC) \$(CFLAGS) %s \$(RSYS_INC) -L\$\$(pwd) "\ +"-o \$@ src/%s.c -lrsimd -lm\n" "${cflags}" "${prefix}" + + test_list="${test_list} ${i}" + done + printf "test_bin: %s\n" "${test_list}" +} + + +config_pkg() +{ + pkg_config=$(showvar PKG_CONFIG) + + rsys_version=$(showvar RSYS_VERSION) + sleef_version=$(showvar SLEEF_VERSION) + dependencies="\ + RSys rsys ${rsys_version} + Sleef sleef ${sleef_version}" + + printf "%s\n" "${dependencies}" | while read -r i; do + name=$(printf "%s" "${i}" | cut -d' ' -f1) + pc=$(printf "%s" "${i}" | cut -d' ' -f2) + version=$(printf "%s" "${i}" | cut -d' ' -f3) + + if ! "${pkg_config}" --atleast-version "${version}" "${pc}"; then + >&2 printf "\e[1;31merror\e[0m:%s %s: dependency is missing\n" \ + "${name}" "${version}" + exit 1 + fi + done || exit $? +} + +"$@" diff --git a/rsimd.pc.in b/rsimd.pc.in @@ -0,0 +1,12 @@ +prefix=@PREFIX@ +includedir=${prefix}/include +libdir=${prefix}/lib +cflags_simd=@CFLAGS_SIMD@ + +Requires: rsys >= @RSYS_VERSION@ +Requires.private: sleef >= @SLEEF_VERSION@ +Name: RSIMD +Description: RSIMD library +Version: @VERSION@ +Libs: -L${libdir} -lrsimd +CFlags: -I${includedir} ${cflags_simd}