From 07698050e56747de32c7ce580467cc8bbebb2a28 Mon Sep 17 00:00:00 2001 From: Yuriy Sydorov Date: Fri, 13 Aug 2021 13:53:22 +0300 Subject: [PATCH] * 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. --- compiler/nld.pas | 10 ++- compiler/optloadmodifystore.pas | 135 +++++++++++++++++--------------- 2 files changed, 82 insertions(+), 63 deletions(-) diff --git a/compiler/nld.pas b/compiler/nld.pas index 7be26db2bc..49b8b42293 100644 --- a/compiler/nld.pas +++ b/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; diff --git a/compiler/optloadmodifystore.pas b/compiler/optloadmodifystore.pas index ecca114000..84c45d36cf 100644 --- a/compiler/optloadmodifystore.pas +++ b/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;