diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-06-16 21:29:48 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-06-16 21:29:48 +0000 |
commit | c091377c82543520d8a7024539b995f7a83e598a (patch) | |
tree | 607ab1def06d9193fd09faba54380ab5335a218b | |
parent | 5ec0a0bc1e60fa88ceeac9ec9f345c32939b7a49 (diff) | |
download | fpc-c091377c82543520d8a7024539b995f7a83e598a.tar.gz |
+ keep (certain) arrays in registers if they are used with constants indices only
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@42239 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r-- | compiler/defutil.pas | 11 | ||||
-rw-r--r-- | compiler/hlcgobj.pas | 6 | ||||
-rw-r--r-- | compiler/ncgmem.pas | 69 | ||||
-rw-r--r-- | compiler/ncnv.pas | 1 | ||||
-rw-r--r-- | compiler/nmem.pas | 4 | ||||
-rw-r--r-- | compiler/symdef.pas | 8 |
6 files changed, 84 insertions, 15 deletions
diff --git a/compiler/defutil.pas b/compiler/defutil.pas index 6ac905156b..862ff650ea 100644 --- a/compiler/defutil.pas +++ b/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 diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 627b36c0e4..daef6110fe 100644 --- a/compiler/hlcgobj.pas +++ b/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 diff --git a/compiler/ncgmem.pas b/compiler/ncgmem.pas index a38849f939..a751625835 100644 --- a/compiler/ncgmem.pas +++ b/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 diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index 5fd1e9605e..5f69d3a6e6 100644 --- a/compiler/ncnv.pas +++ b/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; diff --git a/compiler/nmem.pas b/compiler/nmem.pas index ec36ceead6..4eae7da363 100644 --- a/compiler/nmem.pas +++ b/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]); diff --git a/compiler/symdef.pas b/compiler/symdef.pas index 12a28dafd1..b4e54b9c7f 100644 --- a/compiler/symdef.pas +++ b/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} |