浏览代码

* remove implicit typecast to extended automatically inserted for trunc/round
(due to the declaration in the system unit) on x86_64 if this allows us
to use SSE code instead (mantis #28366)

git-svn-id: trunk@31192 -

Jonas Maebe 10 年之前
父节点
当前提交
1bcc276dcf
共有 2 个文件被更改,包括 42 次插入1 次删除
  1. 11 0
      compiler/x86/nx86inl.pas
  2. 31 1
      compiler/x86_64/nx64inl.pas

+ 11 - 0
compiler/x86/nx86inl.pas

@@ -30,6 +30,9 @@ interface
 
     type
        tx86inlinenode = class(tcginlinenode)
+         protected
+          procedure maybe_remove_round_trunc_typeconv; virtual;
+         public
           { first pass override
             so that the code generator will actually generate
             these nodes.
@@ -91,6 +94,12 @@ implementation
                               TX86INLINENODE
 *****************************************************************************}
 
+     procedure tx86inlinenode.maybe_remove_round_trunc_typeconv;
+       begin
+         { only makes a difference for x86_64 }
+       end;
+
+
      function tx86inlinenode.first_pi : tnode;
       begin
         if (tfloatdef(pbestrealtype^).floattype=s80real) then
@@ -202,6 +211,7 @@ implementation
 
      function tx86inlinenode.first_round_real : tnode;
       begin
+        maybe_remove_round_trunc_typeconv;
 {$ifdef x86_64}
         if use_vectorfpu(left.resultdef) then
           expectloc:=LOC_REGISTER
@@ -214,6 +224,7 @@ implementation
 
      function tx86inlinenode.first_trunc_real: tnode;
        begin
+         maybe_remove_round_trunc_typeconv;
          if (cs_opt_size in current_settings.optimizerswitches)
 {$ifdef x86_64}
            and not(use_vectorfpu(left.resultdef))

+ 31 - 1
compiler/x86_64/nx64inl.pas

@@ -30,12 +30,42 @@ interface
 
     type
        tx8664inlinenode = class(tx86inlinenode)
+        protected
+          procedure maybe_remove_round_trunc_typeconv; override;
        end;
 
 implementation
 
   uses
-    ninl;
+    symconst,
+    node,ncnv,ninl;
+
+  procedure tx8664inlinenode.maybe_remove_round_trunc_typeconv;
+    var
+      temp: tnode;
+    begin
+      { the prototype of trunc()/round() in the system unit is declared
+        with valreal as parameter type, so the argument will always be
+        extended -> remove the typeconversion to extended if any; not done
+        in ninl, because there are other code generators that assume that
+        the parameter to trunc has been converted to valreal (e.g. PowerPC).
+
+        We can always remove such typeconversions here if they exist, because
+        on the x87 all floating point types are handled the same, and
+        if we call the inherited version we'll insert a call node, which
+        will insert the necessary type conversion again }
+      if (left.nodetype=typeconvn) and
+         not(nf_explicit in left.flags) and
+         (ttypeconvnode(left).left.resultdef.typ=floatdef) then
+        begin
+          { get rid of the type conversion, so the use_vectorfpu will be
+            applied to the original type }
+          temp:=ttypeconvnode(left).left;
+          ttypeconvnode(left).left:=nil;
+          left.free;
+          left:=temp;
+        end;
+    end;
 
 begin
    cinlinenode:=tx8664inlinenode;