optloadmodifystore.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. {
  2. Copyright (c) 2017 by Nikolay Nikolov
  3. Optimizations for making use of load-modify-store operations in CISC-like
  4. instruction set architectures (such as x86)
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit optloadmodifystore;
  19. {$i fpcdefs.inc}
  20. {$if defined(i386) or defined(x86_64) or defined(m68k)}
  21. {$define enable_shl_shr_assign_x_y}
  22. {$endif}
  23. {$if defined(i386) or defined(x86_64)}
  24. {$define enable_sar_assign_x_y}
  25. {$endif}
  26. {$if defined(i386) or defined(x86_64)}
  27. {$define enable_rox_assign_x_y}
  28. {$endif}
  29. interface
  30. uses
  31. node,nld;
  32. procedure do_optloadmodifystore(var rootnode : tnode);
  33. function try_opt_assignmentnode(assignmentnode : tassignmentnode): tnode;
  34. implementation
  35. uses
  36. globtype,globals,verbose,nutils,compinnr,
  37. defutil,defcmp,htypechk,pass_1,constexp,
  38. nadd,ncal,ncon,ncnv,ninl,nmat,
  39. symdef;
  40. function try_opt_assignmentnode(assignmentnode: tassignmentnode): tnode;
  41. var
  42. newinlinenodetype: tinlinenumber;
  43. begin
  44. result:=nil;
  45. with assignmentnode do
  46. begin
  47. { *** Here are simple optimizations which are performed
  48. when -O2 (via a call from tassignmentnode.simplify) or
  49. when cs_opt_use_load_modify_store is enabled (in a separate pass).
  50. }
  51. { replace i:=succ/pred(i) by inc/dec(i)? }
  52. if (right.nodetype=inlinen) and
  53. ((tinlinenode(right).inlinenumber=in_succ_x) or (tinlinenode(right).inlinenumber=in_pred_x)) and
  54. (tinlinenode(right).left.isequal(left)) and
  55. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  56. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  57. valid_for_var(tinlinenode(right).left,false) and
  58. not(might_have_sideeffects(tinlinenode(right).left)) then
  59. begin
  60. if tinlinenode(right).inlinenumber=in_succ_x then
  61. newinlinenodetype:=in_inc_x
  62. else
  63. newinlinenodetype:=in_dec_x;
  64. result:=cinlinenode.createintern(
  65. newinlinenodetype,false,ccallparanode.create(
  66. tinlinenode(right).left,nil));
  67. result.localswitches:=localswitches;
  68. result.fileinfo:=fileinfo;
  69. result.verbosity:=verbosity;
  70. tinlinenode(right).left:=nil;
  71. exit;
  72. end;
  73. { replace i:=i+k by inc(i,k)
  74. i:=i-k by dec(i,k)
  75. i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k)
  76. this handles the case, where there are no implicit type conversions }
  77. if (right.nodetype in [addn,subn,andn,orn,xorn]) and
  78. (taddnode(right).left.isequal(left)) and
  79. is_integer(taddnode(right).left.resultdef) and
  80. is_integer(taddnode(right).right.resultdef) and
  81. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  82. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  83. valid_for_var(taddnode(right).left,false) and
  84. not(might_have_sideeffects(taddnode(right).left)) then
  85. begin
  86. case right.nodetype of
  87. addn:
  88. newinlinenodetype:=in_inc_x;
  89. subn:
  90. newinlinenodetype:=in_dec_x;
  91. andn:
  92. newinlinenodetype:=in_and_assign_x_y;
  93. orn:
  94. newinlinenodetype:=in_or_assign_x_y;
  95. xorn:
  96. newinlinenodetype:=in_xor_assign_x_y;
  97. else
  98. internalerror(2017032901);
  99. end;
  100. if right.nodetype in [addn,subn] then
  101. result:=cinlinenode.createintern(
  102. newinlinenodetype,false,ccallparanode.create(
  103. taddnode(right).left,ccallparanode.create(taddnode(right).right,nil)))
  104. else
  105. result:=cinlinenode.createintern(
  106. newinlinenodetype,false,ccallparanode.create(
  107. taddnode(right).right,ccallparanode.create(taddnode(right).left,nil)));
  108. result.localswitches:=localswitches;
  109. result.fileinfo:=fileinfo;
  110. result.verbosity:=verbosity;
  111. taddnode(right).left:=nil;
  112. taddnode(right).right:=nil;
  113. exit;
  114. end;
  115. { replace i:=i+k by inc(i,k)
  116. i:=i-k by dec(i,k)
  117. i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k)
  118. this handles the case with two conversions (outer and inner):
  119. outer typeconv: right
  120. add/sub/and/or/xor: ttypeconvnode(right).left
  121. inner typeconv: taddnode(ttypeconvnode(right).left).left
  122. right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left
  123. right side 'k': taddnode(ttypeconvnode(right).left).right }
  124. if (right.nodetype=typeconvn) and
  125. (ttypeconvnode(right).convtype=tc_int_2_int) and
  126. (ttypeconvnode(right).left.nodetype in [addn,subn,andn,orn,xorn]) and
  127. is_integer(ttypeconvnode(right).left.resultdef) and
  128. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  129. (taddnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  130. (ttypeconvnode(taddnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  131. are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and
  132. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.isequal(left) and
  133. is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and
  134. is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and
  135. is_integer(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and
  136. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  137. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  138. valid_for_var(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,false) and
  139. not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left)) then
  140. begin
  141. case ttypeconvnode(right).left.nodetype of
  142. addn:
  143. newinlinenodetype:=in_inc_x;
  144. subn:
  145. newinlinenodetype:=in_dec_x;
  146. andn:
  147. newinlinenodetype:=in_and_assign_x_y;
  148. orn:
  149. newinlinenodetype:=in_or_assign_x_y;
  150. xorn:
  151. newinlinenodetype:=in_xor_assign_x_y;
  152. else
  153. internalerror(2017032903);
  154. end;
  155. inserttypeconv_internal(taddnode(ttypeconvnode(right).left).right,left.resultdef);
  156. if ttypeconvnode(right).left.nodetype in [addn,subn] then
  157. result:=cinlinenode.createintern(
  158. newinlinenodetype,false,ccallparanode.create(
  159. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).right,nil)))
  160. else
  161. result:=cinlinenode.createintern(
  162. newinlinenodetype,false,ccallparanode.create(
  163. taddnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,nil)));
  164. result.localswitches:=localswitches;
  165. result.fileinfo:=fileinfo;
  166. result.verbosity:=verbosity;
  167. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left:=nil;
  168. taddnode(ttypeconvnode(right).left).right:=nil;
  169. exit;
  170. end;
  171. { replace i:=k+i by inc(i,k)
  172. i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k)
  173. this handles the case, where there are no implicit type conversions }
  174. if (right.nodetype in [addn,andn,orn,xorn]) and
  175. (taddnode(right).right.isequal(left)) and
  176. is_integer(taddnode(right).left.resultdef) and
  177. is_integer(taddnode(right).right.resultdef) and
  178. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  179. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  180. valid_for_var(taddnode(right).right,false) and
  181. not(might_have_sideeffects(taddnode(right).right)) then
  182. begin
  183. case right.nodetype of
  184. addn:
  185. newinlinenodetype:=in_inc_x;
  186. andn:
  187. newinlinenodetype:=in_and_assign_x_y;
  188. orn:
  189. newinlinenodetype:=in_or_assign_x_y;
  190. xorn:
  191. newinlinenodetype:=in_xor_assign_x_y;
  192. else
  193. internalerror(2017032902);
  194. end;
  195. if right.nodetype=addn then
  196. result:=cinlinenode.createintern(
  197. newinlinenodetype,false,ccallparanode.create(
  198. taddnode(right).right,ccallparanode.create(taddnode(right).left,nil)))
  199. else
  200. result:=cinlinenode.createintern(
  201. newinlinenodetype,false,ccallparanode.create(
  202. taddnode(right).left,ccallparanode.create(taddnode(right).right,nil)));
  203. result.localswitches:=localswitches;
  204. result.fileinfo:=fileinfo;
  205. result.verbosity:=verbosity;
  206. taddnode(right).right:=nil;
  207. taddnode(right).left:=nil;
  208. exit;
  209. end;
  210. { replace i:=k+i by inc(i,k)
  211. i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k)
  212. this handles the case with two conversions (outer and inner):
  213. outer typeconv: right
  214. add/and/or/xor: ttypeconvnode(right).left
  215. inner typeconv: taddnode(ttypeconvnode(right).left).right
  216. right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left
  217. right side 'k': taddnode(ttypeconvnode(right).left).left }
  218. if (right.nodetype=typeconvn) and
  219. (ttypeconvnode(right).convtype=tc_int_2_int) and
  220. (ttypeconvnode(right).left.nodetype in [addn,andn,orn,xorn]) and
  221. is_integer(ttypeconvnode(right).left.resultdef) and
  222. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  223. (taddnode(ttypeconvnode(right).left).right.nodetype=typeconvn) and
  224. (ttypeconvnode(taddnode(ttypeconvnode(right).left).right).convtype=tc_int_2_int) and
  225. are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.resultdef) and
  226. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.isequal(left) and
  227. is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and
  228. is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and
  229. is_integer(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.resultdef) and
  230. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  231. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  232. valid_for_var(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,false) and
  233. not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left)) then
  234. begin
  235. case ttypeconvnode(right).left.nodetype of
  236. addn:
  237. newinlinenodetype:=in_inc_x;
  238. andn:
  239. newinlinenodetype:=in_and_assign_x_y;
  240. orn:
  241. newinlinenodetype:=in_or_assign_x_y;
  242. xorn:
  243. newinlinenodetype:=in_xor_assign_x_y;
  244. else
  245. internalerror(2017051101);
  246. end;
  247. inserttypeconv_internal(taddnode(ttypeconvnode(right).left).left,left.resultdef);
  248. if ttypeconvnode(right).left.nodetype=addn then
  249. result:=cinlinenode.createintern(
  250. newinlinenodetype,false,ccallparanode.create(
  251. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).left,nil)))
  252. else
  253. result:=cinlinenode.createintern(
  254. newinlinenodetype,false,ccallparanode.create(
  255. taddnode(ttypeconvnode(right).left).left,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,nil)));
  256. result.localswitches:=localswitches;
  257. result.fileinfo:=fileinfo;
  258. result.verbosity:=verbosity;
  259. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left:=nil;
  260. taddnode(ttypeconvnode(right).left).left:=nil;
  261. exit;
  262. end;
  263. { replace i:=not i by in_not_assign_x(i)
  264. i:=-i by in_neg_assign_x(i)
  265. this handles the case, where there are no implicit type conversions }
  266. if (right.nodetype in [notn,unaryminusn]) and
  267. (tunarynode(right).left.isequal(left)) and
  268. is_integer(tunarynode(right).left.resultdef) and
  269. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  270. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  271. valid_for_var(tunarynode(right).left,false) and
  272. not(might_have_sideeffects(tunarynode(right).left)) then
  273. begin
  274. if right.nodetype=notn then
  275. newinlinenodetype:=in_not_assign_x
  276. else
  277. newinlinenodetype:=in_neg_assign_x;
  278. result:=cinlinenode.createintern(
  279. newinlinenodetype,false,tunarynode(right).left);
  280. result.localswitches:=localswitches;
  281. result.fileinfo:=fileinfo;
  282. result.verbosity:=verbosity;
  283. tunarynode(right).left:=nil;
  284. exit;
  285. end;
  286. { replace i:=not i by in_not_assign_x(i)
  287. i:=-i by in_neg_assign_x(i)
  288. this handles the case with type conversions:
  289. outer typeconv: right
  290. neg/not: ttypeconvnode(right).left
  291. inner typeconv: tunarynode(ttypeconvnode(right).left).left
  292. right side 'i': ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left }
  293. if (right.nodetype=typeconvn) and
  294. (ttypeconvnode(right).convtype=tc_int_2_int) and
  295. (ttypeconvnode(right).left.nodetype in [notn,unaryminusn]) and
  296. is_integer(ttypeconvnode(right).left.resultdef) and
  297. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  298. (tunarynode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  299. (ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  300. are_equal_ints(right.resultdef,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
  301. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.isequal(left) and
  302. is_integer(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
  303. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  304. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  305. valid_for_var(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left,false) and
  306. not(might_have_sideeffects(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left)) then
  307. begin
  308. if ttypeconvnode(right).left.nodetype=notn then
  309. newinlinenodetype:=in_not_assign_x
  310. else
  311. newinlinenodetype:=in_neg_assign_x;
  312. result:=cinlinenode.createintern(
  313. newinlinenodetype,false,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left);
  314. result.localswitches:=localswitches;
  315. result.fileinfo:=fileinfo;
  316. result.verbosity:=verbosity;
  317. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil;
  318. exit;
  319. end;
  320. if not (cs_opt_use_load_modify_store in current_settings.optimizerswitches) then
  321. exit;
  322. { *** Here are more complex optimizations which are performed only
  323. when cs_opt_use_load_modify_store is enabled.
  324. }
  325. {$ifdef enable_shl_shr_assign_x_y}
  326. { replace i:=i shl k by in_shl_assign_x_y(i,k)
  327. i:=i shr k by in_shr_assign_x_y(i,k)
  328. this handles the case, where there are no implicit type conversions }
  329. if (right.nodetype in [shln,shrn]) and
  330. (tshlshrnode(right).left.isequal(left)) and
  331. is_integer(tshlshrnode(right).left.resultdef) and
  332. is_integer(tshlshrnode(right).right.resultdef) and
  333. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  334. not(is_64bitint(tshlshrnode(right).left.resultdef)) and
  335. {$endif}
  336. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  337. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  338. valid_for_var(tshlshrnode(right).left,false) and
  339. not(might_have_sideeffects(tshlshrnode(right).left)) then
  340. begin
  341. case right.nodetype of
  342. shln:
  343. newinlinenodetype:=in_shl_assign_x_y;
  344. shrn:
  345. newinlinenodetype:=in_shr_assign_x_y;
  346. else
  347. internalerror(2017051201);
  348. end;
  349. result:=cinlinenode.createintern(
  350. newinlinenodetype,false,ccallparanode.create(
  351. tshlshrnode(right).right,ccallparanode.create(tshlshrnode(right).left,nil)));
  352. result.localswitches:=localswitches;
  353. result.fileinfo:=fileinfo;
  354. result.verbosity:=verbosity;
  355. tshlshrnode(right).left:=nil;
  356. tshlshrnode(right).right:=nil;
  357. exit;
  358. end;
  359. { replace i:=i shl k by in_shl_assign_x_y(i,k)
  360. i:=i shr k by in_shr_assign_x_y(i,k)
  361. this handles the case with two conversions (outer and inner):
  362. outer typeconv: right
  363. shl/shr: ttypeconvnode(right).left
  364. inner typeconv: tshlshrnode(ttypeconvnode(right).left).left
  365. right side 'i': ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left
  366. right side 'k': tshlshrnode(ttypeconvnode(right).left).right }
  367. if (right.nodetype=typeconvn) and
  368. (ttypeconvnode(right).convtype=tc_int_2_int) and
  369. (ttypeconvnode(right).left.nodetype in [shln,shrn]) and
  370. is_integer(ttypeconvnode(right).left.resultdef) and
  371. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  372. not(is_64bitint(ttypeconvnode(right).left.resultdef)) and
  373. {$endif}
  374. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  375. (tshlshrnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  376. (ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  377. are_equal_ints(right.resultdef,ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.resultdef) and
  378. ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.isequal(left) and
  379. is_integer(tshlshrnode(ttypeconvnode(right).left).left.resultdef) and
  380. is_integer(tshlshrnode(ttypeconvnode(right).left).right.resultdef) and
  381. is_integer(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.resultdef) and
  382. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  383. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  384. valid_for_var(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left,false) and
  385. not(might_have_sideeffects(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left)) then
  386. begin
  387. case ttypeconvnode(right).left.nodetype of
  388. shln:
  389. newinlinenodetype:=in_shl_assign_x_y;
  390. shrn:
  391. newinlinenodetype:=in_shr_assign_x_y;
  392. else
  393. internalerror(2017051202);
  394. end;
  395. inserttypeconv_internal(tshlshrnode(ttypeconvnode(right).left).right,left.resultdef);
  396. result:=cinlinenode.createintern(
  397. newinlinenodetype,false,ccallparanode.create(
  398. tshlshrnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left,nil)));
  399. result.localswitches:=localswitches;
  400. result.fileinfo:=fileinfo;
  401. result.verbosity:=verbosity;
  402. ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left:=nil;
  403. tshlshrnode(ttypeconvnode(right).left).right:=nil;
  404. exit;
  405. end;
  406. {$endif enable_shl_shr_assign_x_y}
  407. {$if defined(enable_sar_assign_x_y) or defined(enable_rox_assign_x_y)}
  408. { replace i:=sar(i) by in_sar_assign_x_y(i,1)
  409. i:=rol(i) by in_rol_assign_x_y(i,1)
  410. i:=ror(i) by in_ror_assign_x_y(i,1)
  411. this handles the case, where there are no implicit type conversions }
  412. if (right.nodetype=inlinen) and
  413. (tinlinenode(right).inlinenumber in [
  414. {$ifdef enable_sar_assign_x_y}
  415. in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
  416. {$endif enable_sar_assign_x_y}
  417. {$ifdef enable_rox_assign_x_y}
  418. in_rol_x,in_ror_x
  419. {$endif enable_rox_assign_x_y}
  420. ]) and
  421. (tinlinenode(right).left.isequal(left)) and
  422. is_integer(tinlinenode(right).left.resultdef) and
  423. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  424. not(is_64bitint(tinlinenode(right).left.resultdef)) and
  425. {$endif}
  426. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  427. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  428. valid_for_var(tinlinenode(right).left,false) and
  429. not(might_have_sideeffects(tinlinenode(right).left)) then
  430. begin
  431. case tinlinenode(right).inlinenumber of
  432. in_sar_x:
  433. newinlinenodetype:=in_sar_assign_x_y;
  434. in_rol_x:
  435. newinlinenodetype:=in_rol_assign_x_y;
  436. in_ror_x:
  437. newinlinenodetype:=in_ror_assign_x_y;
  438. else
  439. internalerror(2017071701);
  440. end;
  441. result:=cinlinenode.createintern(
  442. newinlinenodetype,false,ccallparanode.create(
  443. cordconstnode.create(1,u8inttype,false),ccallparanode.create(tinlinenode(right).left,nil)));
  444. result.localswitches:=localswitches;
  445. result.fileinfo:=fileinfo;
  446. result.verbosity:=verbosity;
  447. tinlinenode(right).left:=nil;
  448. exit;
  449. end;
  450. { replace i:=sar(i) by in_sar_assign_x_y(i,1)
  451. i:=rol(i) by in_rol_assign_x_y(i,1)
  452. i:=ror(i) by in_ror_assign_x_y(i,1)
  453. this handles the case with type conversions:
  454. outer typeconv: right
  455. sar/rol/ror inline node: ttypeconvnode(right).left
  456. inner typeconv: tinlinenode(ttypeconvnode(right).left).left
  457. right side 'i': ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left }
  458. if (right.nodetype=typeconvn) and
  459. (ttypeconvnode(right).convtype=tc_int_2_int) and
  460. (ttypeconvnode(right).left.nodetype=inlinen) and
  461. (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
  462. {$ifdef enable_sar_assign_x_y}
  463. in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
  464. {$endif enable_sar_assign_x_y}
  465. {$ifdef enable_rox_assign_x_y}
  466. in_rol_x,in_ror_x
  467. {$endif enable_rox_assign_x_y}
  468. ]) and
  469. is_integer(ttypeconvnode(right).left.resultdef) and
  470. (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
  471. (tinlinenode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  472. (ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  473. are_equal_ints(right.resultdef,ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.resultdef) and
  474. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.isequal(left) and
  475. is_integer(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.resultdef) and
  476. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  477. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  478. valid_for_var(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left,false) and
  479. not(might_have_sideeffects(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left)) then
  480. begin
  481. case tinlinenode(ttypeconvnode(right).left).inlinenumber of
  482. in_sar_x:
  483. newinlinenodetype:=in_sar_assign_x_y;
  484. in_rol_x:
  485. newinlinenodetype:=in_rol_assign_x_y;
  486. in_ror_x:
  487. newinlinenodetype:=in_ror_assign_x_y;
  488. else
  489. internalerror(2017071801);
  490. end;
  491. result:=cinlinenode.createintern(
  492. newinlinenodetype,false,ccallparanode.create(
  493. cordconstnode.create(1,u8inttype,false),ccallparanode.create(
  494. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left,nil)));
  495. result.localswitches:=localswitches;
  496. result.fileinfo:=fileinfo;
  497. result.verbosity:=verbosity;
  498. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
  499. exit;
  500. end;
  501. { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
  502. i:=rol(i,k) by in_rol_assign_x_y(i,k)
  503. i:=ror(i,k) by in_ror_assign_x_y(i,k)
  504. this handles the case, where there are no implicit type conversions }
  505. if (right.nodetype=inlinen) and
  506. (tinlinenode(right).inlinenumber in [
  507. {$ifdef enable_sar_assign_x_y}
  508. in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
  509. {$endif enable_sar_assign_x_y}
  510. {$ifdef enable_rox_assign_x_y}
  511. in_rol_x_y,in_ror_x_y
  512. {$endif enable_rox_assign_x_y}
  513. ]) and
  514. (tinlinenode(right).left.nodetype=callparan) and
  515. tcallparanode(tcallparanode(tinlinenode(right).left).right).left.isequal(left) and
  516. is_integer(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef) and
  517. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  518. not(is_64bitint(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef)) and
  519. {$endif}
  520. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  521. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  522. valid_for_var(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,false) and
  523. not(might_have_sideeffects(tcallparanode(tcallparanode(tinlinenode(right).left).right).left)) then
  524. begin
  525. case tinlinenode(right).inlinenumber of
  526. in_sar_x_y:
  527. newinlinenodetype:=in_sar_assign_x_y;
  528. in_rol_x_y:
  529. newinlinenodetype:=in_rol_assign_x_y;
  530. in_ror_x_y:
  531. newinlinenodetype:=in_ror_assign_x_y;
  532. else
  533. internalerror(2017071702);
  534. end;
  535. result:=cinlinenode.createintern(
  536. newinlinenodetype,false,ccallparanode.create(
  537. tcallparanode(tinlinenode(right).left).left,
  538. ccallparanode.create(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,nil)));
  539. result.localswitches:=localswitches;
  540. result.fileinfo:=fileinfo;
  541. result.verbosity:=verbosity;
  542. tcallparanode(tinlinenode(right).left).left:=nil;
  543. tcallparanode(tcallparanode(tinlinenode(right).left).right).left:=nil;
  544. exit;
  545. end;
  546. { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
  547. i:=rol(i,k) by in_rol_assign_x_y(i,k)
  548. i:=ror(i,k) by in_ror_assign_x_y(i,k)
  549. this handles the case with two conversions (outer and inner):
  550. outer typeconv: right
  551. sar/rol/ror inline node: ttypeconvnode(right).left
  552. inner typeconv: tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left
  553. right side 'i': ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left
  554. right side 'k': tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left }
  555. if (right.nodetype=typeconvn) and
  556. (ttypeconvnode(right).convtype=tc_int_2_int) and
  557. (ttypeconvnode(right).left.nodetype=inlinen) and
  558. (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
  559. {$ifdef enable_sar_assign_x_y}
  560. in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
  561. {$endif enable_sar_assign_x_y}
  562. {$ifdef enable_rox_assign_x_y}
  563. in_rol_x_y,in_ror_x_y
  564. {$endif enable_rox_assign_x_y}
  565. ]) and
  566. is_integer(ttypeconvnode(right).left.resultdef) and
  567. (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
  568. (tinlinenode(ttypeconvnode(right).left).left.nodetype=callparan) and
  569. (tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left.nodetype=typeconvn) and
  570. (ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).convtype=tc_int_2_int) and
  571. are_equal_ints(right.resultdef,ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.resultdef) and
  572. ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.isequal(left) and
  573. is_integer(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.resultdef) and
  574. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  575. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  576. valid_for_var(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,false) and
  577. not(might_have_sideeffects(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left)) then
  578. begin
  579. case tinlinenode(ttypeconvnode(right).left).inlinenumber of
  580. in_sar_x_y:
  581. newinlinenodetype:=in_sar_assign_x_y;
  582. in_rol_x_y:
  583. newinlinenodetype:=in_rol_assign_x_y;
  584. in_ror_x_y:
  585. newinlinenodetype:=in_ror_assign_x_y;
  586. else
  587. internalerror(2017072002);
  588. end;
  589. result:=cinlinenode.createintern(
  590. newinlinenodetype,false,ccallparanode.create(
  591. tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left,
  592. ccallparanode.create(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,nil)));
  593. result.localswitches:=localswitches;
  594. result.fileinfo:=fileinfo;
  595. result.verbosity:=verbosity;
  596. tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
  597. ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left:=nil;
  598. exit;
  599. end;
  600. {$endif enable_sar_assign_x_y or enable_rox_assign_x_y}
  601. end;
  602. end;
  603. function try_opt_node(var n: tnode; arg: pointer): foreachnoderesult;
  604. var
  605. hn : tnode;
  606. begin
  607. result:=fen_false;
  608. if n.nodetype=assignn then
  609. begin
  610. hn:=try_opt_assignmentnode(tassignmentnode(n));
  611. if assigned(hn) then
  612. begin
  613. n.free;
  614. n:=hn;
  615. typecheckpass(n);
  616. do_firstpass(n);
  617. end;
  618. end;
  619. end;
  620. procedure do_optloadmodifystore(var rootnode : tnode);
  621. begin
  622. foreachnodestatic(pm_postprocess,rootnode,@try_opt_node,nil);
  623. end;
  624. end.