* patch by Rika: Improve generic CompareByte, resolves #40120

This commit is contained in:
florian 2023-01-19 22:43:59 +01:00
parent 06a7610a35
commit 218da184e6

View File

@ -429,68 +429,48 @@ end;
{$ifndef FPC_SYSTEM_HAS_COMPAREBYTE} {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
var var
aligncount : sizeint; psrc,pdest,pend,pendpart : pbyte;
psrc,pdest,pend : pbyte;
b : ptrint;
begin begin
b:=0;
psrc:=@buf1; psrc:=@buf1;
pdest:=@buf2; pdest:=@buf2;
if (len>4*sizeof(ptruint)-1) pend:=psrc+len;
if (pend<psrc) then
pend:=pbyte(high(ptruint));
if (len>=2*sizeof(ptruint))
{$ifdef FPC_REQUIRES_PROPER_ALIGNMENT} {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1))) and ((PtrUInt(pdest) and (sizeof(PtrUInt)-1))=(PtrUInt(psrc) and (sizeof(PtrUInt)-1)))
{$endif FPC_REQUIRES_PROPER_ALIGNMENT} {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
then then
begin begin
{ Align on native pointer size } { Align "psrc" on native pointer size. }
aligncount:=(sizeof(PtrUInt)-(PtrUInt(pdest) and (sizeof(PtrUInt)-1))) and (sizeof(PtrUInt)-1); PtrUint(pendpart):=PtrUint(psrc+(sizeof(PtrUint)-1)) and PtrUint(not PtrUint(sizeof(PtrUint)-1));
dec(len,aligncount); if psrc<pendpart then
pend:=psrc+aligncount;
while psrc<pend do
begin begin
b:=(ptrint(psrc^)-ptrint(pdest^)); while (psrc<pendpart) and (psrc^=pdest^) do
if b<>0 then
begin begin
if b<0 then inc(pdest);
exit(-1) inc(psrc);
else
exit(1);
end; end;
inc(pdest); if psrc<pendpart then
inc(psrc); exit(sizeint(psrc^)-sizeint(pdest^));
end; end;
{ use sizeuint typecast to force shr optimization } { "pend" is the end of "psrc" and "psrc" is aligned, so aligned "pend" can be obtained this way. }
pptruint(pend):=pptruint(psrc)+(sizeuint(len) div sizeof(ptruint)); PtrUint(pendpart):=PtrUint(pend) and PtrUint(not PtrUint(sizeof(PtrUint)-1));
len:=len and (sizeof(PtrUInt)-1); while (psrc<pendpart) and (pptruint(psrc)^=pptruint(pdest)^) do
while psrc<pend do
begin begin
b:=(pptrint(psrc)^-pptrint(pdest)^);
if b<>0 then
begin
len:=sizeof(ptruint);
break;
end;
inc(pptruint(pdest)); inc(pptruint(pdest));
inc(pptruint(psrc)); inc(pptruint(psrc));
end; end;
if psrc<pendpart then
pend:=psrc+sizeof(ptruint);
end; end;
if (psrc+len >= psrc) then while (psrc<pend) and (psrc^=pdest^) do
pend:=psrc+len
else
pend:=pbyte(high(ptruint)-1);
while psrc<pend do
begin begin
b:=(ptrint(psrc^)-ptrint(pdest^));
if b<>0 then
begin
if b<0 then
exit(-1)
else
exit(1);
end;
inc(pdest); inc(pdest);
inc(psrc); inc(psrc);
end; end;
if psrc<pend then
exit(sizeint(psrc^)-sizeint(pdest^));
result:=0; result:=0;
end; end;
{$endif not FPC_SYSTEM_HAS_COMPAREBYTE} {$endif not FPC_SYSTEM_HAS_COMPAREBYTE}