optloadmodifystore.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  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. { replace i:=sar(i) by in_sar_assign_x_y(i,1)
  384. i:=rol(i) by in_rol_assign_x_y(i,1)
  385. i:=ror(i) by in_ror_assign_x_y(i,1)
  386. this handles the case with type conversions:
  387. outer typeconv: right
  388. sar/rol/ror inline node: ttypeconvnode(right).left
  389. inner typeconv: tinlinenode(ttypeconvnode(right).left).left
  390. right side 'i': ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left }
  391. if (right.nodetype=typeconvn) and
  392. (ttypeconvnode(right).convtype=tc_int_2_int) and
  393. (ttypeconvnode(right).left.nodetype=inlinen) and
  394. (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
  395. {$ifdef enable_sar_assign_x_y}
  396. in_sar_x{$ifdef enable_rox_assign_x_y},{$endif}
  397. {$endif enable_sar_assign_x_y}
  398. {$ifdef enable_rox_assign_x_y}
  399. in_rol_x,in_ror_x
  400. {$endif enable_rox_assign_x_y}
  401. ]) and
  402. is_integer(ttypeconvnode(right).left.resultdef) and
  403. (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
  404. (tinlinenode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  405. (ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  406. are_equal_ints(right.resultdef,ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.resultdef) and
  407. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.isequal(left) and
  408. is_integer(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left.resultdef) and
  409. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  410. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  411. valid_for_var(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left,false) and
  412. not(might_have_sideeffects(ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left)) then
  413. begin
  414. case tinlinenode(ttypeconvnode(right).left).inlinenumber of
  415. in_sar_x:
  416. newinlinenodetype:=in_sar_assign_x_y;
  417. in_rol_x:
  418. newinlinenodetype:=in_rol_assign_x_y;
  419. in_ror_x:
  420. newinlinenodetype:=in_ror_assign_x_y;
  421. else
  422. internalerror(2017071801);
  423. end;
  424. result:=cinlinenode.createintern(
  425. newinlinenodetype,false,ccallparanode.create(
  426. cordconstnode.create(1,u8inttype,false),ccallparanode.create(
  427. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left,nil)));
  428. result.localswitches:=localswitches;
  429. result.fileinfo:=fileinfo;
  430. result.verbosity:=verbosity;
  431. ttypeconvnode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
  432. exit;
  433. end;
  434. { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
  435. i:=rol(i,k) by in_rol_assign_x_y(i,k)
  436. i:=ror(i,k) by in_ror_assign_x_y(i,k)
  437. this handles the case, where there are no implicit type conversions }
  438. if (right.nodetype=inlinen) and
  439. (tinlinenode(right).inlinenumber in [
  440. {$ifdef enable_sar_assign_x_y}
  441. in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
  442. {$endif enable_sar_assign_x_y}
  443. {$ifdef enable_rox_assign_x_y}
  444. in_rol_x_y,in_ror_x_y
  445. {$endif enable_rox_assign_x_y}
  446. ]) and
  447. (tinlinenode(right).left.nodetype=callparan) and
  448. tcallparanode(tcallparanode(tinlinenode(right).left).right).left.isequal(left) and
  449. is_integer(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef) and
  450. {$if not defined(cpu64bitalu) and not defined(cpucg64shiftsupport)}
  451. not(is_64bitint(tcallparanode(tcallparanode(tinlinenode(right).left).right).left.resultdef)) and
  452. {$endif}
  453. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  454. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  455. valid_for_var(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,false) and
  456. not(might_have_sideeffects(tcallparanode(tcallparanode(tinlinenode(right).left).right).left)) then
  457. begin
  458. case tinlinenode(right).inlinenumber of
  459. in_sar_x_y:
  460. newinlinenodetype:=in_sar_assign_x_y;
  461. in_rol_x_y:
  462. newinlinenodetype:=in_rol_assign_x_y;
  463. in_ror_x_y:
  464. newinlinenodetype:=in_ror_assign_x_y;
  465. else
  466. internalerror(2017071701);
  467. end;
  468. result:=cinlinenode.createintern(
  469. newinlinenodetype,false,ccallparanode.create(
  470. tcallparanode(tinlinenode(right).left).left,
  471. ccallparanode.create(tcallparanode(tcallparanode(tinlinenode(right).left).right).left,nil)));
  472. result.localswitches:=localswitches;
  473. result.fileinfo:=fileinfo;
  474. result.verbosity:=verbosity;
  475. tcallparanode(tinlinenode(right).left).left:=nil;
  476. tcallparanode(tcallparanode(tinlinenode(right).left).right).left:=nil;
  477. exit;
  478. end;
  479. { replace i:=sar(i,k) by in_sar_assign_x_y(i,k)
  480. i:=rol(i,k) by in_rol_assign_x_y(i,k)
  481. i:=ror(i,k) by in_ror_assign_x_y(i,k)
  482. this handles the case with two conversions (outer and inner):
  483. outer typeconv: right
  484. sar/rol/ror inline node: ttypeconvnode(right).left
  485. inner typeconv: tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left
  486. right side 'i': ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left
  487. right side 'k': tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left }
  488. if (right.nodetype=typeconvn) and
  489. (ttypeconvnode(right).convtype=tc_int_2_int) and
  490. (ttypeconvnode(right).left.nodetype=inlinen) and
  491. (tinlinenode(ttypeconvnode(right).left).inlinenumber in [
  492. {$ifdef enable_sar_assign_x_y}
  493. in_sar_x_y{$ifdef enable_rox_assign_x_y},{$endif}
  494. {$endif enable_sar_assign_x_y}
  495. {$ifdef enable_rox_assign_x_y}
  496. in_rol_x_y,in_ror_x_y
  497. {$endif enable_rox_assign_x_y}
  498. ]) and
  499. is_integer(ttypeconvnode(right).left.resultdef) and
  500. (right.resultdef.size=ttypeconvnode(right).left.resultdef.size) and
  501. (tinlinenode(ttypeconvnode(right).left).left.nodetype=callparan) and
  502. (tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left.nodetype=typeconvn) and
  503. (ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).convtype=tc_int_2_int) and
  504. are_equal_ints(right.resultdef,ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.resultdef) and
  505. ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.isequal(left) and
  506. is_integer(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left.resultdef) and
  507. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  508. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  509. valid_for_var(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,false) and
  510. not(might_have_sideeffects(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left)) then
  511. begin
  512. case tinlinenode(ttypeconvnode(right).left).inlinenumber of
  513. in_sar_x_y:
  514. newinlinenodetype:=in_sar_assign_x_y;
  515. in_rol_x_y:
  516. newinlinenodetype:=in_rol_assign_x_y;
  517. in_ror_x_y:
  518. newinlinenodetype:=in_ror_assign_x_y;
  519. else
  520. internalerror(2017072002);
  521. end;
  522. result:=cinlinenode.createintern(
  523. newinlinenodetype,false,ccallparanode.create(
  524. tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left,
  525. ccallparanode.create(ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left,nil)));
  526. result.localswitches:=localswitches;
  527. result.fileinfo:=fileinfo;
  528. result.verbosity:=verbosity;
  529. tcallparanode(tinlinenode(ttypeconvnode(right).left).left).left:=nil;
  530. ttypeconvnode(tcallparanode(tcallparanode(tinlinenode(ttypeconvnode(right).left).left).right).left).left:=nil;
  531. exit;
  532. end;
  533. {$endif enable_sar_assign_x_y or enable_rox_assign_x_y}
  534. { replace i:=not i by in_not_assign_x(i)
  535. i:=-i by in_neg_assign_x(i)
  536. this handles the case, where there are no implicit type conversions }
  537. if (right.nodetype in [notn,unaryminusn]) and
  538. (tunarynode(right).left.isequal(left)) and
  539. is_integer(tunarynode(right).left.resultdef) and
  540. ((localswitches*[cs_check_overflow,cs_check_range])=[]) and
  541. ((right.localswitches*[cs_check_overflow,cs_check_range])=[]) and
  542. valid_for_var(tunarynode(right).left,false) and
  543. not(might_have_sideeffects(tunarynode(right).left)) then
  544. begin
  545. if right.nodetype=notn then
  546. newinlinenodetype:=in_not_assign_x
  547. else
  548. newinlinenodetype:=in_neg_assign_x;
  549. result:=cinlinenode.createintern(
  550. newinlinenodetype,false,tunarynode(right).left);
  551. result.localswitches:=localswitches;
  552. result.fileinfo:=fileinfo;
  553. result.verbosity:=verbosity;
  554. tunarynode(right).left:=nil;
  555. exit;
  556. end;
  557. { replace i:=not i by in_not_assign_x(i)
  558. i:=-i by in_neg_assign_x(i)
  559. this handles the case with type conversions:
  560. outer typeconv: right
  561. neg/not: ttypeconvnode(right).left
  562. inner typeconv: tunarynode(ttypeconvnode(right).left).left
  563. right side 'i': ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left }
  564. if (right.nodetype=typeconvn) and
  565. (ttypeconvnode(right).convtype=tc_int_2_int) and
  566. (ttypeconvnode(right).left.nodetype in [notn,unaryminusn]) and
  567. is_integer(ttypeconvnode(right).left.resultdef) and
  568. (right.resultdef.size<=ttypeconvnode(right).left.resultdef.size) and
  569. (tunarynode(ttypeconvnode(right).left).left.nodetype=typeconvn) and
  570. (ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).convtype=tc_int_2_int) and
  571. are_equal_ints(right.resultdef,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.resultdef) and
  572. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left.isequal(left) and
  573. is_integer(ttypeconvnode(tunarynode(ttypeconvnode(right).left).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(tunarynode(ttypeconvnode(right).left).left).left,false) and
  577. not(might_have_sideeffects(ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left)) then
  578. begin
  579. if ttypeconvnode(right).left.nodetype=notn then
  580. newinlinenodetype:=in_not_assign_x
  581. else
  582. newinlinenodetype:=in_neg_assign_x;
  583. result:=cinlinenode.createintern(
  584. newinlinenodetype,false,ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left);
  585. result.localswitches:=localswitches;
  586. result.fileinfo:=fileinfo;
  587. result.verbosity:=verbosity;
  588. ttypeconvnode(tunarynode(ttypeconvnode(right).left).left).left:=nil;
  589. exit;
  590. end;
  591. end;
  592. end;
  593. function try_opt_node(var n: tnode; arg: pointer): foreachnoderesult;
  594. var
  595. hn : tnode;
  596. begin
  597. result:=fen_false;
  598. if n.nodetype=assignn then
  599. begin
  600. hn:=try_opt_assignmentnode(tassignmentnode(n));
  601. if assigned(hn) then
  602. begin
  603. n.free;
  604. n:=hn;
  605. typecheckpass(n);
  606. do_firstpass(n);
  607. end;
  608. end;
  609. end;
  610. procedure do_optloadmodifystore(var rootnode : tnode);
  611. begin
  612. foreachnodestatic(pm_postprocess,rootnode,@try_opt_node,nil);
  613. end;
  614. end.