2
0
Эх сурвалжийг харах

+ implement while i>0 do ... dec(i); to if i>0 then repeat ... dec(i) until i=0; as proposed by Rika in mr1122

florian 2 долоо хоног өмнө
parent
commit
9bff60e270
2 өөрчлөгдсөн 64 нэмэгдсэн , 5 устгасан
  1. 41 5
      compiler/nflw.pas
  2. 23 0
      compiler/nutils.pas

+ 41 - 5
compiler/nflw.pas

@@ -88,6 +88,9 @@ interface
 {$ifdef state_tracking}
           function track_state_pass(exec_known:boolean):boolean;override;
 {$endif}
+          function simplify(forinline: boolean): tnode;override;
+
+          function internalsimplify(forinline: boolean): tnode;
        end;
        twhilerepeatnodeclass = class of twhilerepeatnode;
 
@@ -1295,13 +1298,14 @@ implementation
 
     constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
       begin
-          inherited create(whilerepeatn,l,r,nil,nil);
-          if tab then
-              include(loopflags, lnf_testatbegin);
-          if cn then
-              include(loopflags,lnf_checknegate);
+        inherited create(whilerepeatn,l,r,nil,nil);
+        if tab then
+          include(loopflags, lnf_testatbegin);
+        if cn then
+          include(loopflags,lnf_checknegate);
       end;
 
+
     function twhilerepeatnode.pass_typecheck:tnode;
       var
          t:Tunarynode;
@@ -1346,6 +1350,38 @@ implementation
       end;
 
 
+    function twhilerepeatnode.internalsimplify(forinline : boolean) : tnode;
+      var
+        p: tnode;
+      begin
+        result:=nil;
+        { convert while i>0 do ... dec(i); to if i>0 then repeat ... dec(i) until i=0; ? }
+        if (cs_opt_level2 in current_settings.optimizerswitches) and
+          { while loop?}
+          (lnf_testatbegin in loopflags) and not(lnf_checknegate in loopflags) and
+          ((left.nodetype=gtn) and (taddnode(left).left.nodetype=loadn) and is_constintnode(taddnode(left).right) and
+           (tordconstnode(taddnode(left).right).value=0)) then
+          begin
+            p:=GetLastStatement(right);
+            if assigned(p) and (tstatementnode(p).left.nodetype=inlinen) and (tinlinenode(tstatementnode(p).left).inlinenumber=in_dec_x) and
+              taddnode(left).left.isequal(tcallparanode(tinlinenode(tstatementnode(p).left).left).left) and
+              not(assigned(tcallparanode(tinlinenode(tstatementnode(p).left).left).right)) then
+              begin
+                result:=cifnode.create_internal(left.getcopy,getcopy,nil);
+                include(twhilerepeatnode(tifnode(result).right).loopflags,lnf_checknegate);
+                exclude(twhilerepeatnode(tifnode(result).right).loopflags,lnf_testatbegin);
+                twhilerepeatnode(tifnode(result).right).left.nodetype:=equaln;
+              end;
+          end;
+      end;
+
+
+    function twhilerepeatnode.simplify(forinline : boolean) : tnode;
+      begin
+        result:=internalsimplify(false);
+      end;
+
+
 {$ifdef prefetchnext}
     type
       passignmentquery = ^tassignmentquery;

+ 23 - 0
compiler/nutils.pas

@@ -188,6 +188,9 @@ interface
     { checks if p is a single statement, if yes, it is returned in s }
     function IsSingleStatement(p : tnode;var s : tnode) : Boolean;
 
+    { gets the last statement in a sequence of statements/blocks }
+    function GetLastStatement(p : tnode) : tnode;
+
     type
       TMatchProc2 = function(n1,n2 : tnode) : Boolean is nested;
       TTransformProc2 = function(n1,n2 : tnode) : tnode is nested;
@@ -1663,6 +1666,26 @@ implementation
       end;
 
 
+    { gets the last statement in a sequence of statements/blocks }
+    function GetLastStatement(p : tnode) : tnode;
+      var
+        i: Integer;
+      begin
+        Result:=p;
+        while assigned(Result) do
+          begin
+            if (tstatementnode(Result).nodetype=statementn) and assigned(tstatementnode(Result).next) then
+              Result:=tstatementnode(Result).next
+            else if tstatementnode(Result).nodetype=blockn then
+              Result:=tblocknode(Result).statements
+            else if tstatementnode(Result).statement.nodetype=blockn then
+              Result:=tblocknode(tstatementnode(Result).left).statements
+            else
+              exit;
+          end;
+      end;
+
+
     function MatchAndTransformNodesCommutative(n1,n2 : tnode;matchproc : TMatchProc2;transformproc : TTransformProc2;var res : tnode) : Boolean;
       begin
         res:=nil;