Browse Source

+ special code for string + char, between -dnewoptimizations

Jonas Maebe 25 years ago
parent
commit
490769db7d
2 changed files with 125 additions and 18 deletions
  1. 103 15
      compiler/cg386add.pas
  2. 22 3
      compiler/tcadd.pas

+ 103 - 15
compiler/cg386add.pas

@@ -141,6 +141,11 @@ implementation
 
 
     procedure addstring(var p : ptree);
     procedure addstring(var p : ptree);
       var
       var
+{$ifdef newoptimizations}
+        l: pasmlabel;
+        hreg: tregister;
+        href2: preference;
+{$endif newoptimizations}
         pushedregs : tpushed;
         pushedregs : tpushed;
         href       : treference;
         href       : treference;
         pushed,
         pushed,
@@ -291,30 +296,110 @@ implementation
                              clear_location(p^.left^.location);
                              clear_location(p^.left^.location);
                              p^.left^.location.loc:=LOC_MEM;
                              p^.left^.location.loc:=LOC_MEM;
                              p^.left^.location.reference:=href;
                              p^.left^.location.reference:=href;
+                             
+                             { length of temp string = 255 (JM) }
+                             pstringdef(p^.left^.resulttype)^.len := 255;
                           end;
                           end;
 
 
                         secondpass(p^.right);
                         secondpass(p^.right);
 
 
-                        { on the right we do not need the register anymore too }
+{$ifdef newoptimizations}
+                        { special case for string := string + char (JM) }
+                        hreg := R_NO;
+                        if is_shortstring(p^.left^.resulttype) and
+                           is_char(p^.right^.resulttype) then
+                          begin
+                            getlabel(l);
+                            getexplicitregister32(R_EDI);
+                            { load the current string length }
+                            emit_ref_reg(A_MOVZX,S_BL,
+                              newreference(p^.left^.location.reference),R_EDI);
+                            { is it already maximal? }
+                            emit_const_reg(A_CMP,S_L,
+                              pstringdef(p^.left^.resulttype)^.len,R_EDI);
+                            emitjmp(C_E,l);
+                            { no, so add the new character }
+                            { is it a constant char? }
+                            if (p^.right^.treetype <> ordconstn) then
+                              { no, make sure it is in a register }
+                              if p^.right^.location.loc in [LOC_REFERENCE,LOC_MEM] then
+                                begin
+                                  { free the registers of p^.right } 
+                                  del_reference(p^.right^.location.reference);
+                                  { get register for the char }
+                                  hreg := reg32toreg8(getregister32);
+                                  emit_ref_reg(A_MOV,S_B,
+                                    newreference(p^.right^.location.reference),
+                                    hreg);
+                                 { I don't think a temp char exists, but it won't hurt (JM)Ê}
+                                 ungetiftemp(p^.right^.location.reference);
+                                end
+                              else hreg := p^.right^.location.register;
+                            href2 := newreference(p^.left^.location.reference);
+                            { we need a new reference to store the character }
+                            { at the end of the string. Check if the base or }
+                            { index register is still free                   }
+                            if (p^.left^.location.reference.base <> R_NO) and
+                               (p^.left^.location.reference.index <> R_NO) then
+                              begin
+                                { they're not free, so add the base reg to }
+                                { the string length (since the index can   }
+                                { have a scalefactor) and use EDI as base  }
+                                emit_reg_reg(A_ADD,S_L,
+                                  p^.left^.location.reference.base,R_EDI);
+                                href2^.base := R_EDI;
+                              end
+                            else
+                              { at least one is still free, so put EDI there }
+                              if href2^.base = R_NO then
+                                href2^.base := R_EDI
+                              else
+                                begin
+                                  href2^.index := R_EDI;
+                                  href2^.scalefactor := 1;
+                                end;
+                            { we need to be one position after the last char }
+                            inc(href2^.offset);
+                            { increase the string length }
+                            emit_ref(A_INC,S_B,newreference(p^.left^.location.reference));
+                            { and store the character at the end of the string }
+                            if (p^.right^.treetype <> ordconstn) then
+                              begin
+                                { no new_reference(href2) because it's only }
+                                { used once (JM)                            }
+                                emit_reg_ref(A_MOV,S_B,hreg,href2);
+                                ungetregister(hreg);
+                              end
+                            else
+                              emit_const_ref(A_MOV,S_B,p^.right^.value,href2);
+                            emitlab(l);
+                            ungetregister32(R_EDI);
+                          end
+                        else
+                          begin
+{$endif  newoptimizations}
 {$IfNDef regallocfix}
 {$IfNDef regallocfix}
-                        del_reference(p^.right^.location.reference);
-                        pushusedregisters(pushedregs,$ff);
+                        { on the right we do not need the register anymore too }
+                            del_reference(p^.right^.location.reference);
+                            pushusedregisters(pushedregs,$ff);
 {$Else regallocfix}
 {$Else regallocfix}
-                        pushusedregisters(pushedregs,$ff
-                          xor ($80 shr byte(p^.right^.location.reference.base))
-                          xor ($80 shr byte(p^.right^.location.reference.index)));
+                            pushusedregisters(pushedregs,$ff
+                              xor ($80 shr byte(p^.right^.location.reference.base))
+                              xor ($80 shr byte(p^.right^.location.reference.index)));
 {$EndIf regallocfix}
 {$EndIf regallocfix}
-                        emitpushreferenceaddr(p^.left^.location.reference);
-                        emitpushreferenceaddr(p^.right^.location.reference);
+                            emitpushreferenceaddr(p^.left^.location.reference);
+                            emitpushreferenceaddr(p^.right^.location.reference);
 {$IfDef regallocfix}
 {$IfDef regallocfix}
-                        del_reference(p^.right^.location.reference);
+                            del_reference(p^.right^.location.reference);
 {$EndIf regallocfix}
 {$EndIf regallocfix}
-                        emitcall('FPC_SHORTSTR_CONCAT');
-                        maybe_loadesi;
-                        popusedregisters(pushedregs);
-
+                            emitcall('FPC_SHORTSTR_CONCAT');
+                            maybe_loadesi;
+                            popusedregisters(pushedregs);
+                            ungetiftemp(p^.right^.location.reference);
+{$ifdef newoptimizations}
+                        end;
+{$endif newoptimizations}
                         set_location(p^.location,p^.left^.location);
                         set_location(p^.location,p^.left^.location);
-                        ungetiftemp(p^.right^.location.reference);
                      end;
                      end;
                    ltn,lten,gtn,gten,
                    ltn,lten,gtn,gten,
                    equaln,unequaln :
                    equaln,unequaln :
@@ -2271,7 +2356,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.98  2000-04-10 12:23:19  jonas
+  Revision 1.99  2000-04-21 12:35:05  jonas
+    + special code for string + char, between -dnewoptimizations
+
+  Revision 1.98  2000/04/10 12:23:19  jonas
     * modified copyshortstring so it takes an extra paramter which allows it
     * modified copyshortstring so it takes an extra paramter which allows it
       to delete the sref itself (so the reg deallocations are put in the
       to delete the sref itself (so the reg deallocations are put in the
       right place for the optimizer)
       right place for the optimizer)

+ 22 - 3
compiler/tcadd.pas

@@ -841,8 +841,16 @@ implementation
                 end
                 end
               else
               else
                 begin
                 begin
-                   if not(is_shortstring(rd)) then
-                     p^.right:=gentypeconvnode(p^.right,cshortstringdef);
+                   if not(is_shortstring(rd))
+{$ifdef newoptimizations}
+{$ifdef i386}
+                      { shortstring + char handled seperately  (JM) }
+                      and (not(cs_optimize in aktglobalswitches) or
+                           (p^.treetype <> addn) or not(is_char(rd)))
+{$endif i386}
+{$endif newoptimizations}
+                    then
+                      p^.right:=gentypeconvnode(p^.right,cshortstringdef);
                    if not(is_shortstring(ld)) then
                    if not(is_shortstring(ld)) then
                      p^.left:=gentypeconvnode(p^.left,cshortstringdef);
                      p^.left:=gentypeconvnode(p^.left,cshortstringdef);
                    p^.resulttype:=cshortstringdef;
                    p^.resulttype:=cshortstringdef;
@@ -861,6 +869,14 @@ implementation
                 calcregisters(p,0,0,0)
                 calcregisters(p,0,0,0)
               else
               else
                 calcregisters(p,1,0,0);
                 calcregisters(p,1,0,0);
+{$ifdef newoptimizations}
+{$ifdef i386}
+              { not always necessary, only if it is not a constant char and }
+              { not a regvar, but don't know how to check this here (JM)    }
+              if is_char(rd) then
+                inc(p^.registers32);
+{$endif i386}
+{$endif newoptimizations}
               convdone:=true;
               convdone:=true;
            end
            end
          else
          else
@@ -1285,7 +1301,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.73  2000-03-28 21:14:18  pierre
+  Revision 1.74  2000-04-21 12:35:05  jonas
+    + special code for string + char, between -dnewoptimizations
+
+  Revision 1.73  2000/03/28 21:14:18  pierre
    * fix for bug 891
    * fix for bug 891
 
 
   Revision 1.72  2000/03/20 10:16:51  florian
   Revision 1.72  2000/03/20 10:16:51  florian