Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions HashLib.Benchmark/Delphi/PerformanceBenchmarkConsole.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ uses
HlpMurmur2_64 in '..\..\HashLib\src\Hash64\HlpMurmur2_64.pas',
HlpSipHash in '..\..\HashLib\src\Hash64\HlpSipHash.pas',
HlpXXHash64 in '..\..\HashLib\src\Hash64\HlpXXHash64.pas',
HlpXXHash3Dispatch in '..\..\HashLib\src\Hash64\HlpXXHash3Dispatch.pas',
HlpXXHash3 in '..\..\HashLib\src\Hash64\HlpXXHash3.pas',
HlpMurmurHash3_x86_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x86_128.pas',
HlpMurmurHash3_x64_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x64_128.pas',
Expand All @@ -108,6 +109,7 @@ uses
HlpConverters in '..\..\HashLib\src\Utils\HlpConverters.pas',
HlpBitConverter in '..\..\HashLib\src\Utils\HlpBitConverter.pas',
HlpBits in '..\..\HashLib\src\Utils\HlpBits.pas',
HlpSimd in '..\..\HashLib\src\Utils\HlpSimd.pas',
HlpHashLibTypes in '..\..\HashLib\src\Utils\HlpHashLibTypes.pas',
HlpArrayUtils in '..\..\HashLib\src\Utils\HlpArrayUtils.pas';

Expand Down
2 changes: 2 additions & 0 deletions HashLib.Benchmark/Delphi/PerformanceBenchmarkFMX.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ uses
HlpMurmur2_64 in '..\..\HashLib\src\Hash64\HlpMurmur2_64.pas',
HlpSipHash in '..\..\HashLib\src\Hash64\HlpSipHash.pas',
HlpXXHash64 in '..\..\HashLib\src\Hash64\HlpXXHash64.pas',
HlpXXHash3Dispatch in '..\..\HashLib\src\Hash64\HlpXXHash3Dispatch.pas',
HlpXXHash3 in '..\..\HashLib\src\Hash64\HlpXXHash3.pas',
HlpMurmurHash3_x86_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x86_128.pas',
HlpMurmurHash3_x64_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x64_128.pas',
Expand All @@ -107,6 +108,7 @@ uses
HlpConverters in '..\..\HashLib\src\Utils\HlpConverters.pas',
HlpBitConverter in '..\..\HashLib\src\Utils\HlpBitConverter.pas',
HlpBits in '..\..\HashLib\src\Utils\HlpBits.pas',
HlpSimd in '..\..\HashLib\src\Utils\HlpSimd.pas',
HlpHashLibTypes in '..\..\HashLib\src\Utils\HlpHashLibTypes.pas',
HlpArrayUtils in '..\..\HashLib\src\Utils\HlpArrayUtils.pas';

Expand Down
2 changes: 2 additions & 0 deletions HashLib.Tests/Delphi.Tests/HashLib.Tests.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ uses
HlpMurmur2_64 in '..\..\HashLib\src\Hash64\HlpMurmur2_64.pas',
HlpSipHash in '..\..\HashLib\src\Hash64\HlpSipHash.pas',
HlpXXHash64 in '..\..\HashLib\src\Hash64\HlpXXHash64.pas',
HlpXXHash3Dispatch in '..\..\HashLib\src\Hash64\HlpXXHash3Dispatch.pas',
HlpXXHash3 in '..\..\HashLib\src\Hash64\HlpXXHash3.pas',
HlpMurmurHash3_x86_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x86_128.pas',
HlpMurmurHash3_x64_128 in '..\..\HashLib\src\Hash128\HlpMurmurHash3_x64_128.pas',
Expand All @@ -129,6 +130,7 @@ uses
HlpConverters in '..\..\HashLib\src\Utils\HlpConverters.pas',
HlpBitConverter in '..\..\HashLib\src\Utils\HlpBitConverter.pas',
HlpBits in '..\..\HashLib\src\Utils\HlpBits.pas',
HlpSimd in '..\..\HashLib\src\Utils\HlpSimd.pas',
HlpHashLibTypes in '..\..\HashLib\src\Utils\HlpHashLibTypes.pas',
HlpArrayUtils in '..\..\HashLib\src\Utils\HlpArrayUtils.pas',
HashLibTestBase in '..\src\HashLibTestBase.pas',
Expand Down
32 changes: 7 additions & 25 deletions HashLib/src/Hash64/HlpXXHash3.pas
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ TXXH3_State = record

implementation

uses
HlpXXHash3Dispatch;

{ TXXH3Core }

class function TXXH3Core.XXH_mult32to64(AX, AY: UInt32): UInt64;
Expand Down Expand Up @@ -283,11 +286,8 @@ class procedure TXXH3Core.XXH3_scalarRound(var AAcc: TXXH3AccArray;

class procedure TXXH3Core.XXH3_accumulate_512(var AAcc: TXXH3AccArray;
AInput, ASecret: PByte);
var
I: Int32;
begin
for I := 0 to XXH_ACC_NB - 1 do
XXH3_scalarRound(AAcc, AInput, ASecret, I);
HlpXXHash3Dispatch.XXH3_Accumulate512(@AAcc[0], AInput, ASecret);
end;

class procedure TXXH3Core.XXH3_scalarScrambleRound(var AAcc: TXXH3AccArray;
Expand All @@ -305,21 +305,14 @@ class procedure TXXH3Core.XXH3_scalarScrambleRound(var AAcc: TXXH3AccArray;

class procedure TXXH3Core.XXH3_scrambleAcc(var AAcc: TXXH3AccArray;
ASecret: PByte);
var
I: Int32;
begin
for I := 0 to XXH_ACC_NB - 1 do
XXH3_scalarScrambleRound(AAcc, ASecret, I);
HlpXXHash3Dispatch.XXH3_ScrambleAcc(@AAcc[0], ASecret);
end;

class procedure TXXH3Core.XXH3_accumulate(var AAcc: TXXH3AccArray;
AInput, ASecret: PByte; ANbStripes: Int32);
var
N: Int32;
begin
for N := 0 to ANbStripes - 1 do
XXH3_accumulate_512(AAcc, AInput + N * XXH_STRIPE_LEN,
ASecret + N * XXH_SECRET_CONSUME_RATE);
HlpXXHash3Dispatch.XXH3_Accumulate(@AAcc[0], AInput, ASecret, ANbStripes);
end;

class procedure TXXH3Core.XXH3_hashLong_internal_loop(
Expand Down Expand Up @@ -351,19 +344,8 @@ class procedure TXXH3Core.XXH3_hashLong_internal_loop(

class procedure TXXH3Core.XXH3_initCustomSecret(ACustomSecret: PByte;
ASeed: UInt64);
var
I: Int32;
LLo, LHi: UInt64;
begin
for I := 0 to (XXH3_SECRET_DEFAULT_SIZE div 16) - 1 do
begin
LLo := TConverters.ReadBytesAsUInt64LE(PByte(@XXH3_SECRET[0]),
16 * I) + ASeed;
LHi := TConverters.ReadBytesAsUInt64LE(PByte(@XXH3_SECRET[0]),
16 * I + 8) - ASeed;
PUInt64(ACustomSecret + 16 * I)^ := LLo;
PUInt64(ACustomSecret + 16 * I + 8)^ := LHi;
end;
HlpXXHash3Dispatch.XXH3_InitSecret(ACustomSecret, @XXH3_SECRET[0], ASeed);
end;

class procedure TXXH3Core.XXH3_consumeStripes(var AAcc: TXXH3AccArray;
Expand Down
213 changes: 213 additions & 0 deletions HashLib/src/Hash64/HlpXXHash3Dispatch.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
unit HlpXXHash3Dispatch;

{$I ..\Include\HashLib.inc}

interface

type
TXXH3Accumulate512Proc = procedure(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer);
TXXH3AccumulateProc = procedure(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer; ANbStripes: Int32);
TXXH3ScrambleAccProc = procedure(AAcc: Pointer; ASecret: Pointer);
TXXH3InitSecretProc = procedure(ACustomSecret: Pointer;
ADefaultSecret: Pointer; ASeed: UInt64);

var
XXH3_Accumulate512: TXXH3Accumulate512Proc;
XXH3_Accumulate: TXXH3AccumulateProc;
XXH3_ScrambleAcc: TXXH3ScrambleAccProc;
XXH3_InitSecret: TXXH3InitSecretProc;

implementation

uses
HlpSimd;

const
XXH_STRIPE_LEN = 64;
XXH_ACC_NB = 8;
XXH_SECRET_CONSUME_RATE = 8;
XXH_PRIME32_1 = UInt32($9E3779B1);

// =============================================================================
// Scalar fallback implementations
// =============================================================================

procedure XXH3_accumulate_512_scalar(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer);
var
LPAcc: PUInt64;
LPInput, LPSecret: PByte;
I: Int32;
LDataVal, LDataKey: UInt64;
begin
LPAcc := PUInt64(AAcc);
LPInput := PByte(AInput);
LPSecret := PByte(ASecret);
for I := 0 to XXH_ACC_NB - 1 do
begin
LDataVal := PUInt64(LPInput + I * 8)^;
LDataKey := LDataVal xor PUInt64(LPSecret + I * 8)^;
PUInt64(PByte(LPAcc) + (I xor 1) * 8)^ :=
PUInt64(PByte(LPAcc) + (I xor 1) * 8)^ + LDataVal;
PUInt64(PByte(LPAcc) + I * 8)^ :=
PUInt64(PByte(LPAcc) + I * 8)^ +
UInt64(UInt32(LDataKey)) * UInt64(UInt32(LDataKey shr 32));
end;
end;

procedure XXH3_scrambleAcc_scalar(AAcc: Pointer; ASecret: Pointer);
var
LPAcc: PUInt64;
LPSecret: PByte;
I: Int32;
LKey64, LAcc64: UInt64;
begin
LPAcc := PUInt64(AAcc);
LPSecret := PByte(ASecret);
for I := 0 to XXH_ACC_NB - 1 do
begin
LKey64 := PUInt64(LPSecret + I * 8)^;
LAcc64 := PUInt64(PByte(LPAcc) + I * 8)^;
LAcc64 := LAcc64 xor (LAcc64 shr 47);
LAcc64 := LAcc64 xor LKey64;
LAcc64 := LAcc64 * XXH_PRIME32_1;
PUInt64(PByte(LPAcc) + I * 8)^ := LAcc64;
end;
end;

procedure XXH3_initSecret_scalar(ACustomSecret: Pointer;
ADefaultSecret: Pointer; ASeed: UInt64);
var
I: Int32;
LPSrc, LPDst: PByte;
begin
LPSrc := PByte(ADefaultSecret);
LPDst := PByte(ACustomSecret);
for I := 0 to (192 div 16) - 1 do
begin
PUInt64(LPDst + 16 * I)^ := PUInt64(LPSrc + 16 * I)^ + ASeed;
PUInt64(LPDst + 16 * I + 8)^ := PUInt64(LPSrc + 16 * I + 8)^ - ASeed;
end;
end;

procedure XXH3_accumulate_scalar(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer; ANbStripes: Int32);
var
N: Int32;
begin
for N := 0 to ANbStripes - 1 do
XXH3_accumulate_512_scalar(AAcc, PByte(AInput) + N * XXH_STRIPE_LEN,
PByte(ASecret) + N * XXH_SECRET_CONSUME_RATE);
end;

// =============================================================================
// SSE2 and AVX2 implementations (x86-64 only)
// =============================================================================

{$IFDEF HASHLIB_X86_64}

// ----- SSE2 -----

procedure XXH3_accumulate_512_sse2(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer);
{$I ..\Include\Simd\Common\SimdProc3Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3Acc512Sse2.inc}
end;

procedure XXH3_scrambleAcc_sse2(AAcc: Pointer; ASecret: Pointer);
{$I ..\Include\Simd\Common\SimdProc2Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3ScrambleSse2.inc}
end;

procedure XXH3_initSecret_sse2(ACustomSecret: Pointer;
ADefaultSecret: Pointer; ASeed: UInt64);
{$I ..\Include\Simd\Common\SimdProc3Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3InitSecretSse2.inc}
end;

procedure XXH3_accumulate_sse2(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer; ANbStripes: Int32);
var
N: Int32;
begin
for N := 0 to ANbStripes - 1 do
XXH3_accumulate_512_sse2(AAcc, PByte(AInput) + N * XXH_STRIPE_LEN,
PByte(ASecret) + N * XXH_SECRET_CONSUME_RATE);
end;

{$IFDEF HASHLIB_AVX2_ASM_SUPPORTED}

// ----- AVX2 -----

procedure XXH3_accumulate_512_avx2(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer);
{$I ..\Include\Simd\Common\SimdProc3Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3Acc512Avx2.inc}
end;

procedure XXH3_scrambleAcc_avx2(AAcc: Pointer; ASecret: Pointer);
{$I ..\Include\Simd\Common\SimdProc2Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3ScrambleAvx2.inc}
end;

procedure XXH3_initSecret_avx2(ACustomSecret: Pointer;
ADefaultSecret: Pointer; ASeed: UInt64);
{$I ..\Include\Simd\Common\SimdProc3Begin.inc}
{$I ..\Include\Simd\XXH3\XXH3InitSecretAvx2.inc}
end;

procedure XXH3_accumulate_avx2(AAcc: Pointer; AInput: Pointer;
ASecret: Pointer; ANbStripes: Int32);
var
N: Int32;
begin
for N := 0 to ANbStripes - 1 do
XXH3_accumulate_512_avx2(AAcc, PByte(AInput) + N * XXH_STRIPE_LEN,
PByte(ASecret) + N * XXH_SECRET_CONSUME_RATE);
end;

{$ENDIF HASHLIB_AVX2_ASM_SUPPORTED}

{$ENDIF HASHLIB_X86_64}

// =============================================================================
// Dispatch initialization
// =============================================================================

procedure InitDispatch();
begin
case TSimd.GetActiveLevel() of
{$IFDEF HASHLIB_X86_64}
{$IFDEF HASHLIB_AVX2_ASM_SUPPORTED}
TSimdLevel.AVX2:
begin
XXH3_Accumulate512 := @XXH3_accumulate_512_avx2;
XXH3_Accumulate := @XXH3_accumulate_avx2;
XXH3_ScrambleAcc := @XXH3_scrambleAcc_avx2;
XXH3_InitSecret := @XXH3_initSecret_avx2;
end;
{$ENDIF HASHLIB_AVX2_ASM_SUPPORTED}
TSimdLevel.SSE2:
begin
XXH3_Accumulate512 := @XXH3_accumulate_512_sse2;
XXH3_Accumulate := @XXH3_accumulate_sse2;
XXH3_ScrambleAcc := @XXH3_scrambleAcc_sse2;
XXH3_InitSecret := @XXH3_initSecret_sse2;
end;
{$ENDIF}
TSimdLevel.Scalar:
begin
XXH3_Accumulate512 := @XXH3_accumulate_512_scalar;
XXH3_Accumulate := @XXH3_accumulate_scalar;
XXH3_ScrambleAcc := @XXH3_scrambleAcc_scalar;
XXH3_InitSecret := @XXH3_initSecret_scalar;
end;
end;
end;

initialization
InitDispatch();

end.
20 changes: 20 additions & 0 deletions HashLib/src/Include/HashLib.inc
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,24 @@
{$SCOPEDENUMS ON}
{$POINTERMATH ON}

{============================== SIMD Settings =================================}

{$IF DEFINED(CPUX86_64) OR DEFINED(CPUX64)}
{$DEFINE HASHLIB_X86_64}
{$IFEND}

{$IFDEF FPC}
{$IFDEF HASHLIB_X86_64}
{$DEFINE HASHLIB_AVX2_ASM_SUPPORTED}
{$ENDIF}
{$ENDIF}

// Uncomment ONE of the following to force a specific SIMD dispatch level:
// {$DEFINE HASHLIB_FORCE_SCALAR}
// {$DEFINE HASHLIB_FORCE_SSE2}

{$IF DEFINED(HASHLIB_FORCE_SCALAR) AND DEFINED(HASHLIB_FORCE_SSE2)}
{$MESSAGE ERROR 'HASHLIB_FORCE_SCALAR and HASHLIB_FORCE_SSE2 cannot both be defined. Enable only one.'}
{$IFEND}

(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
1 change: 1 addition & 0 deletions HashLib/src/Include/HashLibFPC.inc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

{$MODE DELPHI}
{$MACRO ON}
{$ASMMODE INTEL}
{$NOTES OFF}
{$OPTIMIZATION LEVEL3}
{$OPTIMIZATION NOUSELOADMODIFYSTORE}
Expand Down
19 changes: 19 additions & 0 deletions HashLib/src/Include/Simd/Common/SimdProc2Begin.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Shared SIMD procedure prologue for 2-parameter assembly functions.
// After inclusion: rcx = param1, rdx = param2 (MS x64 ABI).
// On FPC non-Windows (System V ABI), remaps rdi,rsi -> rcx,rdx.
// Usage:
// procedure MyProc(P1, P2: Pointer);
// {$I SimdProc2Begin.inc}
// // ... SIMD instructions using rcx, rdx ...
// end;
{$IFDEF FPC}
assembler; nostackframe;
asm
{$IFNDEF MSWINDOWS}
mov rdx, rsi
mov rcx, rdi
{$ENDIF}
{$ELSE}
asm
.noframe
{$ENDIF}
Loading
Loading