瀏覽代碼

* Before r35961 (back in 2017) some simple assignment optimizations, such as "x:=x+y" to "inc(x,y)", were performed when -O2 in tassignmentnode.simplify. In r35961 these optimizations were moved to a separate pass which is enabled only when -O3 by cs_opt_use_load_modify_store. This separate pass can benefit from other optimization. But worse code is generated with -O2 since then.
This commit restores applying of simple assignment optimizations when -O2.

Yuriy Sydorov 4 年之前
父節點
當前提交
07698050e5
共有 2 個文件被更改,包括 82 次插入63 次删除
  1. 9 1
      compiler/nld.pas
  2. 73 62
      compiler/optloadmodifystore.pas

+ 9 - 1
compiler/nld.pas

@@ -197,7 +197,8 @@ implementation
       cpuinfo,
       htypechk,pass_1,procinfo,paramgr,
       nbas,ncon,nflw,ninl,ncnv,nmem,ncal,nutils,
-      cgbase
+      cgbase,
+      optloadmodifystore
       ;
 
 
@@ -625,6 +626,13 @@ implementation
            is_constrealnode(right) and
            not equal_defs(right.resultdef,left.resultdef) then
           inserttypeconv(right,left.resultdef);
+{$if (cs_opt_use_load_modify_store in supported_optimizerswitches)}
+        { Perform simple optimizations when -O2 and the dedicated
+          cs_opt_use_load_modify_store optimization pass is not enabled. }
+        if (cs_opt_level2 in current_settings.optimizerswitches) and
+           not (cs_opt_use_load_modify_store in current_settings.optimizerswitches) then
+          result:=try_opt_assignmentnode(self);
+{$endif}
       end;
 
 

+ 73 - 62
compiler/optloadmodifystore.pas

@@ -38,16 +38,17 @@ unit optloadmodifystore;
   interface
 
     uses
-      node;
+      node,nld;
 
     procedure do_optloadmodifystore(var rootnode : tnode);
+    function try_opt_assignmentnode(assignmentnode : tassignmentnode): tnode;
 
   implementation
 
     uses
-      globtype,verbose,nutils,compinnr,
+      globtype,globals,verbose,nutils,compinnr,
       defutil,defcmp,htypechk,pass_1,constexp,
-      nadd,ncal,ncon,ncnv,ninl,nld,nmat,
+      nadd,ncal,ncon,ncnv,ninl,nmat,
       symdef;
 
     function try_opt_assignmentnode(assignmentnode: tassignmentnode): tnode;
@@ -57,6 +58,10 @@ unit optloadmodifystore;
         result:=nil;
         with assignmentnode do
           begin
+            { *** Here are simple optimizations which are performed
+              when -O2 (via a call from tassignmentnode.simplify) or
+              when cs_opt_use_load_modify_store is enabled (in a separate pass).
+            }
             { replace i:=succ/pred(i) by inc/dec(i)? }
             if (right.nodetype=inlinen) and
               ((tinlinenode(right).inlinenumber=in_succ_x) or (tinlinenode(right).inlinenumber=in_pred_x)) and
@@ -273,6 +278,71 @@ unit optloadmodifystore;
                 taddnode(ttypeconvnode(right).left).left:=nil;
                 exit;
               end;
+            { replace i:=not i  by in_not_assign_x(i)
+                      i:=-i     by in_neg_assign_x(i)
+
+              this handles the case, where there are no implicit type conversions }
+            if (right.nodetype in [notn,unaryminusn]) and
+              (tunarynode(right).left.isequal(left)) and
+              is_integer(tunarynode(right).left.resultdef) and
+              ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
+              ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
+              valid_for_var(tunarynode(right).left,false) and
+              not(might_have_sideeffects(tunarynode(right).left)) then
+              begin
+                if right.nodetype=notn then
+                  newinlinenodetype:=in_not_assign_x
+                else
+                  newinlinenodetype:=in_neg_assign_x;
+                result:=cinlinenode.createintern(
+                  newinlinenodetype,false,tunarynode(right).left);
+                result.localswitches:=localswitches;
+                result.fileinfo:=fileinfo;
+                result.verbosity:=verbosity;
+                tunarynode(right).left:=nil;
+                exit;
+              end;
+            { replace i:=not i  by in_not_assign_x(i)
+                      i:=-i     by in_neg_assign_x(i)
+
+              this handles the case with type conversions:
+                   outer typeconv: right
+                          neg/not: ttypeconvnode(right).left
+                   inner typeconv: tunarynode(ttypeconvnode(right).left).left
+                   right side 'i': ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left }
+            if (right.nodetype=typeconvn) and
+               (ttypeconvnode(right).convtype=tc_int_2_int) and
+               (ttypeconvnode(right).left.nodetype in [notn,unaryminusn]) and
+               is_integer(ttypeconvnode(right).left.resultdef) and
+               (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
+               (tunarynode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
+               (ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
+               are_equal_ints(right.resultdef,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
+               ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.isequal(left) and
+               is_integer(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
+               ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
+               ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
+               valid_for_var(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left,false) and
+               not(might_have_sideeffects(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left)) then
+              begin
+                if ttypeconvnode(right).left.nodetype=notn then
+                  newinlinenodetype:=in_not_assign_x
+                else
+                  newinlinenodetype:=in_neg_assign_x;
+                result:=cinlinenode.createintern(
+                  newinlinenodetype,false,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left);
+                result.localswitches:=localswitches;
+                result.fileinfo:=fileinfo;
+                result.verbosity:=verbosity;
+                ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil;
+                exit;
+              end;
+
+            if not (cs_opt_use_load_modify_store in current_settings.optimizerswitches) then
+              exit;
+            { *** Here are more complex optimizations which are performed only
+              when cs_opt_use_load_modify_store is enabled.
+            }
 {$ifdef enable_shl_shr_assign_x_y}
             { replace i:=i shl k by in_shl_assign_x_y(i,k)
                       i:=i shr k by in_shr_assign_x_y(i,k)
@@ -555,65 +625,6 @@ unit optloadmodifystore;
                 exit;
               end;
 {$endif enable_sar_assign_x_y or enable_rox_assign_x_y}
-            { replace i:=not i  by in_not_assign_x(i)
-                      i:=-i     by in_neg_assign_x(i)
-
-              this handles the case, where there are no implicit type conversions }
-            if (right.nodetype in [notn,unaryminusn]) and
-              (tunarynode(right).left.isequal(left)) and
-              is_integer(tunarynode(right).left.resultdef) and
-              ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
-              ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
-              valid_for_var(tunarynode(right).left,false) and
-              not(might_have_sideeffects(tunarynode(right).left)) then
-              begin
-                if right.nodetype=notn then
-                  newinlinenodetype:=in_not_assign_x
-                else
-                  newinlinenodetype:=in_neg_assign_x;
-                result:=cinlinenode.createintern(
-                  newinlinenodetype,false,tunarynode(right).left);
-                result.localswitches:=localswitches;
-                result.fileinfo:=fileinfo;
-                result.verbosity:=verbosity;
-                tunarynode(right).left:=nil;
-                exit;
-              end;
-            { replace i:=not i  by in_not_assign_x(i)
-                      i:=-i     by in_neg_assign_x(i)
-
-              this handles the case with type conversions:
-                   outer typeconv: right
-                          neg/not: ttypeconvnode(right).left
-                   inner typeconv: tunarynode(ttypeconvnode(right).left).left
-                   right side 'i': ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left }
-            if (right.nodetype=typeconvn) and
-               (ttypeconvnode(right).convtype=tc_int_2_int) and
-               (ttypeconvnode(right).left.nodetype in [notn,unaryminusn]) and
-               is_integer(ttypeconvnode(right).left.resultdef) and
-               (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
-               (tunarynode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
-               (ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
-               are_equal_ints(right.resultdef,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
-               ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.isequal(left) and
-               is_integer(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
-               ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
-               ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
-               valid_for_var(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left,false) and
-               not(might_have_sideeffects(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left)) then
-              begin
-                if ttypeconvnode(right).left.nodetype=notn then
-                  newinlinenodetype:=in_not_assign_x
-                else
-                  newinlinenodetype:=in_neg_assign_x;
-                result:=cinlinenode.createintern(
-                  newinlinenodetype,false,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left);
-                result.localswitches:=localswitches;
-                result.fileinfo:=fileinfo;
-                result.verbosity:=verbosity;
-                ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil;
-                exit;
-              end;
           end;
       end;