optloadmodifystore.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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;
  32. procedure do_optloadmodifystore(var rootnode : tnode);
  33. implementation
  34. uses
  35. globtype,verbose,nutils,compinnr,
  36. defutil,defcmp,htypechk,pass_1,constexp,
  37. nadd,ncal,ncon,ncnv,ninl,nld,nmat,
  38. symdef;
  39. function try_opt_assignmentnode(assignmentnode: tassignmentnode): tnode;
  40. var
  41. newinlinenodetype: tinlinenumber;
  42. begin
  43. result:=nil;
  44. with assignmentnode do
  45. begin
  46. { replace i:=succ/pred(i) by inc/dec(i)? }
  47. if (right.nodetype=inlinen) and
  48. ((tinlinenode(right).inlinenumber=in_succ_x) or (tinlinenode(right).inlinenumber=in_pred_x)) and
  49. (tinlinenode(right).left.isequal(left)) and
  50. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  51. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  52. valid_for_var(tinlinenode(right).left,false) and
  53. not(might_have_sideeffects(tinlinenode(right).left)) then
  54. begin
  55. if tinlinenode(right).inlinenumber=in_succ_x then
  56. newinlinenodetype:=in_inc_x
  57. else
  58. newinlinenodetype:=in_dec_x;
  59. result:=cinlinenode.createintern(
  60. newinlinenodetype,false,ccallparanode.create(
  61. tinlinenode(right).left,nil));
  62. result.localswitches:=localswitches;
  63. result.fileinfo:=fileinfo;
  64. result.verbosity:=verbosity;
  65. tinlinenode(right).left:=nil;
  66. exit;
  67. end;
  68. { replace i:=i+k by inc(i,k)
  69. i:=i-k by dec(i,k)
  70. i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k)
  71. this handles the case, where there are no implicit type conversions }
  72. if (right.nodetype in [addn,subn,andn,orn,xorn]) and
  73. (taddnode(right).left.isequal(left)) and
  74. is_integer(taddnode(right).left.resultdef) and
  75. is_integer(taddnode(right).right.resultdef) and
  76. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  77. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  78. valid_for_var(taddnode(right).left,false) and
  79. not(might_have_sideeffects(taddnode(right).left)) then
  80. begin
  81. case right.nodetype of
  82. addn:
  83. newinlinenodetype:=in_inc_x;
  84. subn:
  85. newinlinenodetype:=in_dec_x;
  86. andn:
  87. newinlinenodetype:=in_and_assign_x_y;
  88. orn:
  89. newinlinenodetype:=in_or_assign_x_y;
  90. xorn:
  91. newinlinenodetype:=in_xor_assign_x_y;
  92. else
  93. internalerror(2017032901);
  94. end;
  95. if right.nodetype in [addn,subn] then
  96. result:=cinlinenode.createintern(
  97. newinlinenodetype,false,ccallparanode.create(
  98. taddnode(right).left,ccallparanode.create(taddnode(right).right,nil)))
  99. else
  100. result:=cinlinenode.createintern(
  101. newinlinenodetype,false,ccallparanode.create(
  102. taddnode(right).right,ccallparanode.create(taddnode(right).left,nil)));
  103. result.localswitches:=localswitches;
  104. result.fileinfo:=fileinfo;
  105. result.verbosity:=verbosity;
  106. taddnode(right).left:=nil;
  107. taddnode(right).right:=nil;
  108. exit;
  109. end;
  110. { replace i:=i+k by inc(i,k)
  111. i:=i-k by dec(i,k)
  112. i:=i and/or/xor k by in_[and/or/xor]_assign_x_y(i,k)
  113. this handles the case with two conversions (outer and inner):
  114. outer typeconv: right
  115. add/sub/and/or/xor: ttypeconvnode(right).left
  116. inner typeconv: taddnode(ttypeconvnode(right).left).left
  117. right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left
  118. right side 'k': taddnode(ttypeconvnode(right).left).right }
  119. if (right.nodetype=typeconvn) and
  120. (ttypeconvnode(right).convtype=tc_int_2_int) and
  121. (ttypeconvnode(right).left.nodetype in [addn,subn,andn,orn,xorn]) and
  122. is_integer(ttypeconvnode(right).left.resultdef) and
  123. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  124. (taddnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  125. (ttypeconvnode(taddnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  126. are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and
  127. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.isequal(left) and
  128. is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and
  129. is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and
  130. is_integer(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left.resultdef) and
  131. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  132. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  133. valid_for_var(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,false) and
  134. not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left)) then
  135. begin
  136. case ttypeconvnode(right).left.nodetype of
  137. addn:
  138. newinlinenodetype:=in_inc_x;
  139. subn:
  140. newinlinenodetype:=in_dec_x;
  141. andn:
  142. newinlinenodetype:=in_and_assign_x_y;
  143. orn:
  144. newinlinenodetype:=in_or_assign_x_y;
  145. xorn:
  146. newinlinenodetype:=in_xor_assign_x_y;
  147. else
  148. internalerror(2017032901);
  149. end;
  150. inserttypeconv_internal(taddnode(ttypeconvnode(right).left).right,left.resultdef);
  151. if ttypeconvnode(right).left.nodetype in [addn,subn] then
  152. result:=cinlinenode.createintern(
  153. newinlinenodetype,false,ccallparanode.create(
  154. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).right,nil)))
  155. else
  156. result:=cinlinenode.createintern(
  157. newinlinenodetype,false,ccallparanode.create(
  158. taddnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left,nil)));
  159. result.localswitches:=localswitches;
  160. result.fileinfo:=fileinfo;
  161. result.verbosity:=verbosity;
  162. ttypeconvnode(taddnode(ttypeconvnode(right).left).left).left:=nil;
  163. taddnode(ttypeconvnode(right).left).right:=nil;
  164. exit;
  165. end;
  166. { replace i:=k+i by inc(i,k)
  167. i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k)
  168. this handles the case, where there are no implicit type conversions }
  169. if (right.nodetype in [addn,andn,orn,xorn]) and
  170. (taddnode(right).right.isequal(left)) and
  171. is_integer(taddnode(right).left.resultdef) and
  172. is_integer(taddnode(right).right.resultdef) and
  173. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  174. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  175. valid_for_var(taddnode(right).right,false) and
  176. not(might_have_sideeffects(taddnode(right).right)) then
  177. begin
  178. case right.nodetype of
  179. addn:
  180. newinlinenodetype:=in_inc_x;
  181. andn:
  182. newinlinenodetype:=in_and_assign_x_y;
  183. orn:
  184. newinlinenodetype:=in_or_assign_x_y;
  185. xorn:
  186. newinlinenodetype:=in_xor_assign_x_y;
  187. else
  188. internalerror(2017032902);
  189. end;
  190. if right.nodetype=addn then
  191. result:=cinlinenode.createintern(
  192. newinlinenodetype,false,ccallparanode.create(
  193. taddnode(right).right,ccallparanode.create(taddnode(right).left,nil)))
  194. else
  195. result:=cinlinenode.createintern(
  196. newinlinenodetype,false,ccallparanode.create(
  197. taddnode(right).left,ccallparanode.create(taddnode(right).right,nil)));
  198. result.localswitches:=localswitches;
  199. result.fileinfo:=fileinfo;
  200. result.verbosity:=verbosity;
  201. taddnode(right).right:=nil;
  202. taddnode(right).left:=nil;
  203. exit;
  204. end;
  205. { replace i:=k+i by inc(i,k)
  206. i:=k and/or/xor i by in_[and/or/xor]_assign_x_y(i,k)
  207. this handles the case with two conversions (outer and inner):
  208. outer typeconv: right
  209. add/and/or/xor: ttypeconvnode(right).left
  210. inner typeconv: taddnode(ttypeconvnode(right).left).right
  211. right side 'i': ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left
  212. right side 'k': taddnode(ttypeconvnode(right).left).left }
  213. if (right.nodetype=typeconvn) and
  214. (ttypeconvnode(right).convtype=tc_int_2_int) and
  215. (ttypeconvnode(right).left.nodetype in [addn,andn,orn,xorn]) and
  216. is_integer(ttypeconvnode(right).left.resultdef) and
  217. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  218. (taddnode(ttypeconvnode(right).left).right.nodetype=typeconvn) and
  219. (ttypeconvnode(taddnode(ttypeconvnode(right).left).right).convtype=tc_int_2_int) and
  220. are_equal_ints(right.resultdef,ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.resultdef) and
  221. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.isequal(left) and
  222. is_integer(taddnode(ttypeconvnode(right).left).left.resultdef) and
  223. is_integer(taddnode(ttypeconvnode(right).left).right.resultdef) and
  224. is_integer(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left.resultdef) and
  225. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  226. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  227. valid_for_var(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,false) and
  228. not(might_have_sideeffects(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left)) then
  229. begin
  230. case ttypeconvnode(right).left.nodetype of
  231. addn:
  232. newinlinenodetype:=in_inc_x;
  233. andn:
  234. newinlinenodetype:=in_and_assign_x_y;
  235. orn:
  236. newinlinenodetype:=in_or_assign_x_y;
  237. xorn:
  238. newinlinenodetype:=in_xor_assign_x_y;
  239. else
  240. internalerror(2017051101);
  241. end;
  242. inserttypeconv_internal(taddnode(ttypeconvnode(right).left).left,left.resultdef);
  243. if ttypeconvnode(right).left.nodetype=addn then
  244. result:=cinlinenode.createintern(
  245. newinlinenodetype,false,ccallparanode.create(
  246. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,ccallparanode.create(taddnode(ttypeconvnode(right).left).left,nil)))
  247. else
  248. result:=cinlinenode.createintern(
  249. newinlinenodetype,false,ccallparanode.create(
  250. taddnode(ttypeconvnode(right).left).left,ccallparanode.create(ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left,nil)));
  251. result.localswitches:=localswitches;
  252. result.fileinfo:=fileinfo;
  253. result.verbosity:=verbosity;
  254. ttypeconvnode(taddnode(ttypeconvnode(right).left).right).left:=nil;
  255. taddnode(ttypeconvnode(right).left).left:=nil;
  256. exit;
  257. end;
  258. {$ifdef enable_shl_shr_assign_x_y}
  259. { replace i:=i shl k by in_shl_assign_x_y(i,k)
  260. i:=i shr k by in_shr_assign_x_y(i,k)
  261. this handles the case, where there are no implicit type conversions }
  262. if (right.nodetype in [shln,shrn]) and
  263. (tshlshrnode(right).left.isequal(left)) and
  264. is_integer(tshlshrnode(right).left.resultdef) and
  265. is_integer(tshlshrnode(right).right.resultdef) and
  266. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  267. not(is_64bitint(tshlshrnode(right).left.resultdef)) and
  268. {$endif}
  269. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  270. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  271. valid_for_var(tshlshrnode(right).left,false) and
  272. not(might_have_sideeffects(tshlshrnode(right).left)) then
  273. begin
  274. case right.nodetype of
  275. shln:
  276. newinlinenodetype:=in_shl_assign_x_y;
  277. shrn:
  278. newinlinenodetype:=in_shr_assign_x_y;
  279. else
  280. internalerror(2017051201);
  281. end;
  282. result:=cinlinenode.createintern(
  283. newinlinenodetype,false,ccallparanode.create(
  284. tshlshrnode(right).right,ccallparanode.create(tshlshrnode(right).left,nil)));
  285. result.localswitches:=localswitches;
  286. result.fileinfo:=fileinfo;
  287. result.verbosity:=verbosity;
  288. tshlshrnode(right).left:=nil;
  289. tshlshrnode(right).right:=nil;
  290. exit;
  291. end;
  292. { replace i:=i shl k by in_shl_assign_x_y(i,k)
  293. i:=i shr k by in_shr_assign_x_y(i,k)
  294. this handles the case with two conversions (outer and inner):
  295. outer typeconv: right
  296. shl/shr: ttypeconvnode(right).left
  297. inner typeconv: tshlshrnode(ttypeconvnode(right).left).left
  298. right side 'i': ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left
  299. right side 'k': tshlshrnode(ttypeconvnode(right).left).right }
  300. if (right.nodetype=typeconvn) and
  301. (ttypeconvnode(right).convtype=tc_int_2_int) and
  302. (ttypeconvnode(right).left.nodetype in [shln,shrn]) and
  303. is_integer(ttypeconvnode(right).left.resultdef) and
  304. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  305. not(is_64bitint(ttypeconvnode(right).left.resultdef)) and
  306. {$endif}
  307. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  308. (tshlshrnode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  309. (ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  310. are_equal_ints(right.resultdef,ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.resultdef) and
  311. ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.isequal(left) and
  312. is_integer(tshlshrnode(ttypeconvnode(right).left).left.resultdef) and
  313. is_integer(tshlshrnode(ttypeconvnode(right).left).right.resultdef) and
  314. is_integer(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left.resultdef) and
  315. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  316. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  317. valid_for_var(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left,false) and
  318. not(might_have_sideeffects(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left)) then
  319. begin
  320. case ttypeconvnode(right).left.nodetype of
  321. shln:
  322. newinlinenodetype:=in_shl_assign_x_y;
  323. shrn:
  324. newinlinenodetype:=in_shr_assign_x_y;
  325. else
  326. internalerror(2017051201);
  327. end;
  328. inserttypeconv_internal(tshlshrnode(ttypeconvnode(right).left).right,left.resultdef);
  329. result:=cinlinenode.createintern(
  330. newinlinenodetype,false,ccallparanode.create(
  331. tshlshrnode(ttypeconvnode(right).left).right,ccallparanode.create(ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left,nil)));
  332. result.localswitches:=localswitches;
  333. result.fileinfo:=fileinfo;
  334. result.verbosity:=verbosity;
  335. ttypeconvnode(tshlshrnode(ttypeconvnode(right).left).left).left:=nil;
  336. tshlshrnode(ttypeconvnode(right).left).right:=nil;
  337. exit;
  338. end;
  339. {$endif enable_shl_shr_assign_x_y}
  340. {$if defined(enable_sar_assign_x_y) or defined(enable_rox_assign_x_y)}
  341. { replace i:=sar(i) by in_sar_assign_x_y(i,1)
  342. i:=rol(i) by in_rol_assign_x_y(i,1)
  343. i:=ror(i) by in_ror_assign_x_y(i,1)
  344. this handles the case, where there are no implicit type conversions }
  345. if (right.nodetype=inlinen) and
  346. (tinlinenode(right).inlinenumber in [
  347. {$ifdef enable_sar_assign_x_y}
  348. in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
  349. {$endif enable_sar_assign_x_y}
  350. {$ifdef enable_rox_assign_x_y}
  351. in_rol_x,in_ror_x
  352. {$endif enable_rox_assign_x_y}
  353. ]) and
  354. (tinlinenode(right).left.isequal(left)) and
  355. is_integer(tinlinenode(right).left.resultdef) and
  356. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  357. not(is_64bitint(tinlinenode(right).left.resultdef)) and
  358. {$endif}
  359. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  360. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  361. valid_for_var(tinlinenode(right).left,false) and
  362. not(might_have_sideeffects(tinlinenode(right).left)) then
  363. begin
  364. case tinlinenode(right).inlinenumber of
  365. in_sar_x:
  366. newinlinenodetype:=in_sar_assign_x_y;
  367. in_rol_x:
  368. newinlinenodetype:=in_rol_assign_x_y;
  369. in_ror_x:
  370. newinlinenodetype:=in_ror_assign_x_y;
  371. else
  372. internalerror(2017071701);
  373. end;
  374. result:=cinlinenode.createintern(
  375. newinlinenodetype,false,ccallparanode.create(
  376. cordconstnode.create(1,u8inttype,false),ccallparanode.create(tinlinenode(right).left,nil)));
  377. result.localswitches:=localswitches;
  378. result.fileinfo:=fileinfo;
  379. result.verbosity:=verbosity;
  380. tinlinenode(right).left:=nil;
  381. exit;
  382. end;
  383. {$endif enable_sar_assign_x_y or enable_rox_assign_x_y}
  384. { replace i:=not i by in_not_assign_x(i)
  385. i:=-i by in_neg_assign_x(i)
  386. this handles the case, where there are no implicit type conversions }
  387. if (right.nodetype in [notn,unaryminusn]) and
  388. (tunarynode(right).left.isequal(left)) and
  389. is_integer(tunarynode(right).left.resultdef) and
  390. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  391. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  392. valid_for_var(tunarynode(right).left,false) and
  393. not(might_have_sideeffects(tunarynode(right).left)) then
  394. begin
  395. if right.nodetype=notn then
  396. newinlinenodetype:=in_not_assign_x
  397. else
  398. newinlinenodetype:=in_neg_assign_x;
  399. result:=cinlinenode.createintern(
  400. newinlinenodetype,false,tunarynode(right).left);
  401. result.localswitches:=localswitches;
  402. result.fileinfo:=fileinfo;
  403. result.verbosity:=verbosity;
  404. tunarynode(right).left:=nil;
  405. exit;
  406. end;
  407. { replace i:=not i by in_not_assign_x(i)
  408. i:=-i by in_neg_assign_x(i)
  409. this handles the case with type conversions:
  410. outer typeconv: right
  411. neg/not: ttypeconvnode(right).left
  412. inner typeconv: tunarynode(ttypeconvnode(right).left).left
  413. right side 'i': ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left }
  414. if (right.nodetype=typeconvn) and
  415. (ttypeconvnode(right).convtype=tc_int_2_int) and
  416. (ttypeconvnode(right).left.nodetype in [notn,unaryminusn]) and
  417. is_integer(ttypeconvnode(right).left.resultdef) and
  418. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  419. (tunarynode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  420. (ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  421. are_equal_ints(right.resultdef,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
  422. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.isequal(left) and
  423. is_integer(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
  424. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  425. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  426. valid_for_var(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left,false) and
  427. not(might_have_sideeffects(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left)) then
  428. begin
  429. if ttypeconvnode(right).left.nodetype=notn then
  430. newinlinenodetype:=in_not_assign_x
  431. else
  432. newinlinenodetype:=in_neg_assign_x;
  433. result:=cinlinenode.createintern(
  434. newinlinenodetype,false,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left);
  435. result.localswitches:=localswitches;
  436. result.fileinfo:=fileinfo;
  437. result.verbosity:=verbosity;
  438. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil;
  439. exit;
  440. end;
  441. end;
  442. end;
  443. function try_opt_node(var n: tnode; arg: pointer): foreachnoderesult;
  444. var
  445. hn : tnode;
  446. begin
  447. result:=fen_false;
  448. if n.nodetype=assignn then
  449. begin
  450. hn:=try_opt_assignmentnode(tassignmentnode(n));
  451. if assigned(hn) then
  452. begin
  453. n.free;
  454. n:=hn;
  455. typecheckpass(n);
  456. do_firstpass(n);
  457. end;
  458. end;
  459. end;
  460. procedure do_optloadmodifystore(var rootnode : tnode);
  461. begin
  462. foreachnodestatic(pm_postprocess,rootnode,@try_opt_node,nil);
  463. end;
  464. end.