Browse Source

+ Patch by Thorsten Engler to optimize string comparisons for = and <> cases. (Mantis #8231)

git-svn-id: trunk@6241 -
daniel 18 years ago
parent
commit
e8050233af
7 changed files with 84 additions and 3 deletions
  1. 7 2
      compiler/nadd.pas
  2. 7 0
      rtl/i386/i386.inc
  3. 23 0
      rtl/inc/astrings.inc
  4. 3 0
      rtl/inc/compproc.inc
  5. 22 0
      rtl/inc/generic.inc
  6. 18 0
      rtl/inc/wstrings.inc
  7. 4 1
      rtl/unix/mouse.pp

+ 7 - 2
compiler/nadd.pas

@@ -1587,6 +1587,7 @@ implementation
         p: tnode;
         p: tnode;
         newstatement : tstatementnode;
         newstatement : tstatementnode;
         tempnode,tempnode2 : ttempcreatenode;
         tempnode,tempnode2 : ttempcreatenode;
+        cmpfuncname: string;
       begin
       begin
         { when we get here, we are sure that both the left and the right }
         { when we get here, we are sure that both the left and the right }
         { node are both strings of the same stringtype (JM)              }
         { node are both strings of the same stringtype (JM)              }
@@ -1714,8 +1715,12 @@ implementation
                   exit;
                   exit;
                 end;
                 end;
               { no string constant -> call compare routine }
               { no string constant -> call compare routine }
-              result := ccallnode.createintern('fpc_'+
-                tstringdef(left.resultdef).stringtypname+'_compare',
+              cmpfuncname := 'fpc_'+tstringdef(left.resultdef).stringtypname+'_compare';
+              { for equality checks use optimized version }
+              if nodetype in [equaln,unequaln] then
+                cmpfuncname := cmpfuncname + '_equal';
+
+              result := ccallnode.createintern(cmpfuncname,
                 ccallparanode.create(right,ccallparanode.create(left,nil)));
                 ccallparanode.create(right,ccallparanode.create(left,nil)));
               { and compare its result with 0 according to the original operator }
               { and compare its result with 0 according to the original operator }
               result := caddnode.create(nodetype,result,
               result := caddnode.create(nodetype,result,

+ 7 - 0
rtl/i386/i386.inc

@@ -936,6 +936,13 @@ asm
         movl    saveebx,%ebx
         movl    saveebx,%ebx
 end;
 end;
 
 
+function fpc_shortstr_compare_equal(const left,right:shortstring): longint; [public,alias:'FPC_SHORTSTR_COMPARE_EQUAL']; compilerproc;
+begin
+  Result := longint(left[0]) - longint(right[0]);
+  if Result = 0 then
+    Result := CompareByte(left[1],right[1], longint(left[0]));
+end;
+
 {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
 {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
 
 
 
 

+ 23 - 0
rtl/inc/astrings.inc

@@ -457,6 +457,29 @@ begin
     result:=Length(S1)-Length(S2);
     result:=Length(S1)-Length(S2);
 end;
 end;
 
 
+Function fpc_AnsiStr_Compare_equal(const S1,S2 : AnsiString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE_EQUAL'];  compilerproc;
+{
+  Compares 2 AnsiStrings for equality/inequality only;
+  The result is
+   0 if S1=S2
+   <>0 if S1<>S2
+}
+Var
+  MaxI,Temp : SizeInt;
+begin
+  if pointer(S1)=pointer(S2) then
+    begin
+      result:=0;
+      exit;
+    end;
+  Maxi:=Length(S1);
+  temp:=Length(S2);
+  Result := Maxi - temp;
+  if Result = 0 then
+    if MaxI>0 then
+      result:=CompareByte(S1[1],S2[1],MaxI);
+end;
+
 
 
 Procedure fpc_AnsiStr_CheckZero(p : pointer);[Public,Alias : 'FPC_ANSISTR_CHECKZERO'];  compilerproc;
 Procedure fpc_AnsiStr_CheckZero(p : pointer);[Public,Alias : 'FPC_ANSISTR_CHECKZERO'];  compilerproc;
 begin
 begin

+ 3 - 0
rtl/inc/compproc.inc

@@ -47,6 +47,7 @@ procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of ps
 {$endif STR_CONCAT_PROCS}
 {$endif STR_CONCAT_PROCS}
 procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring); compilerproc;
 procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring); compilerproc;
 function fpc_shortstr_compare(const left,right:shortstring) : longint; compilerproc;
 function fpc_shortstr_compare(const left,right:shortstring) : longint; compilerproc;
+function fpc_shortstr_compare_equal(const left,right:shortstring) : longint; compilerproc;
 
 
 function fpc_pchar_to_shortstr(p:pchar):shortstring; compilerproc;
 function fpc_pchar_to_shortstr(p:pchar):shortstring; compilerproc;
 function fpc_pchar_length(p:pchar):longint; compilerproc;
 function fpc_pchar_length(p:pchar):longint; compilerproc;
@@ -171,6 +172,7 @@ Function fpc_PChar_To_AnsiStr(const p : pchar): ansistring; compilerproc;
 Function fpc_CharArray_To_AnsiStr(const arr: array of char; zerobased: boolean = true): ansistring; compilerproc;
 Function fpc_CharArray_To_AnsiStr(const arr: array of char; zerobased: boolean = true): ansistring; compilerproc;
 function fpc_ansistr_to_chararray(arraysize: SizeInt; const src: ansistring): fpc_big_chararray; compilerproc;
 function fpc_ansistr_to_chararray(arraysize: SizeInt; const src: ansistring): fpc_big_chararray; compilerproc;
 Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt; compilerproc;
 Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt; compilerproc;
+Function fpc_AnsiStr_Compare_equal(const S1,S2 : AnsiString): SizeInt; compilerproc;
 Procedure fpc_AnsiStr_CheckZero(p : pointer); compilerproc;
 Procedure fpc_AnsiStr_CheckZero(p : pointer); compilerproc;
 Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt); compilerproc;
 Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt); compilerproc;
 Procedure fpc_AnsiStr_SetLength (Var S : AnsiString; l : SizeInt); compilerproc;
 Procedure fpc_AnsiStr_SetLength (Var S : AnsiString; l : SizeInt); compilerproc;
@@ -210,6 +212,7 @@ Function fpc_ansistr_to_widechararray(arraysize: SizeInt; const src: AnsiString)
 Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
 Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
 Function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray; compilerproc;
 Function fpc_widestr_to_widechararray(arraysize: SizeInt; const src: WideString): fpc_big_widechararray; compilerproc;
 Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt; compilerproc;
 Function fpc_WideStr_Compare(const S1,S2 : WideString): SizeInt; compilerproc;
+Function fpc_WideStr_Compare_equal(const S1,S2 : WideString): SizeInt; compilerproc;
 Procedure fpc_WideStr_CheckZero(p : pointer); compilerproc;
 Procedure fpc_WideStr_CheckZero(p : pointer); compilerproc;
 Procedure fpc_WideStr_CheckRange(len,index : SizeInt); compilerproc;
 Procedure fpc_WideStr_CheckRange(len,index : SizeInt); compilerproc;
 Procedure fpc_WideStr_SetLength (Var S : WideString; l : SizeInt); compilerproc;
 Procedure fpc_WideStr_SetLength (Var S : WideString; l : SizeInt); compilerproc;

+ 22 - 0
rtl/inc/generic.inc

@@ -694,6 +694,28 @@ begin
     exit(0);
     exit(0);
 end;
 end;
 
 
+function fpc_shortstr_compare_equal(const left,right:shortstring) : longint;[public,alias:'FPC_SHORTSTR_COMPARE_EQUAL']; compilerproc;
+var
+   s1,s2,i : byte;
+   d : longint;
+begin
+  s1:=length(left);
+  s2:=length(right);
+  if s1<>s2 then
+    exit(-1)
+  else
+    for i:=1 to s1 do
+      begin
+       d:=byte(left[i])-byte(right[i]);
+       if d>0 then
+         exit(1)
+       else if d<0 then
+         exit(-1);
+      end;
+  exit(0);
+end;
+
+
 {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
 {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
 
 
 {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
 {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}

+ 18 - 0
rtl/inc/wstrings.inc

@@ -754,6 +754,24 @@ begin
   fpc_WideStr_Compare:=Temp;
   fpc_WideStr_Compare:=Temp;
 end;
 end;
 
 
+Function fpc_WideStr_Compare_Equal(const S1,S2 : WideString): SizeInt;[Public,Alias : 'FPC_WIDESTR_COMPARE_EQUAL']; compilerproc;
+{
+  Compares 2 WideStrings for equality only;
+  The result is
+   0 if S1=S2
+   <>0 if S1<>S2
+}
+Var
+  MaxI : SizeInt;
+begin
+  if pointer(S1)=pointer(S2) then
+    exit(0);
+  Maxi:=Length(S1);
+  If MaxI<>Length(S2) then
+    exit(-1)
+  else
+    exit(CompareWord(S1[1],S2[1],MaxI));
+end;
 
 
 Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
 Procedure fpc_WideStr_CheckZero(p : pointer);[Public,Alias : 'FPC_WIDESTR_CHECKZERO']; compilerproc;
 begin
 begin

+ 4 - 1
rtl/unix/mouse.pp

@@ -135,7 +135,10 @@ end;
        Some distributions use a patched libgpm to work around this, but
        Some distributions use a patched libgpm to work around this, but
        to avoid this mess, we detect the xterm mouse ourselves (we need to
        to avoid this mess, we detect the xterm mouse ourselves (we need to
        be able to do this anyway for the NOGPM case), and don't do any libgpm
        be able to do this anyway for the NOGPM case), and don't do any libgpm
-       call at all if an xterm mouse is detected.}
+       call at all if an xterm mouse is detected. Of course, we use the
+       Pascal libgpm translation, doing it here allows us to keep the Pascal
+       one compatible with the external C one.
+       }
 
 
 function detect_xterm_mouse:word;
 function detect_xterm_mouse:word;