Răsfoiți Sursa

+ keep (certain) arrays in registers if they are used with constants indices only

git-svn-id: trunk@42239 -
florian 6 ani în urmă
părinte
comite
749c4d4e47
6 a modificat fișierele cu 84 adăugiri și 15 ștergeri
  1. 11 0
      compiler/defutil.pas
  2. 5 1
      compiler/hlcgobj.pas
  3. 56 13
      compiler/ncgmem.pas
  4. 1 0
      compiler/ncnv.pas
  5. 3 1
      compiler/nmem.pas
  6. 8 0
      compiler/symdef.pas

+ 11 - 0
compiler/defutil.pas

@@ -156,6 +156,9 @@ interface
     }
     function is_special_array(p : tdef) : boolean;
 
+    {# Returns true, if p points to a normal array, bitpacked arrays are included }
+    function is_normal_array(p : tdef) : boolean;
+
     {# Returns true if p is a bitpacked array }
     function is_packed_array(p: tdef) : boolean;
 
@@ -752,6 +755,14 @@ implementation
                  );
       end;
 
+    { true, if p points to a normal array, bitpacked arrays are included }
+    function is_normal_array(p : tdef) : boolean;
+      begin
+         result:=(p.typ=arraydef) and
+                 ((tarraydef(p).arrayoptions * [ado_IsVariant,ado_IsArrayOfConst,ado_IsConstructor,ado_IsDynamicArray])=[]) and
+                 not(is_open_array(p));
+      end;
+
     { true if p is an ansi string def }
     function is_ansistring(p : tdef) : boolean;
       begin

+ 5 - 1
compiler/hlcgobj.pas

@@ -823,9 +823,13 @@ implementation
           objectdef,
           procvardef,
           procdef,
-          arraydef,
           formaldef:
             result:=R_ADDRESSREGISTER;
+          arraydef:
+            if tstoreddef(def).is_intregable then
+              result:=R_INTREGISTER
+            else
+              result:=R_ADDRESSREGISTER;
           floatdef:
             if use_vectorfpu(def) then
               result:=R_MMREGISTER

+ 56 - 13
compiler/ncgmem.pas

@@ -855,7 +855,9 @@ implementation
          paraloc2 : tcgpara;
          subsetref : tsubsetreference;
          temp : longint;
+         hreg : tregister;
          indexdef : tdef;
+         i : Integer;
       begin
          paraloc1.init;
          paraloc2.init;
@@ -936,19 +938,29 @@ implementation
            end
          else
            begin
-              { may happen in case of function results }
-              case left.location.loc of
-                LOC_CSUBSETREG,
-                LOC_CREGISTER,
-                LOC_CMMREGISTER,
-                LOC_SUBSETREG,
-                LOC_REGISTER,
-                LOC_MMREGISTER:
-                  hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
-                else
-                  ;
-              end;
-             location_copy(location,left.location);
+             { may happen in case of function results }
+             case left.location.loc of
+               LOC_CREGISTER,
+               LOC_REGISTER:
+                 begin
+                   if not(is_constnode(right)) or (tarraydef(left.resultdef).elementdef.size<>alusinttype.size) then
+                     hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
+                   { we use location here only to get the right offset }
+                   location_reset_ref(location,LOC_REFERENCE,OS_NO,1,[]);
+                 end;
+               LOC_CSUBSETREG,
+               LOC_CMMREGISTER,
+               LOC_SUBSETREG,
+               LOC_MMREGISTER:
+                 begin
+                   hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
+                   location_copy(location,left.location);
+                 end;
+               LOC_INVALID:
+                 Internalerror(2019061101);
+               else
+                 location_copy(location,left.location);
+             end;
            end;
 
          { location must be memory }
@@ -994,6 +1006,37 @@ implementation
                   update_reference_offset(location.reference,extraoffset,bytemulsize);
                   { adjust alignment after this change }
                   location.reference.alignment:=newalignment(location.reference.alignment,extraoffset*bytemulsize);
+
+                  { actually an array in a register? }
+                  if (left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) and
+                    is_normal_array(left.resultdef) then
+                    begin
+{$if defined(cpu64bitalu)}
+                      hreg:=left.location.register;
+{$else defined(cpu64bitalu}}
+                      if target_info.endian=endian_little then
+                        begin
+                          if location.reference.offset>3 then
+                            hreg:=left.location.register64.reghi
+                          else
+                            hreg:=left.location.register64.reglo;
+                        end
+                      else
+                        begin
+                          if location.reference.offset>3 then
+                            hreg:=left.location.register64.reglo
+                          else
+                            hreg:=left.location.register64.reghi;
+                        end;
+{$endif defined(cpu64bitalu)}
+{$if defined(cpu8bitalu) or defined(cpu16bitalu)}
+                      { we support only the case that one element fills at least one register }
+                      for i:=1 to location.reference.offset mod 4 do
+                        hreg:=cg.GetNextReg(hreg);
+{$endif defined(cpu8bitalu) or defined(cpu16bitalu)}
+                      location_reset(location,left.location.loc,def_cgsize(tarraydef(left.resultdef).elementdef));
+                      location.register:=hreg;
+                    end;
                 end
               else
                 begin

+ 1 - 0
compiler/ncnv.pas

@@ -3255,6 +3255,7 @@ implementation
 
       begin
          first_array_to_pointer:=nil;
+         make_not_regable(left,[ra_addr_regable]);
          expectloc:=LOC_REGISTER;
       end;
 

+ 3 - 1
compiler/nmem.pas

@@ -1054,7 +1054,9 @@ implementation
            that has a field of one of these types -> in that case the record
            can't be a regvar either }
          if ((left.resultdef.typ=arraydef) and
-             not is_special_array(left.resultdef)) or
+             not is_special_array(left.resultdef) and
+             { arrays with elements equal to the alu size and with a constant index can be kept in register }
+             not(is_constnode(right) and (tarraydef(left.resultdef).elementdef.size=alusinttype.size))) or
             ((left.resultdef.typ=stringdef) and
              (tstringdef(left.resultdef).stringtype in [st_shortstring,st_longstring])) then
            make_not_regable(left,[ra_addr_regable]);

+ 8 - 0
compiler/symdef.pas

@@ -2225,6 +2225,14 @@ implementation
             is_intregable:=(is_implicit_pointer_object_type(self)) and not needs_inittable;
           setdef:
             is_intregable:=is_smallset(self);
+          arraydef:
+            is_intregable:=not(is_special_array(self)) and
+              (tarraydef(self).size in [1,2,4,8]) and tstoreddef(tarraydef(self).elementdef).is_intregable
+{$ifdef SUPPORT_MMX}
+              and not((cs_mmx in current_settings.localswitches) and
+                 is_mmx_able_array(self))
+{$endif SUPPORT_MMX}
+              ;
           recorddef:
             begin
 {$ifdef llvm}