Explorar o código

+ handle abs(real) internally for LLVM, as the generic code calls a helper
that is not implemented for some architectures

git-svn-id: trunk@31656 -

Jonas Maebe %!s(int64=10) %!d(string=hai) anos
pai
achega
616dbead35
Modificáronse 1 ficheiros con 58 adicións e 1 borrados
  1. 58 1
      compiler/llvm/nllvminl.pas

+ 58 - 1
compiler/llvm/nllvminl.pas

@@ -33,6 +33,7 @@ interface
       tllvminlinenode = class(tcginlinenode)
        protected
         function first_get_frame: tnode; override;
+        function first_abs_real: tnode; override;
        public
         procedure second_length; override;
       end;
@@ -44,7 +45,7 @@ implementation
        verbose,globtype,constexp,
        aasmbase, aasmdata,
        symtype,symdef,defutil,
-       ncal,ncon,ninl,
+       nutils,nadd,nbas,ncal,ncon,nflw,ninl,nld,nmat,
        pass_2,
        cgbase,cgutils,tgobj,hlcgobj,
        cpubase;
@@ -56,6 +57,62 @@ implementation
            ccallparanode.create(genintconstnode(0),nil));
        end;
 
+    { in general, generate regular expression rather than intrinsics: according
+      to the "Performance Tips for Frontend Authors", "The optimizer is quite
+      good at reasoning about general control flow and arithmetic, it is not
+      anywhere near as strong at reasoning about the various intrinsics. If
+      profitable for code generation purposes, the optimizer will likely form
+      the intrinsics itself late in the optimization pipeline." }
+
+    function tllvminlinenode.first_abs_real: tnode;
+      var
+        lefttemp,
+        resulttemp: ttempcreatenode;
+        stat: tstatementnode;
+      begin
+        result:=internalstatements(stat);
+        lefttemp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
+        { assigned twice -> will be spilled if put in register }
+        resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+
+        addstatement(stat,lefttemp);
+        addstatement(stat,resulttemp);
+
+        { lefttemp:=left }
+        addstatement(stat,
+          cassignmentnode.create(ctemprefnode.create(lefttemp),left)
+        );
+
+        { if lefttemp>=0 then
+            resulttemp:=lefttemp
+          else
+            resulttemp:=-lefttemp
+        }
+        addstatement(stat,
+          cifnode.create(
+            caddnode.create(
+              gten,
+              ctemprefnode.create(lefttemp),
+              crealconstnode.create(0.0,left.resultdef)
+            ),
+            cassignmentnode.create(
+              ctemprefnode.create(resulttemp),
+              ctemprefnode.create(lefttemp)
+            ),
+            cassignmentnode.create(
+              ctemprefnode.create(resulttemp),
+              cunaryminusnode.create(ctemprefnode.create(lefttemp))
+            )
+          )
+        );
+        addstatement(stat,ctempdeletenode.create(lefttemp));
+        addstatement(stat,ctempdeletenode.create_normal_temp(resulttemp));
+        { return resulttemp }
+        addstatement(stat,ctemprefnode.create(resulttemp));
+        { reused }
+        left:=nil;
+      end;
+
 
     procedure tllvminlinenode.second_length;
       var