Browse Source

+ change always floating point divisions into multiplications if they are a power of two,
this is an exact operation so it is always allowed
* change only divisions by normal numbers into multiplications

git-svn-id: trunk@29085 -

florian 10 năm trước cách đây
mục cha
commit
5c67fcc43f

+ 3 - 0
compiler/aarch64/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = type extended;
    ts80real = type extended;

+ 3 - 0
compiler/alpha/cpuinfo.pas

@@ -41,6 +41,9 @@ Type
    TConstPtrUInt = qword;
    TConstPtrUInt = qword;
 
 
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TExtended80Rec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/arm/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = type extended;
    ts80real = type extended;

+ 3 - 0
compiler/avr/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = type extended;
    ts80real = type extended;

+ 7 - 0
compiler/generic/cpuinfo.pas

@@ -22,6 +22,13 @@ Interface
 
 
 Type
 Type
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+{$ifdef FPC_HAS_TYPE_EXTENDED}
+   bestrealrec = TExtended80Rec;
+{$else}
+   bestrealrec = TDoubleRec;
+{$endif}
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = type extended;
    ts80real = type extended;

+ 15 - 15
compiler/globals.pas

@@ -84,23 +84,23 @@ interface
        treelogfilename = 'tree.log';
        treelogfilename = 'tree.log';
 
 
 {$if defined(CPUARM) and defined(FPUFPA)}
 {$if defined(CPUARM) and defined(FPUFPA)}
-       MathQNaN : tdoublerec = (bytes : (0,0,252,255,0,0,0,0));
-       MathInf : tdoublerec = (bytes : (0,0,240,127,0,0,0,0));
-       MathNegInf : tdoublerec = (bytes : (0,0,240,255,0,0,0,0));
-       MathPi : tdoublerec =  (bytes : (251,33,9,64,24,45,68,84));
+       MathQNaN : tcompdoublerec = (bytes : (0,0,252,255,0,0,0,0));
+       MathInf : tcompdoublerec = (bytes : (0,0,240,127,0,0,0,0));
+       MathNegInf : tcompdoublerec = (bytes : (0,0,240,255,0,0,0,0));
+       MathPi : tcompdoublerec =  (bytes : (251,33,9,64,24,45,68,84));
 {$else}
 {$else}
 {$ifdef FPC_LITTLE_ENDIAN}
 {$ifdef FPC_LITTLE_ENDIAN}
-       MathQNaN : tdoublerec = (bytes : (0,0,0,0,0,0,252,255));
-       MathInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,127));
-       MathNegInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,255));
-       MathPi : tdoublerec = (bytes : (24,45,68,84,251,33,9,64));
-       MathPiExtended : textendedrec = (bytes : (53,194,104,33,162,218,15,201,0,64));
+       MathQNaN : tcompdoublerec = (bytes : (0,0,0,0,0,0,252,255));
+       MathInf : tcompdoublerec = (bytes : (0,0,0,0,0,0,240,127));
+       MathNegInf : tcompdoublerec = (bytes : (0,0,0,0,0,0,240,255));
+       MathPi : tcompdoublerec = (bytes : (24,45,68,84,251,33,9,64));
+       MathPiExtended : tcompextendedrec = (bytes : (53,194,104,33,162,218,15,201,0,64));
 {$else FPC_LITTLE_ENDIAN}
 {$else FPC_LITTLE_ENDIAN}
-       MathQNaN : tdoublerec = (bytes : (255,252,0,0,0,0,0,0));
-       MathInf : tdoublerec = (bytes : (127,240,0,0,0,0,0,0));
-       MathNegInf : tdoublerec = (bytes : (255,240,0,0,0,0,0,0));
-       MathPi : tdoublerec =  (bytes : (64,9,33,251,84,68,45,24));
-       MathPiExtended : textendedrec = (bytes : (64,0,201,15,218,162,33,104,194,53));
+       MathQNaN : tcompdoublerec = (bytes : (255,252,0,0,0,0,0,0));
+       MathInf : tcompdoublerec = (bytes : (127,240,0,0,0,0,0,0));
+       MathNegInf : tcompdoublerec = (bytes : (255,240,0,0,0,0,0,0));
+       MathPi : tcompdoublerec =  (bytes : (64,9,33,251,84,68,45,24));
+       MathPiExtended : tcompextendedrec = (bytes : (64,0,201,15,218,162,33,104,194,53));
 {$endif FPC_LITTLE_ENDIAN}
 {$endif FPC_LITTLE_ENDIAN}
 {$endif}
 {$endif}
 
 
@@ -963,7 +963,7 @@ implementation
           result := -1;
           result := -1;
       end;
       end;
 
 
-    function convertdoublerec(d : tdoublerec) : tdoublerec;{$ifdef USEINLINE}inline;{$endif}
+    function convertdoublerec(d : tcompdoublerec) : tcompdoublerec;{$ifdef USEINLINE}inline;{$endif}
 {$ifdef CPUARM}
 {$ifdef CPUARM}
       var
       var
         i : longint;
         i : longint;

+ 2 - 2
compiler/globtype.pas

@@ -110,12 +110,12 @@ interface
 {$endif i8086}
 {$endif i8086}
 
 
        { Use a variant record to be sure that the array if aligned correctly }
        { Use a variant record to be sure that the array if aligned correctly }
-       tdoublerec=record
+       tcompdoublerec=record
          case byte of
          case byte of
            0 : (bytes:array[0..7] of byte);
            0 : (bytes:array[0..7] of byte);
            1 : (value:double);
            1 : (value:double);
        end;
        end;
-       textendedrec=record
+       tcompextendedrec=record
          case byte of
          case byte of
            0 : (bytes:array[0..9] of byte);
            0 : (bytes:array[0..9] of byte);
            1 : (value:extended);
            1 : (value:extended);

+ 3 - 0
compiler/i386/cpuinfo.pas

@@ -30,6 +30,9 @@ Interface
 
 
 Type
 Type
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TExtended80Rec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/i8086/cpuinfo.pas

@@ -30,6 +30,9 @@ Interface
 
 
 Type
 Type
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TExtended80Rec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/ia64/cpuinfo.pas

@@ -30,6 +30,9 @@ uses
 
 
 Type
 Type
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TExtended80Rec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/jvm/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/m68k/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/mips/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = type double;
    ts80real = type double;

+ 26 - 7
compiler/nadd.pas

@@ -684,23 +684,41 @@ implementation
              result:=t;
              result:=t;
              exit;
              exit;
           end;
           end;
+{$if FPC_FULLVERSION>20700}
+        { bestrealrec is 2.7.1+ only }
+
+        { replace .../const by a multiplication, but only if fastmath is enabled or
+          the division is done by a power of 2, do not mess with special floating point values like Inf etc.
 
 
-        { replace .../const by a multiplication, but only if fastmath is enabled,
           do this after constant folding to avoid unnecessary precision loss if
           do this after constant folding to avoid unnecessary precision loss if
           an slash expresion would be first converted into a multiplication and later
           an slash expresion would be first converted into a multiplication and later
           folded }
           folded }
         if (nodetype=slashn) and
         if (nodetype=slashn) and
           { do not mess with currency types }
           { do not mess with currency types }
           (not(is_currency(right.resultdef))) and
           (not(is_currency(right.resultdef))) and
-          (cs_opt_fastmath in current_settings.optimizerswitches) then
+          (((cs_opt_fastmath in current_settings.optimizerswitches) and (rt=ordconstn)) or
+           ((cs_opt_fastmath in current_settings.optimizerswitches) and (rt=realconstn) and
+            (bestrealrec(trealconstnode(right).value_real).SpecialType in [fsPositive,fsNegative])
+           ) or
+           ((rt=realconstn) and
+            (bestrealrec(trealconstnode(right).value_real).SpecialType in [fsPositive,fsNegative]) and
+            { mantissa returns the mantissa/fraction without the hidden 1, so power of two means only the hidden
+              bit is set => mantissa must be 0 }
+            (bestrealrec(trealconstnode(right).value_real).Mantissa=0)
+           )
+          ) then
           case rt of
           case rt of
             ordconstn:
             ordconstn:
               begin
               begin
-                nodetype:=muln;
-                t:=crealconstnode.create(1/tordconstnode(right).value,resultdef);
-                right.free;
-                right:=t;
-                exit;
+                { the normal code handles div/0 }
+                if (tordconstnode(right).value<>0) then
+                  begin
+                    nodetype:=muln;
+                    t:=crealconstnode.create(1/tordconstnode(right).value,resultdef);
+                    right.free;
+                    right:=t;
+                    exit;
+                  end;
               end;
               end;
             realconstn:
             realconstn:
               begin
               begin
@@ -709,6 +727,7 @@ implementation
                 exit;
                 exit;
               end;
               end;
           end;
           end;
+{$endif FPC_FULLVERSION>20700}
 
 
         { first, we handle widestrings, so we can check later for }
         { first, we handle widestrings, so we can check later for }
         { stringconstn only                                       }
         { stringconstn only                                       }

+ 3 - 0
compiler/powerpc/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 
 Type
 Type
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 3 - 0
compiler/powerpc64/cpuinfo.pas

@@ -21,6 +21,9 @@ uses
 
 
 type
 type
   bestreal = double;
   bestreal = double;
+{$if FPC_FULLVERSION>20700}
+  bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
   ts32real = single;
   ts32real = single;
   ts64real = double;
   ts64real = double;
   ts80real = extended;
   ts80real = extended;

+ 3 - 0
compiler/sparc/cpuinfo.pas

@@ -30,6 +30,9 @@ uses
 
 
 type
 type
   bestreal = double;
   bestreal = double;
+{$if FPC_FULLVERSION>20700}
+  bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
   ts32real = single;
   ts32real = single;
   ts64real = double;
   ts64real = double;
   ts80real = extended;
   ts80real = extended;

+ 3 - 0
compiler/vis/cpuinfo.pas

@@ -34,6 +34,9 @@ Type
    TConstPtrUInt = Longword;
    TConstPtrUInt = Longword;
 
 
    bestreal = double;
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;

+ 7 - 0
compiler/x86_64/cpuinfo.pas

@@ -30,6 +30,13 @@ Interface
 
 
 Type
 Type
    bestreal = extended;
    bestreal = extended;
+{$if FPC_FULLVERSION>20700}
+{$ifdef FPC_HAS_TYPE_EXTENDED}
+   bestrealrec = TExtended80Rec;
+{$else}
+   bestrealrec = TDoubleRec;
+{$endif}
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts32real = single;
    ts64real = double;
    ts64real = double;
    ts80real = extended;
    ts80real = extended;