optloadmodifystore.pas 34 KB

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