diff --git a/.gitattributes b/.gitattributes index 591cb1fb57..fb00fc3917 100644 --- a/.gitattributes +++ b/.gitattributes @@ -516,6 +516,7 @@ compiler/optdead.pas svneol=native#text/plain compiler/optdeadstore.pas svneol=native#text/pascal compiler/optdfa.pas svneol=native#text/plain compiler/options.pas svneol=native#text/plain +compiler/optloadmodifystore.pas svneol=native#text/plain compiler/optloop.pas svneol=native#text/plain compiler/opttail.pas svneol=native#text/plain compiler/optutils.pas svneol=native#text/plain diff --git a/compiler/globtype.pas b/compiler/globtype.pas index f373212f7d..073813b6e7 100644 --- a/compiler/globtype.pas +++ b/compiler/globtype.pas @@ -313,7 +313,8 @@ interface cs_opt_remove_emtpy_proc, cs_opt_constant_propagate, cs_opt_dead_store_eliminate, - cs_opt_forcenostackframe + cs_opt_forcenostackframe, + cs_opt_use_load_modify_store ); toptimizerswitches = set of toptimizerswitch; @@ -335,14 +336,14 @@ interface end; const - OptimizerSwitchStr : array[toptimizerswitch] of string[17] = ('', + OptimizerSwitchStr : array[toptimizerswitch] of string[18] = ('', 'LEVEL1','LEVEL2','LEVEL3','LEVEL4', 'REGVAR','UNCERTAIN','SIZE','STACKFRAME', 'PEEPHOLE','LOOPUNROLL','TAILREC','CSE', 'DFA','STRENGTH','SCHEDULE','AUTOINLINE','USEEBP','USERBP', 'ORDERFIELDS','FASTMATH','DEADVALUES','REMOVEEMPTYPROCS', 'CONSTPROP', - 'DEADSTORE','FORCENOSTACKFRAME' + 'DEADSTORE','FORCENOSTACKFRAME','USELOADMODIFYSTORE' ); WPOptimizerSwitchStr : array [twpoptimizerswitch] of string[14] = ( 'DEVIRTCALLS','OPTVMTS','SYMBOLLIVENESS' @@ -368,7 +369,7 @@ interface { switches being applied to all CPUs at the given level } genericlevel1optimizerswitches = [cs_opt_level1,cs_opt_peephole]; genericlevel2optimizerswitches = [cs_opt_level2,cs_opt_remove_emtpy_proc]; - genericlevel3optimizerswitches = [cs_opt_level3,cs_opt_constant_propagate,cs_opt_nodedfa]; + genericlevel3optimizerswitches = [cs_opt_level3,cs_opt_constant_propagate,cs_opt_nodedfa,cs_opt_use_load_modify_store]; genericlevel4optimizerswitches = [cs_opt_level4,cs_opt_reorder_fields,cs_opt_dead_values,cs_opt_fastmath]; { whole program optimizations whose information generation requires diff --git a/compiler/nld.pas b/compiler/nld.pas index 60f074b87b..e48ce25443 100644 --- a/compiler/nld.pas +++ b/compiler/nld.pas @@ -551,8 +551,6 @@ implementation function tassignmentnode.simplify(forinline : boolean) : tnode; - var - newinlinenodetype : byte; begin result:=nil; { assignment nodes can perform several floating point } @@ -565,217 +563,6 @@ implementation is_constrealnode(right) and not equal_defs(right.resultdef,left.resultdef) then inserttypeconv(right,left.resultdef); - - if cs_opt_level2 in current_settings.optimizerswitches then - begin - { 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 - (tinlinenode(right).left.isequal(left)) and - ((localswitches*[cs_check_overflow,cs_check_range])=[]) and - ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and - valid_for_var(tinlinenode(right).left,false) and - not(might_have_sideeffects(tinlinenode(right).left)) then - begin - if tinlinenode(right).inlinenumber=in_succ_x then - newinlinenodetype:=in_inc_x - else - newinlinenodetype:=in_dec_x; - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - tinlinenode(right).left,nil)); - tinlinenode(right).left:=nil; - exit; - end; - if cs_opt_level3 in current_settings.optimizerswitches then - begin - { replace i:=i+k by inc(i,k) - i:=i-k by dec(i,k) - i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k) - - this handles the case, where there are no implicit type conversions } - if (right.nodetype in [addn,subn,andn,orn,xorn]) and - (taddnode(right).left.isequal(left)) and - is_integer(taddnode(right).left.resultdef) and - is_integer(taddnode(right).right.resultdef) and - ((localswitches*[cs_check_overflow,cs_check_range])=[]) and - ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and - valid_for_var(taddnode(right).left,false) and - not(might_have_sideeffects(taddnode(right).left)) then - begin - case right.nodetype of - addn: - newinlinenodetype:=in_inc_x; - subn: - newinlinenodetype:=in_dec_x; - andn: - newinlinenodetype:=in_and_assign_x_y; - orn: - newinlinenodetype:=in_or_assign_x_y; - xorn: - newinlinenodetype:=in_xor_assign_x_y; - else - internalerror(2017032901); - end; - if right.nodetype in [addn,subn] then - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - taddnode(right).left,ccallparanode.create(taddnode(right).right,nil))) - else - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - taddnode(right).right,ccallparanode.create(taddnode(right).left,nil))); - taddnode(right).left:=nil; - taddnode(right).right:=nil; - exit; - end; - { replace i:=i+k by inc(i,k) - i:=i-k by dec(i,k) - i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k) - - this handles the case with two conversions (outer and inner): - outer typeconv: right - add/sub/and/or/xor: ttypeconvnode(right).left - inner typeconv: taddnode(ttypeconvnode(right).left).left - right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left - right side 'k': taddnode(ttypeconvnode(right).left).right } - if (right.nodetype=typeconvn) and - (ttypeconvnode(right).convtype=tc_int_2_int) and - (ttypeconvnode(right).left.nodetype in [addn,subn,andn,orn,xorn]) and - is_integer(ttypeconvnode(right).left.resultdef) and - (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and - (taddnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and - (ttypeconvnode(taddnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and - are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and - ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.isequal(left) and - is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and - is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and - is_integer(ttypeconvnode(taddnode(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(taddnode(ttypeconvnode(right).left).left).left,false) and - not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left)) then - begin - case ttypeconvnode(right).left.nodetype of - addn: - newinlinenodetype:=in_inc_x; - subn: - newinlinenodetype:=in_dec_x; - andn: - newinlinenodetype:=in_and_assign_x_y; - orn: - newinlinenodetype:=in_or_assign_x_y; - xorn: - newinlinenodetype:=in_xor_assign_x_y; - else - internalerror(2017032901); - end; - inserttypeconv_internal(taddnode(ttypeconvnode(right).left).right,left.resultdef); - if ttypeconvnode(right).left.nodetype in [addn,subn] then - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).right,nil))) - else - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - taddnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,nil))); - ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left:=nil; - taddnode(ttypeconvnode(right).left).right:=nil; - exit; - end; - { replace i:=k+i by inc(i,k) - i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k) - todo: for some integer types, there are extra implicit - typecasts inserted by the compiler; this code should be - updated to handle them as well } - if (right.nodetype in [addn,andn,orn,xorn]) and - (taddnode(right).right.isequal(left)) and - is_integer(taddnode(right).left.resultdef) and - is_integer(taddnode(right).right.resultdef) and - ((localswitches*[cs_check_overflow,cs_check_range])=[]) and - ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and - valid_for_var(taddnode(right).right,false) and - not(might_have_sideeffects(taddnode(right).right)) then - begin - case right.nodetype of - addn: - newinlinenodetype:=in_inc_x; - andn: - newinlinenodetype:=in_and_assign_x_y; - orn: - newinlinenodetype:=in_or_assign_x_y; - xorn: - newinlinenodetype:=in_xor_assign_x_y; - else - internalerror(2017032902); - end; - if right.nodetype=addn then - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - taddnode(right).right,ccallparanode.create(taddnode(right).left,nil))) - else - result:=cinlinenode.createintern( - newinlinenodetype,false,ccallparanode.create( - taddnode(right).left,ccallparanode.create(taddnode(right).right,nil))); - taddnode(right).right:=nil; - taddnode(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, 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); - 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); - ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil; - exit; - end; - end; - end; end; diff --git a/compiler/optloadmodifystore.pas b/compiler/optloadmodifystore.pas new file mode 100644 index 0000000000..7c2b548586 --- /dev/null +++ b/compiler/optloadmodifystore.pas @@ -0,0 +1,281 @@ +{ + Copyright (c) 2017 by Nikolay Nikolov + + Optimizations for making use of load-modify-store operations in CISC-like + instruction set architectures (such as x86) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} + +unit optloadmodifystore; + +{$i fpcdefs.inc} + + interface + + uses + node; + + procedure do_optloadmodifystore(var rootnode : tnode); + + implementation + + uses + globtype,verbose,nutils, + defutil,defcmp,htypechk,pass_1, + nadd,ncal,ncnv,ninl,nld; + + function try_opt_assignmentnode(assignmentnode: tassignmentnode): tnode; + var + newinlinenodetype: byte; + begin + result:=nil; + with assignmentnode do + begin + { 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 + (tinlinenode(right).left.isequal(left)) and + ((localswitches*[cs_check_overflow,cs_check_range])=[]) and + ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and + valid_for_var(tinlinenode(right).left,false) and + not(might_have_sideeffects(tinlinenode(right).left)) then + begin + if tinlinenode(right).inlinenumber=in_succ_x then + newinlinenodetype:=in_inc_x + else + newinlinenodetype:=in_dec_x; + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + tinlinenode(right).left,nil)); + tinlinenode(right).left:=nil; + exit; + end; + { replace i:=i+k by inc(i,k) + i:=i-k by dec(i,k) + i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k) + + this handles the case, where there are no implicit type conversions } + if (right.nodetype in [addn,subn,andn,orn,xorn]) and + (taddnode(right).left.isequal(left)) and + is_integer(taddnode(right).left.resultdef) and + is_integer(taddnode(right).right.resultdef) and + ((localswitches*[cs_check_overflow,cs_check_range])=[]) and + ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and + valid_for_var(taddnode(right).left,false) and + not(might_have_sideeffects(taddnode(right).left)) then + begin + case right.nodetype of + addn: + newinlinenodetype:=in_inc_x; + subn: + newinlinenodetype:=in_dec_x; + andn: + newinlinenodetype:=in_and_assign_x_y; + orn: + newinlinenodetype:=in_or_assign_x_y; + xorn: + newinlinenodetype:=in_xor_assign_x_y; + else + internalerror(2017032901); + end; + if right.nodetype in [addn,subn] then + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + taddnode(right).left,ccallparanode.create(taddnode(right).right,nil))) + else + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + taddnode(right).right,ccallparanode.create(taddnode(right).left,nil))); + taddnode(right).left:=nil; + taddnode(right).right:=nil; + exit; + end; + { replace i:=i+k by inc(i,k) + i:=i-k by dec(i,k) + i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k) + + this handles the case with two conversions (outer and inner): + outer typeconv: right + add/sub/and/or/xor: ttypeconvnode(right).left + inner typeconv: taddnode(ttypeconvnode(right).left).left + right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left + right side 'k': taddnode(ttypeconvnode(right).left).right } + if (right.nodetype=typeconvn) and + (ttypeconvnode(right).convtype=tc_int_2_int) and + (ttypeconvnode(right).left.nodetype in [addn,subn,andn,orn,xorn]) and + is_integer(ttypeconvnode(right).left.resultdef) and + (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and + (taddnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and + (ttypeconvnode(taddnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and + are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and + ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.isequal(left) and + is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and + is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and + is_integer(ttypeconvnode(taddnode(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(taddnode(ttypeconvnode(right).left).left).left,false) and + not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left)) then + begin + case ttypeconvnode(right).left.nodetype of + addn: + newinlinenodetype:=in_inc_x; + subn: + newinlinenodetype:=in_dec_x; + andn: + newinlinenodetype:=in_and_assign_x_y; + orn: + newinlinenodetype:=in_or_assign_x_y; + xorn: + newinlinenodetype:=in_xor_assign_x_y; + else + internalerror(2017032901); + end; + inserttypeconv_internal(taddnode(ttypeconvnode(right).left).right,left.resultdef); + if ttypeconvnode(right).left.nodetype in [addn,subn] then + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).right,nil))) + else + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + taddnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,nil))); + ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left:=nil; + taddnode(ttypeconvnode(right).left).right:=nil; + exit; + end; + { replace i:=k+i by inc(i,k) + i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k) + todo: for some integer types, there are extra implicit + typecasts inserted by the compiler; this code should be + updated to handle them as well } + if (right.nodetype in [addn,andn,orn,xorn]) and + (taddnode(right).right.isequal(left)) and + is_integer(taddnode(right).left.resultdef) and + is_integer(taddnode(right).right.resultdef) and + ((localswitches*[cs_check_overflow,cs_check_range])=[]) and + ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and + valid_for_var(taddnode(right).right,false) and + not(might_have_sideeffects(taddnode(right).right)) then + begin + case right.nodetype of + addn: + newinlinenodetype:=in_inc_x; + andn: + newinlinenodetype:=in_and_assign_x_y; + orn: + newinlinenodetype:=in_or_assign_x_y; + xorn: + newinlinenodetype:=in_xor_assign_x_y; + else + internalerror(2017032902); + end; + if right.nodetype=addn then + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + taddnode(right).right,ccallparanode.create(taddnode(right).left,nil))) + else + result:=cinlinenode.createintern( + newinlinenodetype,false,ccallparanode.create( + taddnode(right).left,ccallparanode.create(taddnode(right).right,nil))); + taddnode(right).right:=nil; + taddnode(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, 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); + 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); + ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil; + exit; + end; + end; + end; + + function try_opt_node(var n: tnode; arg: pointer): foreachnoderesult; + var + hn : tnode; + begin + result:=fen_false; + if n.nodetype=assignn then + begin + hn:=try_opt_assignmentnode(tassignmentnode(n)); + if assigned(hn) then + begin + n.free; + n:=hn; + typecheckpass(n); + do_firstpass(n); + end; + end; + end; + + + procedure do_optloadmodifystore(var rootnode : tnode); + begin + foreachnodestatic(pm_postprocess,rootnode,@try_opt_node,nil); + end; + +end. + diff --git a/compiler/ppc8086.lpi b/compiler/ppc8086.lpi index eb0df83c81..b0d3f0e8b2 100644 --- a/compiler/ppc8086.lpi +++ b/compiler/ppc8086.lpi @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <CONFIG> <ProjectOptions> - <Version Value="10"/> + <Version Value="9"/> <PathDelim Value="\"/> <General> <Flags> @@ -28,7 +28,7 @@ <LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/> </local> </RunParams> - <Units Count="251"> + <Units Count="252"> <Unit0> <Filename Value="pp.pas"/> <IsPartOfProject Value="True"/> @@ -449,6 +449,7 @@ <Unit104> <Filename Value="aoptobj.pas"/> <IsPartOfProject Value="True"/> + <UnitName Value="AoptObj"/> </Unit104> <Unit105> <Filename Value="assemble.pas"/> @@ -1035,6 +1036,10 @@ <Filename Value="syscinfo.pas"/> <IsPartOfProject Value="True"/> </Unit250> + <Unit251> + <Filename Value="optloadmodifystore.pas"/> + <IsPartOfProject Value="True"/> + </Unit251> </Units> </ProjectOptions> <CompilerOptions> diff --git a/compiler/psub.pas b/compiler/psub.pas index 9b0e7d209e..14147194e3 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -129,7 +129,8 @@ implementation optcse, optloop, optconstprop, - optdeadstore + optdeadstore, + optloadmodifystore {$if defined(arm)} ,cpuinfo {$endif arm} @@ -1437,6 +1438,9 @@ implementation if cs_opt_nodecse in current_settings.optimizerswitches then do_optcse(code); + if cs_opt_use_load_modify_store in current_settings.optimizerswitches then + do_optloadmodifystore(code); + { only do secondpass if there are no errors } if (ErrorCount=0) then begin