diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08d65cbc4..5a81bf262 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: - x86_64-linux-nowallet - x86_64-macos - x86_64-win + - x86_64-linux-experimental include: - name: i686-linux host: i686-pc-linux-gnu @@ -128,6 +129,14 @@ jobs: config-opts: "--enable-gui=qt5 --disable-tests" goal: deploy sdk: 10.11 + - name: x86_64-linux-experimental + host: x86_64-unknown-linux-gnu + os: ubuntu-20.04 + packages: bc python3-zmq + run-tests: true + dep-opts: "AVX2=1" + config-opts: "--with-intel-avx2 --enable-gui=qt5 --enable-zmq --enable-glibc-back-compat --enable-reduce-exports" + goal: install runs-on: ${{ matrix.os }} diff --git a/configure.ac b/configure.ac index 2f21427ae..c929e6709 100644 --- a/configure.ac +++ b/configure.ac @@ -177,6 +177,12 @@ AC_ARG_ENABLE([zmq], [use_zmq=$enableval], [use_zmq=yes]) +AC_ARG_WITH([intel-avx2], + [AS_HELP_STRING([--with-intel-avx2], + [Build with intel avx2 (default is no)])], + [intel_avx2=$withval], + [intel_avx2=no]) + AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) AC_ARG_ENABLE(man, @@ -787,6 +793,16 @@ fi fi +if test x$intel_avx2 = xyes; then + case $host in + x86_64-*-linux*) + AC_CHECK_LIB([IPSec_MB],[sha1_one_block_avx2],LIBS=-lIPSec_MB, AC_MSG_ERROR(IPSec_MB missing)) + AC_CHECK_LIB([IPSec_MB],[sha256_one_block_avx2],LIBS=-lIPSec_MB, AC_MSG_ERROR(IPSec_MB missing)) + AC_CHECK_LIB([IPSec_MB],[sha512_one_block_avx2],LIBS=-lIPSec_MB, AC_MSG_ERROR(IPSec_MB missing)) + AC_DEFINE(USE_AVX2, 1, [Define this symbol if intel axv2 works]) +esac +fi + if test x$use_pkgconfig = xyes; then : dnl m4_ifdef( diff --git a/depends/Makefile b/depends/Makefile index 17eac508d..e9fbdb8dd 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -6,6 +6,7 @@ SDK_PATH ?= $(BASEDIR)/SDKs NO_QT ?= NO_WALLET ?= NO_UPNP ?= +AVX2 ?= FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources BUILD = $(shell ./config.guess) @@ -92,14 +93,19 @@ $(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null) qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) wallet_packages_$(NO_WALLET) = $(wallet_packages) upnp_packages_$(NO_UPNP) = $(upnp_packages) +avx2_packages_$(AVX2) = $(avx2_$(host_arch)_$(host_os)_packages) -packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) +packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(avx2_packages_1) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) ifneq ($(qt_packages_),) native_packages += $(qt_native_packages) endif +ifneq ($(avx2_packages_1),) +native_packages += $(avx2_native_packages) +endif + all_packages = $(packages) $(native_packages) meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk diff --git a/depends/packages/intel-ipsec-mb.mk b/depends/packages/intel-ipsec-mb.mk new file mode 100644 index 000000000..881803fb1 --- /dev/null +++ b/depends/packages/intel-ipsec-mb.mk @@ -0,0 +1,19 @@ +package=intel-ipsec-mb +$(package)_version=1.0 +$(package)_download_path=https://github.com/intel/intel-ipsec-mb/archive/refs/tags +$(package)_file_name=v$($(package)_version).tar.gz +$(package)_sha256_hash=03501aea472d3c8fdf8f1f207816eefeaf5e4ebbdc71d88dcb26b2519841bb74 +$(package)_patches=remove_digest_init.patch +$(package)_dependencies=native_nasm + +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/remove_digest_init.patch +endef + +define $(package)_build_cmds + $(MAKE) NASM=$(build_prefix)/bin/nasm +endef + +define $(package)_stage_cmds + $(MAKE) NASM=$(build_prefix)/bin/nasm PREFIX=$($(package)_staging_prefix_dir) SHARED=n NOLDCONFIG=y install +endef diff --git a/depends/packages/native_nasm.mk b/depends/packages/native_nasm.mk new file mode 100644 index 000000000..b205279f3 --- /dev/null +++ b/depends/packages/native_nasm.mk @@ -0,0 +1,21 @@ +package=native_nasm +$(package)_version=2.15.05 +$(package)_download_path=http://nasm.us/pub/nasm/releasebuilds/$($(package)_version) +$(package)_file_name=nasm-$($(package)_version).tar.bz2 +$(package)_sha256_hash=3c4b8339e5ab54b1bcb2316101f8985a5da50a3f9e504d43fa6f35668bee2fd0 + +define $(package)_config_cmds + $($(package)_autoconf) +endef + +define $(package)_build_cmds + $(MAKE) +endef + +define $(package)_stage_cmds + $(MAKE) DESTDIR=$($(package)_staging_dir) install +endef + +define $(package)_postprocess_cmds + rm -rf share +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 42481389f..ceab33045 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -14,6 +14,9 @@ wallet_packages=bdb upnp_packages=miniupnpc +avx2_native_packages:=native_nasm +avx2_x86_64_linux_packages:=intel-ipsec-mb + darwin_native_packages = native_biplist native_ds_store native_mac_alias ifneq ($(build_os),darwin) diff --git a/depends/patches/intel-ipsec-mb/remove_digest_init.patch b/depends/patches/intel-ipsec-mb/remove_digest_init.patch new file mode 100644 index 000000000..0a8a5f3ba --- /dev/null +++ b/depends/patches/intel-ipsec-mb/remove_digest_init.patch @@ -0,0 +1,13 @@ +diff -dur a/lib/include/sha_generic.h b/lib/include/sha_generic.h +index 3752546..77efd91 100644 +--- a/lib/include/sha_generic.h ++++ b/lib/include/sha_generic.h +@@ -308,7 +308,7 @@ void sha_generic_1block(const void *data, void *digest, + if (data == NULL || digest == NULL) + return; + #endif +- sha_generic_init(digest, sha_type); ++// sha_generic_init(digest, sha_type); + sha_generic_one_block(data, digest, is_avx, sha_type); + #ifdef SAFE_DATA + clear_scratch_gps(); diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 0b895b33a..a5736edda 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -8,12 +8,20 @@ #include +#if (defined(__ia64__) || defined(__x86_64__)) && \ + (defined(__linux__) && !defined(__APPLE__)) && \ + (defined(USE_AVX2)) +#include +#endif + // Internal implementation code. namespace { /// Internal SHA-1 implementation. namespace sha1 { + +#ifndef USE_AVX2 /** One round of SHA-1. */ void inline Round(uint32_t a, uint32_t& b, uint32_t c, uint32_t d, uint32_t& e, uint32_t f, uint32_t k, uint32_t w) { @@ -26,6 +34,7 @@ uint32_t inline f2(uint32_t b, uint32_t c, uint32_t d) { return b ^ c ^ d; } uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & (b | c)); } uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); } +#endif /** Initialize SHA-1 state. */ void inline Initialize(uint32_t* s) @@ -45,6 +54,12 @@ const uint32_t k4 = 0xCA62C1D6ul; /** Perform a SHA-1 transformation, processing a 64-byte chunk. */ void Transform(uint32_t* s, const unsigned char* chunk) { +#ifdef USE_AVX2 + // Perform SHA1 one block (Intel AVX2) + sha1_one_block_avx2(chunk, s); +#else + // Perform SHA one block (legacy) + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; @@ -138,6 +153,9 @@ void Transform(uint32_t* s, const unsigned char* chunk) s[2] += c; s[3] += d; s[4] += e; + +#endif + } } // namespace sha1 diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 5b9f00a0a..7543468dc 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -8,12 +8,19 @@ #include +#if (defined(__ia64__) || defined(__x86_64__)) && \ + (defined(__linux__) && !defined(__APPLE__)) && \ + (defined(USE_AVX2)) +#include +#endif + // Internal implementation code. namespace { /// Internal SHA-256 implementation. namespace sha256 { +#ifndef USE_AVX2 uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } @@ -29,6 +36,7 @@ void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, u d += t1; h = t1 + t2; } +#endif /** Initialize SHA-256 state. */ void inline Initialize(uint32_t* s) @@ -46,6 +54,11 @@ void inline Initialize(uint32_t* s) /** Perform one SHA-256 transformation, processing a 64-byte chunk. */ void Transform(uint32_t* s, const unsigned char* chunk) { +#ifdef USE_AVX2 + // Perform SHA256 one block (Intel AVX2) + sha256_one_block_avx2(chunk, s); +#else + // Perform SHA256 one block (legacy) uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; @@ -125,6 +138,7 @@ void Transform(uint32_t* s, const unsigned char* chunk) s[5] += f; s[6] += g; s[7] += h; +#endif } } // namespace sha256 diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp index 564127cc3..052250394 100644 --- a/src/crypto/sha512.cpp +++ b/src/crypto/sha512.cpp @@ -8,12 +8,19 @@ #include +#if (defined(__ia64__) || defined(__x86_64__)) && \ + (defined(__linux__) && !defined(__APPLE__)) && \ + (defined(USE_AVX2)) +#include +#endif + // Internal implementation code. namespace { /// Internal SHA-512 implementation. namespace sha512 { +#ifndef USE_AVX2 uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); } uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); } uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); } @@ -29,6 +36,7 @@ void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t& d, uint64_t e, u d += t1; h = t1 + t2; } +#endif /** Initialize SHA-256 state. */ void inline Initialize(uint64_t* s) @@ -46,6 +54,11 @@ void inline Initialize(uint64_t* s) /** Perform one SHA-512 transformation, processing a 128-byte chunk. */ void Transform(uint64_t* s, const unsigned char* chunk) { +#ifdef USE_AVX2 + // Perform SHA512 one block (Intel AVX2) + sha512_one_block_avx2(chunk, s); +#else + // Perform SHA512 one block (legacy) uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; @@ -142,6 +155,7 @@ void Transform(uint64_t* s, const unsigned char* chunk) s[5] += f; s[6] += g; s[7] += h; +#endif } } // namespace sha512 @@ -205,3 +219,4 @@ CSHA512& CSHA512::Reset() sha512::Initialize(s); return *this; } +