Browse Source

* sqr(real) and sqrt(real): remove typeconv node inserted by initial call processing (see explanation in comments), allowing these functions to be evaluated using precision of argument. In particular, sqrt(single) and sqrt(double) now emit 'sqrtss' and 'sqrtsd' instructions on x86 targets with -Cfsse3. Non-x86 targets already have the necessary support in code generators.
* abs(real): handle the same way as sqrt and sqr, i.e. without casting to bestreal and back.

git-svn-id: trunk@27808 -

sergei 11 years ago
parent
commit
fc5f45f65c
2 changed files with 28 additions and 2 deletions
  1. 21 2
      compiler/ninl.pas
  2. 7 0
      rtl/i386/math.inc

+ 21 - 2
compiler/ninl.pas

@@ -2469,8 +2469,27 @@ implementation
     function tinlinenode.pass_typecheck:tnode;
 
       procedure setfloatresultdef;
+        var
+          hnode: tnode;
         begin
-          if (left.resultdef.typ=floatdef) and
+          { System unit declares internal functions like this:
+              function foo(x: valreal): valreal; [internproc: number];
+            Calls to such functions are initially processed by callnode,
+            which typechecks the arguments, possibly inserting conversion to valreal.
+            To handle smaller types without excess precision, we need to remove
+            these extra typecasts. }
+          if (left.nodetype=typeconvn) and
+            (ttypeconvnode(left).left.resultdef.typ=floatdef) and
+            (left.flags*[nf_explicit,nf_internal]=[]) and
+            (tfloatdef(ttypeconvnode(left).left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real]) then
+            begin
+              hnode:=ttypeconvnode(left).left;
+              ttypeconvnode(left).left:=nil;
+              left.free;
+              left:=hnode;
+              resultdef:=left.resultdef;
+            end
+          else if (left.resultdef.typ=floatdef) and
             (tfloatdef(left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real]) then
             resultdef:=left.resultdef
           else
@@ -3093,7 +3112,6 @@ implementation
               in_cos_real,
               in_sin_real,
               in_arctan_real,
-              in_abs_real,
               in_ln_real :
                 begin
                   set_varstate(left,vs_read,[vsf_must_be_valid]);
@@ -3137,6 +3155,7 @@ implementation
                   resultdef:=s32inttype;
                 end;
 
+              in_abs_real,
               in_sqr_real,
               in_sqrt_real :
                 begin

+ 7 - 0
rtl/i386/math.inc

@@ -41,6 +41,13 @@
                             FPU Control word
  ****************************************************************************}
 
+{$push}
+{$codealign constmin=16}
+const
+  FPC_ABSMASK_SINGLE: array[0..1] of qword=($7fffffff7fffffff,$7fffffff7fffffff); cvar; public;
+  FPC_ABSMASK_DOUBLE: array[0..1] of qword=($7fffffffffffffff,$7fffffffffffffff); cvar; public;
+{$pop}
+
     procedure Set8087CW(cw:word);
       begin
         { pic-safe ; cw will not be a regvar because it's accessed from }