mORMot and Open Source friends
Check-in [5447d35e1a]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1:5447d35e1afdc305ff061bad83c28729f2303552
Date: 2015-06-30 14:30:25
User: ab
Comment:{1584} SSE4.2 support for StrComp() and all internal UTF-8 text comparison process
Tags And Properties
Context
2015-06-30
21:49
[c6dad25635] {1585} introducing variable count of parameters for MVC Web (user: ab, tags: trunk)
14:30
[5447d35e1a] {1584} SSE4.2 support for StrComp() and all internal UTF-8 text comparison process (user: ab, tags: trunk)
12:49
[6f761b495d] {1583} StrLen() function will now use SSE4.2 instructions on supported CPUs (user: ab, tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SynCommons.pas.

2173
2174
2175
2176
2177
2178
2179

2180
2181
2182













2183
2184
2185
2186
2187
2188
2189
....
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
....
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
.....
18441
18442
18443
18444
18445
18446
18447
18448
18449
18450


18451
18452
18453
18454
18455
18456
18457
18458
18459
18460
18461
18462
18463
18464
18465
18466
18467

18468


18469
18470
18471
18472
18473
18474
18475
.....
18489
18490
18491
18492
18493
18494
18495

















18496





























18497














































18498
18499
18500
18501
18502
18503
18504
.....
29778
29779
29780
29781
29782
29783
29784
29785
29786
29787
29788
29789
29790
29791
29792
29793
29794
29795
29796
29797
29798
29799
29800
29801
29802
29803
29804
29805
29806
29807
29808
29809
29810
29811
29812
29813
29814
29815
29816
29817
.....
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908
29909
29910
29911








29912
29913
29914
29915
29916
29917
29918
29919
29920
29921
29922
29923
29924
29925
29926
29927
.....
29932
29933
29934
29935
29936
29937
29938
29939
29940
29941
29942
29943
29944
29945
29946
.....
43473
43474
43475
43476
43477
43478
43479
43480
43481
43482
43483
43484
43485
43486
43487
.....
48957
48958
48959
48960
48961
48962
48963
48964
48965











48966
48967
48968
48969
48970
48971
48972
procedure AppendBuffersToRawUTF8(var Text: RawUTF8; const Buffers: array of PUTF8Char);

/// fast add some characters from a RawUTF8 string into a given buffer
// - warning: the Buffer should contain enough space to store the Text, otherwise
// you may encounter buffer overflows and random memory errors
function AppendRawUTF8ToBuffer(Buffer: PUTF8Char; const Text: RawUTF8): PUTF8Char;


/// use our fast version of StrComp(), to be used with PUTF8Char/PAnsiChar
function StrComp(Str1, Str2: pointer): PtrInt;
  {$ifdef PUREPASCAL} {$ifdef HASINLINE}inline;{$endif} {$endif}














/// use our fast version of StrIComp(), to be used with PUTF8Char/PAnsiChar
function StrIComp(Str1, Str2: pointer): PtrInt;
  {$ifdef PUREPASCAL} {$ifdef HASINLINE}inline;{$endif} {$endif}

/// slower version of StrLen(), but which will never read over the buffer
// - to be used instead of StrLen() on a memory protected buffer
................................................................................

/// hash one pointer value with the suppplied Hasher() function
// - this version is not the same as HashPtrUInt, since it will always
// use the hasher function
function HashPointer(const Elem; Hasher: THasher): cardinal;


const
  /// helper array to get the comparison function corresponding to a given
  // standard array type
  // - not to be used as such, but e.g. when inlining TDynArray methods
  DYNARRAY_SORTFIRSTFIELD: array[boolean,TDynArrayKind] of TDynArraySortCompare = (
    (nil, SortDynArrayByte, SortDynArrayWord, SortDynArrayInteger,
    SortDynArrayCardinal, SortDynArraySingle,
    SortDynArrayInt64, SortDynArrayDouble,
................................................................................
   cfSSE3, cf_c1, cf_c2, cfMON, cfDS_CPL, cf_c5, cf_c6, cfEIST,
   cfTM2, cfSSSE3, cfCID, cfSSE5, cf_c12, cfCX16, cfxTPR, cf_c15,
   cf_c16, cf_c17, cf_c18, cfSSE41, cfSSE42, cf_c21, cf_c22, cfPOPCNT,
   cf_c24, cfAESNI, cf_c26, cf_c27, cfAVX, cf_c29, cf_c30, cf_c31);

/// compute CRC32C checksum on the supplied buffer using SSE 4.2
// - use Intel Streaming SIMD Extensions 4.2 hardware accelerated instruction
// - SSE 4.2 shall be available on the processor (checked with SupportSSE42)
// - result is not compatible with zlib's crc32() - not the same polynom
// - crc32cfast() is 1.7 GB/s, crc32csse42() is 3.7 GB/s
function crc32csse42(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal;
{$endif CPUINTEL}

/// naive symmetric encryption scheme using a 32 bit key
// - fast, but not very secure
................................................................................
    result := pWord(Str1)^-pWord(Str2)^;
    exit;
  end else
  result := 1 else  // Str2=''
  result := -1 else // Str1=''
  result := 0;      // Str1=Str2
end;

function StrComp(Str1, Str2: pointer): PtrInt;
{$ifdef PUREPASCAL}


begin
  if Str1<>Str2 then
  if Str1<>nil then
  if Str2<>nil then begin
    if PAnsiChar(Str1)^=PAnsiChar(Str2)^ then
      repeat
        if pByte(Str1)^=0 then break;
        inc(PtrUInt(Str1));
        inc(PtrUInt(Str2));
      until pByte(Str1)^<>pByte(Str2)^;
    result := pByte(Str1)^-pByte(Str2)^;
    exit;
  end else
  result := 1 else  // Str2=''
  result := -1 else // Str1=''
  result := 0;      // Str1=Str2
end;

{$else}


asm // no branch taken in case of not equal first char
        cmp   eax,edx
        je    @zero  // same string or both nil
        test  eax,edx
        jz    @maynil
@1:     mov   cl,[eax]
        mov   ch,[edx]
................................................................................
        jnz   @1
        or    eax,-1
        ret
@max:   inc   eax
        ret
@zero:  xor   eax,eax
end;

















{$endif}













































































function IdemPropNameU(const P1,P2: RawUTF8): boolean;
{$ifdef PUREPASCAL}
var i,j,L: integer;
begin
  result := false;
  L := length(P1);
................................................................................
@@1: mov eax,1;   ret
@@2: mov eax,2;   ret
@@3: mov eax,3
end;

{$ifndef DELPHI5OROLDER} // need SSE2 asm instruction set

function SupportsSSE2: boolean;
begin
  result := false;
  asm
    pushfd
    pop eax
    mov edx,eax
    xor eax,$200000
    push eax
    popfd
    pushfd
    pop eax
    xor eax,edx
    jz @nocpuidopcode
    push ebx
    mov eax,1
    cpuid
    test edx,$04000000
    jz @nosse2
    mov result,true
@nosse2:
    pop ebx
@nocpuidopcode:
  end;
end;

procedure FillCharSSE2;
asm // Dest=eax Count=edx Value=cl
  cmp       edx, 32
  mov       ch,cl                {copy value into both bytes of cx}
  jl        @@small
  sub       edx,16
  movd      xmm0,ecx
................................................................................
        pop      ecx                 // restore start address
        sub      eax,ecx             // subtract start address
        add      eax,edx             // add byte index
@null:
end;

function StrLenSSE42(S: pointer): PtrInt;
const EQUAL_EACH = 8;
asm // see http://www.felixcloutier.com/x86/PCMPISTRI.html
        or        eax,eax
        mov       edx,eax             // copy pointer
        jz        @null               // returns 0 if S=nil
        mov       eax,-16
        pxor      xmm0,xmm0








@loop:  add       eax,16
        {$ifdef HASAESNI}
        PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH  // comparison result in ecx
        {$else}
        db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH
        {$endif}
        jnz       @loop
        add       eax,ecx
@null:
end;

{$endif DELPHI5OROLDER}

{$endif CPU64}

procedure InitRedirectCode;
................................................................................
  MoveFast := @MoveX87;
  {$else}
  {$ifdef CPU64}
  StrLen := @StrLenSSE2;
  FillcharFast := @FillCharSSE2;
  MoveFast := @MoveSSE2;
  {$else}
  if SupportsSSE2 then begin
    if cfSSE42 in CpuFeatures then
      StrLen := @StrLenSSE42 else
      StrLen := @StrLenSSE2;
    FillcharFast := @FillCharSSE2;
  end else begin
    StrLen := @StrLenX86;
    FillcharFast := @FillCharX87;
................................................................................
begin
  if RawByteString(A)=RawByteString(B) then // faster than StrCmp
    result := 0 else
    result := 1; // fake comparison, but fHash only use equality
end;
{$endif}

const
  DYNARRAY_SORTFIRSTFIELDHASHONLY: array[boolean] of TDynArraySortCompare = (
    SortDynArrayAnsiStringI,
    {$ifdef PUREPASCAL}SortDynArrayAnsiStringHashOnly
    {$else}SortDynArrayAnsiString{$endif});

constructor TRawUTF8ListHashed.Create(aOwnObjects: boolean);
begin
................................................................................
    crc := crc32ctab[0,i];
    for n := 1 to high(crc32ctab) do begin
      crc := (crc shr 8) xor crc32ctab[0,ToByte(crc)];
      crc32ctab[n,i] := crc;
    end;
  end;
  {$ifdef CPUINTEL}
  if cfSSE42 in CpuFeatures then
    crc32c := @crc32csse42 else











  {$endif CPUINTEL}
    crc32c := @crc32cfast;
  DefaultHasher := crc32c;
end;


initialization







>
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 








<

>
>




|

|
|
|
|
|






>

>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
<



|

>
>
>
>
>
>
>
>







|
<







 







|







 







|







 







|
|
>
>
>
>
>
>
>
>
>
>
>







2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
....
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
....
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
.....
18455
18456
18457
18458
18459
18460
18461
18462

18463
18464
18465
18466
18467
18468
18469
18470
18471
18472
18473
18474
18475
18476
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487
18488
18489
18490
18491
18492
18493
.....
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522
18523
18524
18525
18526
18527
18528
18529
18530
18531
18532
18533
18534
18535
18536
18537
18538
18539
18540
18541
18542
18543
18544
18545
18546
18547
18548
18549
18550
18551
18552
18553
18554
18555
18556
18557
18558
18559
18560
18561
18562
18563
18564
18565
18566
18567
18568
18569
18570
18571
18572
18573
18574
18575
18576
18577
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18607
18608
18609
18610
18611
18612
18613
18614
.....
29888
29889
29890
29891
29892
29893
29894


























29895
29896
29897
29898
29899
29900
29901
.....
29982
29983
29984
29985
29986
29987
29988
29989

29990
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002
30003
30004
30005
30006
30007
30008
30009
30010

30011
30012
30013
30014
30015
30016
30017
.....
30022
30023
30024
30025
30026
30027
30028
30029
30030
30031
30032
30033
30034
30035
30036
.....
43563
43564
43565
43566
43567
43568
43569
43570
43571
43572
43573
43574
43575
43576
43577
.....
49047
49048
49049
49050
49051
49052
49053
49054
49055
49056
49057
49058
49059
49060
49061
49062
49063
49064
49065
49066
49067
49068
49069
49070
49071
49072
49073
procedure AppendBuffersToRawUTF8(var Text: RawUTF8; const Buffers: array of PUTF8Char);

/// fast add some characters from a RawUTF8 string into a given buffer
// - warning: the Buffer should contain enough space to store the Text, otherwise
// you may encounter buffer overflows and random memory errors
function AppendRawUTF8ToBuffer(Buffer: PUTF8Char; const Text: RawUTF8): PUTF8Char;

{$ifdef PUREPASCAL}
/// inlined StrComp(), to be used with PUTF8Char/PAnsiChar
function StrComp(Str1, Str2: pointer): PtrInt;
  {$ifdef HASINLINE}inline;{$endif}
{$else}

/// x86 asm version of StrComp(), to be used with PUTF8Char/PAnsiChar
function StrCompFast(Str1, Str2: pointer): PtrInt;

/// SSE 4.2 version of StrComp(), to be used with PUTF8Char/PAnsiChar
function StrCompSSE42(Str1, Str2: pointer): PtrInt;

/// fastest available version of StrComp(), to be used with PUTF8Char/PAnsiChar
// - will use SSE4.2 instructions on supported CPUs
var StrComp: function (Str1, Str2: pointer): PtrInt = StrCompFast;

{$endif}

/// use our fast version of StrIComp(), to be used with PUTF8Char/PAnsiChar
function StrIComp(Str1, Str2: pointer): PtrInt;
  {$ifdef PUREPASCAL} {$ifdef HASINLINE}inline;{$endif} {$endif}

/// slower version of StrLen(), but which will never read over the buffer
// - to be used instead of StrLen() on a memory protected buffer
................................................................................

/// hash one pointer value with the suppplied Hasher() function
// - this version is not the same as HashPtrUInt, since it will always
// use the hasher function
function HashPointer(const Elem; Hasher: THasher): cardinal;


var
  /// helper array to get the comparison function corresponding to a given
  // standard array type
  // - not to be used as such, but e.g. when inlining TDynArray methods
  DYNARRAY_SORTFIRSTFIELD: array[boolean,TDynArrayKind] of TDynArraySortCompare = (
    (nil, SortDynArrayByte, SortDynArrayWord, SortDynArrayInteger,
    SortDynArrayCardinal, SortDynArraySingle,
    SortDynArrayInt64, SortDynArrayDouble,
................................................................................
   cfSSE3, cf_c1, cf_c2, cfMON, cfDS_CPL, cf_c5, cf_c6, cfEIST,
   cfTM2, cfSSSE3, cfCID, cfSSE5, cf_c12, cfCX16, cfxTPR, cf_c15,
   cf_c16, cf_c17, cf_c18, cfSSE41, cfSSE42, cf_c21, cf_c22, cfPOPCNT,
   cf_c24, cfAESNI, cf_c26, cf_c27, cfAVX, cf_c29, cf_c30, cf_c31);

/// compute CRC32C checksum on the supplied buffer using SSE 4.2
// - use Intel Streaming SIMD Extensions 4.2 hardware accelerated instruction
// - SSE 4.2 shall be available on the processor (i.e. cfSSE42 in CpuFeatures)
// - result is not compatible with zlib's crc32() - not the same polynom
// - crc32cfast() is 1.7 GB/s, crc32csse42() is 3.7 GB/s
function crc32csse42(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal;
{$endif CPUINTEL}

/// naive symmetric encryption scheme using a 32 bit key
// - fast, but not very secure
................................................................................
    result := pWord(Str1)^-pWord(Str2)^;
    exit;
  end else
  result := 1 else  // Str2=''
  result := -1 else // Str1=''
  result := 0;      // Str1=Str2
end;


{$ifdef PUREPASCAL}

function StrComp(Str1, Str2: pointer): PtrInt;
begin
  if Str1<>Str2 then
  if Str1<>nil then
  if Str2<>nil then begin
    if PByte(Str1)^=PByte(Str2)^ then
      repeat
        if PByte(Str1)^=0 then break;
        inc(PByte(Str1));
        inc(PByte(Str2));
      until PByte(Str1)^<>PByte(Str2)^;
    result := PByte(Str1)^-PByte(Str2)^;
    exit;
  end else
  result := 1 else  // Str2=''
  result := -1 else // Str1=''
  result := 0;      // Str1=Str2
end;

{$else}

function StrCompFast(Str1, Str2: pointer): PtrInt;
asm // no branch taken in case of not equal first char
        cmp   eax,edx
        je    @zero  // same string or both nil
        test  eax,edx
        jz    @maynil
@1:     mov   cl,[eax]
        mov   ch,[edx]
................................................................................
        jnz   @1
        or    eax,-1
        ret
@max:   inc   eax
        ret
@zero:  xor   eax,eax
end;

const  // see http://www.felixcloutier.com/x86/PCMPISTRI.html
  EQUAL_EACH = 8;
  NEGATIVE_POLARITY = 16;

function StrCompSSE42(Str1, Str2: pointer): PtrInt;
asm 
      test      eax,edx
      jz        @n
@ok:  sub       eax,edx
      jz        @0
      {$ifdef HASAESNI}
      MovDqU    xmm0,dqword [edx]
      PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH+NEGATIVE_POLARITY // result in ecx
      {$else}
      db $F3,$0F,$6F,$02
      db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH+NEGATIVE_POLARITY
      {$endif}
      ja        @1
      jc        @2
      xor       eax,eax
      ret
@1:   add       edx,16
      {$ifdef HASAESNI}
      MovDqU    xmm0,dqword [edx]
      PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH+NEGATIVE_POLARITY // result in ecx
      {$else}
      db $F3,$0F,$6F,$02
      db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH+NEGATIVE_POLARITY
      {$endif}
      ja        @1
      jc        @2
@0:   xor       eax,eax // Str1=Str2
      ret
@n:   test      eax,eax  // Str1='' ?
      jz        @max
      test      edx,edx  // Str2='' ?
      jnz       @ok
      or        eax,-1
      ret
@max: inc       eax
      ret
@2:   add       eax,edx
      movzx     eax,byte ptr [eax+ecx]
      movzx     edx,byte ptr [edx+ecx]
      sub       eax,edx
end;

function SortDynArrayAnsiStringSSE42(const A,B): integer;
asm
      mov       eax,[eax]
      mov       edx,[edx]
      test      eax,edx
      jz        @n
@ok:  sub       eax,edx
      jz        @0
      {$ifdef HASAESNI}
      MovDqU    xmm0,dqword [edx]
      PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH+NEGATIVE_POLARITY // result in ecx
      {$else}
      db $F3,$0F,$6F,$02
      db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH+NEGATIVE_POLARITY
      {$endif}
      ja        @1
      jc        @2
      xor       eax,eax
      ret
@1:   add       edx,16
      {$ifdef HASAESNI}
      MovDqU    xmm0,dqword [edx]
      PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH+NEGATIVE_POLARITY // result in ecx
      {$else}
      db $F3,$0F,$6F,$02
      db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH+NEGATIVE_POLARITY
      {$endif}
      ja        @1
      jc        @2
@0:   xor       eax,eax // Str1=Str2
      ret
@n:   test      eax,eax  // Str1='' ?
      jz        @max
      test      edx,edx  // Str2='' ?
      jnz       @ok
      or        eax,-1
      ret
@max: inc       eax
      ret
@2:   add       eax,edx
      movzx     eax,byte ptr [eax+ecx]
      movzx     edx,byte ptr [edx+ecx]
      sub       eax,edx
end;

{$endif PUREPASCAL}

function IdemPropNameU(const P1,P2: RawUTF8): boolean;
{$ifdef PUREPASCAL}
var i,j,L: integer;
begin
  result := false;
  L := length(P1);
................................................................................
@@1: mov eax,1;   ret
@@2: mov eax,2;   ret
@@3: mov eax,3
end;

{$ifndef DELPHI5OROLDER} // need SSE2 asm instruction set



























procedure FillCharSSE2;
asm // Dest=eax Count=edx Value=cl
  cmp       edx, 32
  mov       ch,cl                {copy value into both bytes of cx}
  jl        @@small
  sub       edx,16
  movd      xmm0,ecx
................................................................................
        pop      ecx                 // restore start address
        sub      eax,ecx             // subtract start address
        add      eax,edx             // add byte index
@null:
end;

function StrLenSSE42(S: pointer): PtrInt;
asm 

        or        eax,eax
        mov       edx,eax             // copy pointer
        jz        @null               // returns 0 if S=nil
        xor       eax,eax
        pxor      xmm0,xmm0
        {$ifdef HASAESNI}
        PcmpIstrI xmm0,dqword [edx],EQUAL_EACH  // comparison result in ecx
        {$else}
        db $66,$0F,$3A,$63,$02,EQUAL_EACH
        {$endif}
        jnz       @loop
        mov       eax,ecx
@null:  ret
@loop:  add       eax,16
        {$ifdef HASAESNI}
        PcmpIstrI xmm0,dqword [edx+eax],EQUAL_EACH  // comparison result in ecx
        {$else}
        db $66,$0F,$3A,$63,$04,$10,EQUAL_EACH
        {$endif}
        jnz       @loop
@ok:    add       eax,ecx

end;

{$endif DELPHI5OROLDER}

{$endif CPU64}

procedure InitRedirectCode;
................................................................................
  MoveFast := @MoveX87;
  {$else}
  {$ifdef CPU64}
  StrLen := @StrLenSSE2;
  FillcharFast := @FillCharSSE2;
  MoveFast := @MoveSSE2;
  {$else}
  if cfSSE2 in CpuFeatures then begin
    if cfSSE42 in CpuFeatures then
      StrLen := @StrLenSSE42 else
      StrLen := @StrLenSSE2;
    FillcharFast := @FillCharSSE2;
  end else begin
    StrLen := @StrLenX86;
    FillcharFast := @FillCharX87;
................................................................................
begin
  if RawByteString(A)=RawByteString(B) then // faster than StrCmp
    result := 0 else
    result := 1; // fake comparison, but fHash only use equality
end;
{$endif}

var
  DYNARRAY_SORTFIRSTFIELDHASHONLY: array[boolean] of TDynArraySortCompare = (
    SortDynArrayAnsiStringI,
    {$ifdef PUREPASCAL}SortDynArrayAnsiStringHashOnly
    {$else}SortDynArrayAnsiString{$endif});

constructor TRawUTF8ListHashed.Create(aOwnObjects: boolean);
begin
................................................................................
    crc := crc32ctab[0,i];
    for n := 1 to high(crc32ctab) do begin
      crc := (crc shr 8) xor crc32ctab[0,ToByte(crc)];
      crc32ctab[n,i] := crc;
    end;
  end;
  {$ifdef CPUINTEL}
  if cfSSE42 in CpuFeatures then begin
    crc32c := @crc32csse42;
    {$ifndef PUREPASCAL}
    StrComp := @StrCompSSE42;
    DYNARRAY_SORTFIRSTFIELD[false,djRawUTF8] := @SortDynArrayAnsiStringSSE42;
    DYNARRAY_SORTFIRSTFIELD[false,djWinAnsi] := @SortDynArrayAnsiStringSSE42;
    DYNARRAY_SORTFIRSTFIELD[false,djRawByteString] := @SortDynArrayAnsiStringSSE42;
    {$ifndef UNICODE}
    DYNARRAY_SORTFIRSTFIELD[false,djString] := @SortDynArrayAnsiStringSSE42;
    {$endif}
    DYNARRAY_SORTFIRSTFIELDHASHONLY[true] := @SortDynArrayAnsiStringSSE42;
    {$endif}
  end else
  {$endif CPUINTEL}
    crc32c := @crc32cfast;
  DefaultHasher := crc32c;
end;


initialization

Changes to SynopseCommit.inc.

1
'1.18.1583'
|
1
'1.18.1584'