123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656 |
- {
- 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}
- {$if defined(i386) or defined(x86_64) or defined(m68k)}
- {$define enable_shl_shr_assign_x_y}
- {$endif}
- {$if defined(i386) or defined(x86_64)}
- {$define enable_sar_assign_x_y}
- {$endif}
- {$if defined(i386) or defined(x86_64)}
- {$define enable_rox_assign_x_y}
- {$endif}
- interface
- uses
- node,nld;
- procedure do_optloadmodifystore(var rootnode : tnode);
- function try_opt_assignmentnode(assignmentnode : tassignmentnode): tnode;
- implementation
- uses
- globtype,globals,verbose,nutils,compinnr,
- defutil,defcmp,htypechk,pass_1,constexp,
- nadd,ncal,ncon,ncnv,ninl,nmat,
- symdef;
- function try_opt_assignmentnode(assignmentnode: tassignmentnode): tnode;
- var
- newinlinenodetype: tinlinenumber;
- begin
- 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
- (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));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- 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)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- 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(2017032903);
- 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)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- 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)
- this handles the case, where there are no implicit type conversions }
- 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)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- taddnode(right).right:=nil;
- taddnode(right).left:=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)
- this handles the case with two conversions (outer and inner):
- outer typeconv: right
- add/and/or/xor: ttypeconvnode(right).left
- inner typeconv: taddnode(ttypeconvnode(right).left).right
- right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left
- right side 'k': taddnode(ttypeconvnode(right).left).left }
- if (right.nodetype=typeconvn) and
- (ttypeconvnode(right).convtype=tc_int_2_int) and
- (ttypeconvnode(right).left.nodetype in [addn,andn,orn,xorn]) and
- is_integer(ttypeconvnode(right).left.resultdef) and
- (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
- (taddnode(ttypeconvnode(right).left).right.nodetype=typeconvn) and
- (ttypeconvnode(taddnode(ttypeconvnode(right).left).right).convtype=tc_int_2_int) and
- are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.resultdef) and
- ttypeconvnode(taddnode(ttypeconvnode(right).left).right).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).right).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).right).left,false) and
- not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left)) then
- begin
- case ttypeconvnode(right).left.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(2017051101);
- end;
- inserttypeconv_internal(taddnode(ttypeconvnode(right).left).left,left.resultdef);
- if ttypeconvnode(right).left.nodetype=addn then
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).left,nil)))
- else
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- taddnode(ttypeconvnode(right).left).left,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left:=nil;
- 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)
- this handles the case, where there are no implicit type conversions }
- if (right.nodetype in [shln,shrn]) and
- (tshlshrnode(right).left.isequal(left)) and
- is_integer(tshlshrnode(right).left.resultdef) and
- is_integer(tshlshrnode(right).right.resultdef) and
- {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
- not(is_64bitint(tshlshrnode(right).left.resultdef)) and
- {$endif}
- ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
- ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
- valid_for_var(tshlshrnode(right).left,false) and
- not(might_have_sideeffects(tshlshrnode(right).left)) then
- begin
- case right.nodetype of
- shln:
- newinlinenodetype:=in_shl_assign_x_y;
- shrn:
- newinlinenodetype:=in_shr_assign_x_y;
- else
- internalerror(2017051201);
- end;
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- tshlshrnode(right).right,ccallparanode.create(tshlshrnode(right).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- tshlshrnode(right).left:=nil;
- tshlshrnode(right).right:=nil;
- exit;
- end;
- { 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)
- this handles the case with two conversions (outer and inner):
- outer typeconv: right
- shl/shr: ttypeconvnode(right).left
- inner typeconv: tshlshrnode(ttypeconvnode(right).left).left
- right side 'i': ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left
- right side 'k': tshlshrnode(ttypeconvnode(right).left).right }
- if (right.nodetype=typeconvn) and
- (ttypeconvnode(right).convtype=tc_int_2_int) and
- (ttypeconvnode(right).left.nodetype in [shln,shrn]) and
- is_integer(ttypeconvnode(right).left.resultdef) and
- {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
- not(is_64bitint(ttypeconvnode(right).left.resultdef)) and
- {$endif}
- (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
- (tshlshrnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
- (ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
- are_equal_ints(right.resultdef,ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.resultdef) and
- ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.isequal(left) and
- is_integer(tshlshrnode(ttypeconvnode(right).left).left.resultdef) and
- is_integer(tshlshrnode(ttypeconvnode(right).left).right.resultdef) and
- is_integer(ttypeconvnode(tshlshrnode(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(tshlshrnode(ttypeconvnode(right).left).left).left,false) and
- not(might_have_sideeffects(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left)) then
- begin
- case ttypeconvnode(right).left.nodetype of
- shln:
- newinlinenodetype:=in_shl_assign_x_y;
- shrn:
- newinlinenodetype:=in_shr_assign_x_y;
- else
- internalerror(2017051202);
- end;
- inserttypeconv_internal(tshlshrnode(ttypeconvnode(right).left).right,left.resultdef);
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- tshlshrnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left:=nil;
- tshlshrnode(ttypeconvnode(right).left).right:=nil;
- exit;
- end;
- {$endif enable_shl_shr_assign_x_y}
- {$if defined(enable_sar_assign_x_y) or defined(enable_rox_assign_x_y)}
- { replace i:=sar(i) by in_sar_assign_x_y(i,1)
- i:=rol(i) by in_rol_assign_x_y(i,1)
- i:=ror(i) by in_ror_assign_x_y(i,1)
- this handles the case, where there are no implicit type conversions }
- if (right.nodetype=inlinen) and
- (tinlinenode(right).inlinenumber in [
- {$ifdef enable_sar_assign_x_y}
- in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
- {$endif enable_sar_assign_x_y}
- {$ifdef enable_rox_assign_x_y}
- in_rol_x,in_ror_x
- {$endif enable_rox_assign_x_y}
- ]) and
- (tinlinenode(right).left.isequal(left)) and
- is_integer(tinlinenode(right).left.resultdef) and
- {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
- not(is_64bitint(tinlinenode(right).left.resultdef)) and
- {$endif}
- ((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
- case tinlinenode(right).inlinenumber of
- in_sar_x:
- newinlinenodetype:=in_sar_assign_x_y;
- in_rol_x:
- newinlinenodetype:=in_rol_assign_x_y;
- in_ror_x:
- newinlinenodetype:=in_ror_assign_x_y;
- else
- internalerror(2017071701);
- end;
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- cordconstnode.create(1,u8inttype,false),ccallparanode.create(tinlinenode(right).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- tinlinenode(right).left:=nil;
- exit;
- end;
- { replace i:=sar(i) by in_sar_assign_x_y(i,1)
- i:=rol(i) by in_rol_assign_x_y(i,1)
- i:=ror(i) by in_ror_assign_x_y(i,1)
- this handles the case with type conversions:
- outer typeconv: right
- sar/rol/ror inline node: ttypeconvnode(right).left
- inner typeconv: tinlinenode(ttypeconvnode(right).left).left
- right side 'i': ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left }
- if (right.nodetype=typeconvn) and
- (ttypeconvnode(right).convtype=tc_int_2_int) and
- (ttypeconvnode(right).left.nodetype=inlinen) and
- (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
- {$ifdef enable_sar_assign_x_y}
- in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
- {$endif enable_sar_assign_x_y}
- {$ifdef enable_rox_assign_x_y}
- in_rol_x,in_ror_x
- {$endif enable_rox_assign_x_y}
- ]) and
- is_integer(ttypeconvnode(right).left.resultdef) and
- (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
- (tinlinenode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
- (ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
- are_equal_ints(right.resultdef,ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.resultdef) and
- ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.isequal(left) and
- is_integer(ttypeconvnode(tinlinenode(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(tinlinenode(ttypeconvnode(right).left).left).left,false) and
- not(might_have_sideeffects(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left)) then
- begin
- case tinlinenode(ttypeconvnode(right).left).inlinenumber of
- in_sar_x:
- newinlinenodetype:=in_sar_assign_x_y;
- in_rol_x:
- newinlinenodetype:=in_rol_assign_x_y;
- in_ror_x:
- newinlinenodetype:=in_ror_assign_x_y;
- else
- internalerror(2017071801);
- end;
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- cordconstnode.create(1,u8inttype,false),ccallparanode.create(
- ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
- exit;
- end;
- { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
- i:=rol(i,k) by in_rol_assign_x_y(i,k)
- i:=ror(i,k) by in_ror_assign_x_y(i,k)
- this handles the case, where there are no implicit type conversions }
- if (right.nodetype=inlinen) and
- (tinlinenode(right).inlinenumber in [
- {$ifdef enable_sar_assign_x_y}
- in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
- {$endif enable_sar_assign_x_y}
- {$ifdef enable_rox_assign_x_y}
- in_rol_x_y,in_ror_x_y
- {$endif enable_rox_assign_x_y}
- ]) and
- (tinlinenode(right).left.nodetype=callparan) and
- tcallparanode(tcallparanode(tinlinenode(right).left).right).left.isequal(left) and
- is_integer(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef) and
- {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
- not(is_64bitint(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef)) and
- {$endif}
- ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
- ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
- valid_for_var(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,false) and
- not(might_have_sideeffects(tcallparanode(tcallparanode(tinlinenode(right).left).right).left)) then
- begin
- case tinlinenode(right).inlinenumber of
- in_sar_x_y:
- newinlinenodetype:=in_sar_assign_x_y;
- in_rol_x_y:
- newinlinenodetype:=in_rol_assign_x_y;
- in_ror_x_y:
- newinlinenodetype:=in_ror_assign_x_y;
- else
- internalerror(2017071702);
- end;
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- tcallparanode(tinlinenode(right).left).left,
- ccallparanode.create(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- tcallparanode(tinlinenode(right).left).left:=nil;
- tcallparanode(tcallparanode(tinlinenode(right).left).right).left:=nil;
- exit;
- end;
- { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
- i:=rol(i,k) by in_rol_assign_x_y(i,k)
- i:=ror(i,k) by in_ror_assign_x_y(i,k)
- this handles the case with two conversions (outer and inner):
- outer typeconv: right
- sar/rol/ror inline node: ttypeconvnode(right).left
- inner typeconv: tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left
- right side 'i': ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left
- right side 'k': tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left }
- if (right.nodetype=typeconvn) and
- (ttypeconvnode(right).convtype=tc_int_2_int) and
- (ttypeconvnode(right).left.nodetype=inlinen) and
- (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
- {$ifdef enable_sar_assign_x_y}
- in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
- {$endif enable_sar_assign_x_y}
- {$ifdef enable_rox_assign_x_y}
- in_rol_x_y,in_ror_x_y
- {$endif enable_rox_assign_x_y}
- ]) and
- is_integer(ttypeconvnode(right).left.resultdef) and
- (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
- (tinlinenode(ttypeconvnode(right).left).left.nodetype=callparan) and
- (tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left.nodetype=typeconvn) and
- (ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).convtype=tc_int_2_int) and
- are_equal_ints(right.resultdef,ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.resultdef) and
- ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.isequal(left) and
- is_integer(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).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(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,false) and
- not(might_have_sideeffects(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left)) then
- begin
- case tinlinenode(ttypeconvnode(right).left).inlinenumber of
- in_sar_x_y:
- newinlinenodetype:=in_sar_assign_x_y;
- in_rol_x_y:
- newinlinenodetype:=in_rol_assign_x_y;
- in_ror_x_y:
- newinlinenodetype:=in_ror_assign_x_y;
- else
- internalerror(2017072002);
- end;
- result:=cinlinenode.createintern(
- newinlinenodetype,false,ccallparanode.create(
- tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left,
- ccallparanode.create(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,nil)));
- result.localswitches:=localswitches;
- result.fileinfo:=fileinfo;
- result.verbosity:=verbosity;
- tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
- ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left:=nil;
- exit;
- end;
- {$endif enable_sar_assign_x_y or enable_rox_assign_x_y}
- 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.
|