Forráskód Böngészése

* Optimized pooling of floating point and large set constants using hash tables.

git-svn-id: trunk@17769 -
sergei 14 éve
szülő
commit
1470d91ba1
2 módosított fájl, 40 hozzáadás és 94 törlés
  1. 5 3
      compiler/aasmdata.pas
  2. 35 91
      compiler/ncgcon.pas

+ 5 - 3
compiler/aasmdata.pas

@@ -71,8 +71,8 @@ interface
         al_end
         al_end
       );
       );
 
 
-      { Type of constant 'pools'. Currently contains only string types,
-        but may be extended with reals, sets, etc. }
+      { Type of constant 'pools'. Mostly for string types, but usable for
+        floating point and large set constants, too. }
       
       
       TConstPoolType = (
       TConstPoolType = (
          sp_invalid,
          sp_invalid,
@@ -87,7 +87,9 @@ interface
          sp_objcclassnames,
          sp_objcclassnames,
          sp_objcvarnames,
          sp_objcvarnames,
          sp_objcvartypes,
          sp_objcvartypes,
-         sp_objcprotocolrefs
+         sp_objcprotocolrefs,
+         sp_varsets,
+         sp_floats
       );
       );
       
       
     const
     const

+ 35 - 91
compiler/ncgcon.pas

@@ -109,10 +109,22 @@ implementation
       const
       const
         floattype2ait:array[tfloattype] of taitype=
         floattype2ait:array[tfloattype] of taitype=
           (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
           (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+
+      { Since the value is stored always as bestreal, we share a single pool
+        between all float types. This requires type and hiloswapped flag to
+        be matched along with the value }
+      type
+        tfloatkey = record
+          value: bestreal;
+          aitype: taitype;
+          swapped: boolean;
+        end;
+
       var
       var
-         hp1 : tai;
          lastlabel : tasmlabel;
          lastlabel : tasmlabel;
          realait : taitype;
          realait : taitype;
+         entry : PHashSetItem;
+         key: tfloatkey;
 {$ifdef ARM}
 {$ifdef ARM}
          hiloswapped : boolean;
          hiloswapped : boolean;
 {$endif ARM}
 {$endif ARM}
@@ -127,44 +139,25 @@ implementation
         { const already used ? }
         { const already used ? }
         if not assigned(lab_real) then
         if not assigned(lab_real) then
           begin
           begin
-             { tries to find an old entry }
-             hp1:=tai(current_asmdata.asmlists[al_typedconsts].first);
-             while assigned(hp1) do
-               begin
-                  if hp1.typ=ait_label then
-                    lastlabel:=tai_label(hp1).labsym
-                  else
-                    begin
-                       if (hp1.typ=realait) and (lastlabel<>nil) then
-                         begin
-                            if is_number_float(value_real) and
-                              (
-                               ((realait=ait_real_32bit) and (tai_real_32bit(hp1).value=value_real) and is_number_float(tai_real_32bit(hp1).value) and (get_real_sign(value_real) = get_real_sign(tai_real_32bit(hp1).value))) or
-                               ((realait=ait_real_64bit) and
+            if current_asmdata.ConstPools[sp_floats] = nil then
+              current_asmdata.ConstPools[sp_floats] := THashSet.Create(64, True, False);
+
+            { there may be gap between record fields, zero it out }
+            fillchar(key,sizeof(key),0);
+            key.value:=value_real;
+            key.aitype:=realait;
 {$ifdef ARM}
 {$ifdef ARM}
-                                 ((tai_real_64bit(hp1).formatoptions=fo_hiloswapped)=hiloswapped) and
+            key.swapped:=hiloswapped;
 {$endif ARM}
 {$endif ARM}
-                                 (tai_real_64bit(hp1).value=value_real) and is_number_float(tai_real_64bit(hp1).value) and (get_real_sign(value_real) = get_real_sign(tai_real_64bit(hp1).value))) or
-                               ((realait=ait_real_80bit) and (tai_real_80bit(hp1).value=value_real) and (tai_real_80bit(hp1).savesize=resultdef.size) and is_number_float(tai_real_80bit(hp1).value) and (get_real_sign(value_real) = get_real_sign(tai_real_80bit(hp1).value))) or
-{$ifdef cpufloat128}
-                               ((realait=ait_real_128bit) and (tai_real_128bit(hp1).value=value_real) and is_number_float(tai_real_128bit(hp1).value) and (get_real_sign(value_real) = get_real_sign(tai_real_128bit(hp1).value))) or
-{$endif cpufloat128}
-                               ((realait=ait_comp_64bit) and (tai_comp_64bit(hp1).value=value_real) and is_number_float(tai_comp_64bit(hp1).value) and (get_real_sign(value_real) = get_real_sign(tai_comp_64bit(hp1).value)))
-                              ) then
-                              begin
-                                { found! }
-                                lab_real:=lastlabel;
-                                break;
-                              end;
-                         end;
-                       lastlabel:=nil;
-                    end;
-                  hp1:=tai(hp1.next);
-               end;
+            entry := current_asmdata.ConstPools[sp_floats].FindOrAdd(@key, sizeof(key));
+
+            lab_real := TAsmLabel(entry^.Data);  // is it needed anymore?
+
              { :-(, we must generate a new entry }
              { :-(, we must generate a new entry }
              if not assigned(lab_real) then
              if not assigned(lab_real) then
                begin
                begin
                   current_asmdata.getdatalabel(lastlabel);
                   current_asmdata.getdatalabel(lastlabel);
+                  entry^.Data:=lastlabel;
                   lab_real:=lastlabel;
                   lab_real:=lastlabel;
                   maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
                   maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
                   new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(resultdef.alignment));
                   new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(resultdef.alignment));
@@ -412,76 +405,27 @@ implementation
 
 
         procedure varsetconst;
         procedure varsetconst;
         var
         var
-           hp1         : tai;
            lastlabel   : tasmlabel;
            lastlabel   : tasmlabel;
            i           : longint;
            i           : longint;
-           neededtyp   : taiconst_type;
+           entry       : PHashSetItem;
         begin
         begin
           location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(8));
           location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(8));
-          neededtyp:=aitconst_8bit;
           lastlabel:=nil;
           lastlabel:=nil;
           { const already used ? }
           { const already used ? }
           if not assigned(lab_set) then
           if not assigned(lab_set) then
             begin
             begin
-              { tries to found an old entry }
-              hp1:=tai(current_asmdata.asmlists[al_typedconsts].first);
-              while assigned(hp1) do
-                begin
-                   if hp1.typ=ait_label then
-                     lastlabel:=tai_label(hp1).labsym
-                   else
-                     begin
-                       if (lastlabel<>nil) and
-                         (hp1.typ=ait_const) and
-                         (tai_const(hp1).consttype=neededtyp) then
-                         begin
-                           if (tai_const(hp1).consttype=aitconst_8bit) then
-                            begin
-                              { compare normal set }
-                              i:=0;
-                              while assigned(hp1) and (i<32) do
-                               begin
-                                 if (source_info.endian=target_info.endian) then
-                                   begin
-                                     if tai_const(hp1).value<>Psetbytes(value_set)^[i ] then
-                                       break
-                                   end
-                                 else if tai_const(hp1).value<>reverse_byte(Psetbytes(value_set)^[i]) then
-                                   break;
-                                 inc(i);
-                                 hp1:=tai(hp1.next);
-                               end;
-                              if i=32 then
-                               begin
-                                 { found! }
-                                 lab_set:=lastlabel;
-                                 break;
-                               end;
-                              { leave when the end of consts is reached, so no
-                                hp1.next is done }
-                              if not assigned(hp1) then
-                               break;
-                            end
-                           else
-                            begin
-                              { compare small set }
-                              if paint(value_set)^=tai_const(hp1).value then
-                               begin
-                                 { found! }
-                                 lab_set:=lastlabel;
-                                 break;
-                               end;
-                            end;
-                         end;
-                       lastlabel:=nil;
-                     end;
-                   hp1:=tai(hp1.next);
-                 end;
+              if current_asmdata.ConstPools[sp_varsets] = nil then
+                current_asmdata.ConstPools[sp_varsets] := THashSet.Create(64, True, False);
+              entry := current_asmdata.ConstPools[sp_varsets].FindOrAdd(value_set, 32);
+
+              lab_set := TAsmLabel(entry^.Data);  // is it needed anymore?
+
                { :-(, we must generate a new entry }
                { :-(, we must generate a new entry }
-               if not assigned(lab_set) then
+               if not assigned(entry^.Data) then
                  begin
                  begin
                    current_asmdata.getdatalabel(lastlabel);
                    current_asmdata.getdatalabel(lastlabel);
                    lab_set:=lastlabel;
                    lab_set:=lastlabel;
+                   entry^.Data:=lastlabel;
                    maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
                    maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
                    new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(8));
                    new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(8));
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));