Browse Source

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

florian 2 years ago
parent
commit
218da184e6
1 changed files with 21 additions and 41 deletions
  1. 21 41
      rtl/inc/generic.inc

+ 21 - 41
rtl/inc/generic.inc

@@ -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 : pbyte;
-  b : ptrint;
+  psrc,pdest,pend,pendpart : pbyte;
 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 }
-      aligncount:=(sizeof(PtrUInt)-(PtrUInt(pdest) and (sizeof(PtrUInt)-1))) and (sizeof(PtrUInt)-1);
-      dec(len,aligncount);
-      pend:=psrc+aligncount;
-      while psrc<pend do
+      { Align "psrc" on native pointer size. }
+      PtrUint(pendpart):=PtrUint(psrc+(sizeof(PtrUint)-1)) and PtrUint(not PtrUint(sizeof(PtrUint)-1));
+      if psrc<pendpart then
         begin
         begin
-          b:=(ptrint(psrc^)-ptrint(pdest^));
-          if b<>0 then
+          while (psrc<pendpart) and (psrc^=pdest^) do
             begin
             begin
-              if b<0 then
-                exit(-1)
-              else
-                exit(1);
+              inc(pdest);
+              inc(psrc);
             end;
             end;
-          inc(pdest);
-          inc(psrc);
+          if psrc<pendpart then
+            exit(sizeint(psrc^)-sizeint(pdest^));
         end;
         end;
-      { use sizeuint typecast to force shr optimization }
-      pptruint(pend):=pptruint(psrc)+(sizeuint(len) div sizeof(ptruint));
-      len:=len and (sizeof(PtrUInt)-1);
-      while psrc<pend do
+      { "pend" is the end of "psrc" and "psrc" is aligned, so aligned "pend" can be obtained this way. }
+      PtrUint(pendpart):=PtrUint(pend) and PtrUint(not PtrUint(sizeof(PtrUint)-1));
+      while (psrc<pendpart) and (pptruint(psrc)^=pptruint(pdest)^) 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
-    pend:=psrc+len
-  else
-    pend:=pbyte(high(ptruint)-1);
-  while psrc<pend do
+  while (psrc<pend) and (psrc^=pdest^) 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}