csopt386.pas 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  4. development team
  5. This unit contains the common subexpression elimination procedure.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit CSOpt386;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses aasmbase,aasmtai,aasmcpu, cpuinfo, cpubase, optbase, cgbase;
  23. function CSE(asml: TAAsmoutput; first, last: tai; pass: longint): boolean;
  24. function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
  25. function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
  26. function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
  27. function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
  28. function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
  29. implementation
  30. uses
  31. {$ifdef csdebug}
  32. cutils,
  33. {$else}
  34. {$ifdef replaceregdebug}cutils,{$endif}
  35. {$endif}
  36. globtype, verbose, procinfo, globals, daopt386, rgobj, rropt386,cgutils;
  37. {
  38. function TaiInSequence(P: tai; Const Seq: TContent): Boolean;
  39. var P1: tai;
  40. Counter: Byte;
  41. TmpResult: Boolean;
  42. begin
  43. TmpResult := False;
  44. P1 := Seq.StartMod;
  45. Counter := 1;
  46. while not(TmpResult) and
  47. (Counter <= Seq.NrofMods) do
  48. begin
  49. if (P = P1) then TmpResult := True;
  50. inc(Counter);
  51. p1 := tai(p1.Next);
  52. end;
  53. TaiInSequence := TmpResult;
  54. end;
  55. }
  56. function modifiesConflictingMemLocation(p1: tai; supreg: tsuperregister; c: tregContent;
  57. var regsStillValid: tregset; onlymem: boolean; var invalsmemwrite: boolean): boolean;
  58. var
  59. p, hp: taicpu;
  60. tmpRef: treference;
  61. r,regCounter: tsuperregister;
  62. opCount: byte;
  63. dummy: boolean;
  64. begin
  65. modifiesConflictingMemLocation := false;
  66. invalsmemwrite := false;
  67. if p1.typ <> ait_instruction then
  68. exit;
  69. p := taicpu(p1);
  70. case p.opcode of
  71. A_MOV,A_MOVSX,A_MOVZX:
  72. if p.oper[1]^.typ = top_ref then
  73. for regCounter := RS_EAX to RS_EDI do
  74. begin
  75. if p.oper[0]^.typ<>top_reg then
  76. break;
  77. if writeToMemDestroysContents(getsupreg(p.oper[0]^.reg),p.oper[1]^.ref^,
  78. regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  79. begin
  80. exclude(regsStillValid,regCounter);
  81. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  82. end;
  83. if (regcounter = supreg) then
  84. invalsmemwrite := invalsmemwrite or dummy;
  85. end
  86. else
  87. { if is_reg_var[getsupreg(p.oper[1]^.reg)] then }
  88. if not onlymem then
  89. for regCounter := RS_EAX to RS_EDI do
  90. begin
  91. if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  92. begin
  93. exclude(regsStillValid,regCounter);
  94. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  95. end
  96. end;
  97. A_DIV, A_IDIV, A_MUL, A_IMUL:
  98. begin
  99. if not onlymem then
  100. if (p.ops = 1) then
  101. begin
  102. for regCounter := RS_EAX to RS_EDI do
  103. begin
  104. if writeToRegDestroysContents(RS_EDX,regCounter,c[regCounter]) then
  105. begin
  106. exclude(regsStillValid,RS_EDX);
  107. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  108. end;
  109. if writeToRegDestroysContents(RS_EAX,regCounter,c[regCounter]) then
  110. begin
  111. exclude(regsStillValid,RS_EAX);
  112. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  113. end;
  114. end
  115. end
  116. else
  117. { only possible for imul }
  118. { last operand is always destination }
  119. for regCounter := RS_EAX to RS_EDI do
  120. begin
  121. if writeDestroysContents(p.oper[p.ops-1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  122. begin
  123. exclude(regsStillValid,regCounter);
  124. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  125. end
  126. end
  127. end;
  128. else
  129. for opCount := 1 to maxinschanges do
  130. case InsProp[p.opcode].Ch[opCount] of
  131. Ch_MOp1,CH_WOp1,CH_RWOp1:
  132. if not(onlymem) or
  133. (p.oper[0]^.typ = top_ref) then
  134. { or ((p.oper[0]^.typ = top_reg) and }
  135. { is_reg_var[getsupreg(p.oper[0]^.reg)]) then }
  136. for regCounter := RS_EAX to RS_EDI do
  137. begin
  138. if writeDestroysContents(p.oper[0]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  139. begin
  140. exclude(regsStillValid,regCounter);
  141. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  142. end;
  143. if (regcounter = supreg) then
  144. invalsmemwrite := invalsmemwrite or dummy;
  145. end;
  146. Ch_MOp2,CH_WOp2,CH_RWOp2:
  147. if not(onlymem) or
  148. (p.oper[1]^.typ = top_ref) then
  149. { or ((p.oper[1]^.typ = top_reg) and }
  150. { is_reg_var[getsupreg(p.oper[1]^.reg)]) then }
  151. for regCounter := RS_EAX to RS_EDI do
  152. begin
  153. if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  154. begin
  155. exclude(regsStillValid,regCounter);
  156. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  157. end;
  158. if (regcounter = supreg) then
  159. invalsmemwrite := invalsmemwrite or dummy;
  160. end;
  161. Ch_MOp3,CH_WOp3,CH_RWOp3:
  162. if not(onlymem) or
  163. (p.oper[2]^.typ = top_ref) then
  164. { or ((p.oper[2]^.typ = top_reg) and }
  165. { is_reg_var[getsupreg(p.oper[2]^.reg)]) then }
  166. for regCounter := RS_EAX to RS_EDI do
  167. begin
  168. if writeDestroysContents(p.oper[2]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  169. begin
  170. exclude(regsStillValid,regCounter);
  171. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  172. end;
  173. if (regcounter = supreg) then
  174. invalsmemwrite := invalsmemwrite or dummy;
  175. end;
  176. Ch_WMemEDI:
  177. begin
  178. fillchar(tmpref,sizeof(tmpref),0);
  179. tmpRef.base := NR_EDI;
  180. tmpRef.index := NR_EDI;
  181. for regCounter := RS_EAX to RS_EDI do
  182. if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,OS_32,c[regCounter],dummy) then
  183. begin
  184. exclude(regsStillValid,regCounter);
  185. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  186. end;
  187. if (regcounter = supreg) then
  188. invalsmemwrite := invalsmemwrite or dummy;
  189. end;
  190. end;
  191. end;
  192. end;
  193. function isSimpleMemLoc(const ref: treference): boolean;
  194. begin
  195. { isSimpleMemLoc :=
  196. (ref.index = RS_NO) and
  197. not(ref.base in (rg.usableregsint+[RS_EDI]));}
  198. isSimpleMemLoc :=
  199. (ref.index = NR_NO) and
  200. ((ref.base = NR_NO) or
  201. not(getsupreg(ref.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]));
  202. end;
  203. {checks whether the current instruction sequence (starting with p) and the
  204. one between StartMod and EndMod of Reg are the same. if so, the number of
  205. instructions that match is stored in Found and true is returned, otherwise
  206. Found holds the number of instructions between StartMod and EndMod and false
  207. is returned}
  208. function CheckSequence(p: tai; var prev: tai; supreg: tsuperregister; var Found: Longint;
  209. var reginfo: toptreginfo; findPrevSeqs: boolean): Boolean;
  210. var
  211. regsNotRead, regsStillValid : tregset;
  212. checkingPrevSequences,
  213. passedFlagsModifyingInstr,
  214. invalsmemwrite : boolean;
  215. function getPrevSequence(p: tai; supreg: tsuperregister; currentPrev: tai; var newPrev: tai): tsuperregister;
  216. const
  217. current_reg: tsuperregister = RS_INVALID;
  218. function stillValid(p: tai): boolean;
  219. var
  220. hp: tai;
  221. begin
  222. stillValid :=
  223. (p.typ = ait_instruction) and
  224. (taicpu(p).opcode <> a_jmp) and
  225. (ptaiprop(p.optinfo)^.regs[supreg].wstate =
  226. ptaiprop(currentPrev.optinfo)^.regs[supreg].wstate) and
  227. { in case destroyreg is called with doIncState = false }
  228. (ptaiprop(p.optinfo)^.regs[supreg].typ =
  229. ptaiprop(currentPrev.optinfo)^.regs[supreg].typ) and
  230. (supreg in (regsNotRead * regsStillValid));
  231. { stop if the register was still used right before a (conditional) }
  232. { jump, since in that case its current contents could still be }
  233. { used in the other path of the jump) }
  234. if (p.typ = ait_instruction) and
  235. (taicpu(p).is_jmp) and
  236. getlastinstruction(p,hp) then
  237. stillValid := stillValid and
  238. not(supreg in ptaiprop(hp.optinfo)^.usedregs);
  239. passedFlagsModifyingInstr := passedFlagsModifyingInstr or
  240. instrWritesFlags(currentPrev);
  241. end;
  242. function findChangedRegister(p: tai): tsuperregister;
  243. var
  244. regCounter, loopstart: tsuperregister;
  245. begin
  246. if (current_reg <> RS_INVALID) then
  247. loopstart := succ(current_reg)
  248. else
  249. loopstart := RS_EAX;
  250. for regCounter := loopstart to RS_EDI do
  251. with ptaiprop(p.optinfo)^.regs[regCounter] do
  252. if ((startmod <>
  253. ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
  254. (nrofMods <>
  255. ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
  256. (ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then
  257. begin
  258. findChangedRegister := regCounter;
  259. current_reg := regCounter;
  260. exit;
  261. end;
  262. current_reg := RS_INVALID;
  263. findChangedRegister := RS_INVALID;
  264. end;
  265. var
  266. hp, prevFound: tai;
  267. tmpResult, regCounter: tsuperregister;
  268. invalsmemwrite: boolean;
  269. begin
  270. if (current_reg <> RS_EDI) and
  271. (current_reg <> RS_INVALID) then
  272. begin
  273. tmpResult := findChangedRegister(currentPrev);
  274. if tmpResult <> RS_INVALID then
  275. begin
  276. getPrevSequence := tmpResult;
  277. exit;
  278. end;
  279. end;
  280. getPrevSequence := RS_INVALID;
  281. passedFlagsModifyingInstr := passedFlagsModifyingInstr or
  282. instrWritesFlags(currentPrev);
  283. if not getLastInstruction(currentPrev,hp) then
  284. exit;
  285. prevFound := currentPrev;
  286. tmpResult := RS_INVALID;
  287. while (tmpResult = RS_INVALID) and
  288. stillValid(hp) and
  289. (ptaiprop(prevFound.optinfo)^.canBeRemoved or
  290. not(modifiesConflictingMemLocation(prevFound,supreg,
  291. ptaiprop(p.optinfo)^.regs,regsStillValid,false, invalsmemwrite))) do
  292. begin
  293. { only update the regsread for the instructions we already passed }
  294. if not(ptaiprop(prevFound.optinfo)^.canBeRemoved) then
  295. for regCounter := RS_EAX to RS_EDI do
  296. if regReadByInstruction(regCounter,prevFound) then
  297. exclude(regsNotRead,regCounter);
  298. { in case getPreviousInstruction fails and sets hp to nil in the }
  299. { next iteration }
  300. prevFound := hp;
  301. if not(ptaiprop(hp.optinfo)^.canBeRemoved) then
  302. tmpResult := findChangedRegister(hp);
  303. if not getLastInstruction(hp,hp) then
  304. break;
  305. end;
  306. getPrevSequence := tmpResult;
  307. if tmpResult <> RS_INVALID then
  308. newPrev := prevFound;
  309. end;
  310. function getNextRegToTest(var prev: tai; currentReg: tsuperregister): tsuperregister;
  311. begin
  312. if not checkingPrevSequences then
  313. begin
  314. if (currentreg = RS_INVALID) then
  315. currentreg := RS_EAX
  316. else
  317. inc(currentreg);
  318. while (currentReg <= RS_EDI) and
  319. not(ptaiprop(prev.optinfo)^.regs[currentReg].typ in [con_ref,con_noRemoveRef]) do
  320. inc(currentReg);
  321. if currentReg > RS_EDI then
  322. begin
  323. if (taicpu(p).oper[0]^.typ <> top_ref) or
  324. isSimpleMemLoc(taicpu(p).oper[0]^.ref^) then
  325. begin
  326. checkingPrevSequences := true;
  327. end
  328. else
  329. getNextRegToTest := RS_INVALID;
  330. end
  331. else
  332. getNextRegToTest := currentReg;
  333. end;
  334. if checkingPrevSequences then
  335. if findPrevSeqs then
  336. getNextRegToTest :=
  337. getPrevSequence(p,supreg,prev,prev)
  338. else
  339. getNextRegToTest := RS_INVALID;
  340. end;
  341. function changedreginvalidatedbetween(const oldreginfo: toptreginfo; var newreginfo: toptreginfo; startp,endp,current: tai): boolean;
  342. var
  343. orgdiffregs,diffregs: tregset;
  344. runner: tai;
  345. invalsmemwrite: boolean;
  346. begin
  347. diffregs := newreginfo.newregsencountered - oldreginfo.newregsencountered;
  348. orgdiffregs := diffregs;
  349. if diffregs <> [] then
  350. begin
  351. runner := startp;
  352. repeat
  353. modifiesConflictingMemLocation(runner,RS_EAX { dummy },ptaiprop(current.optinfo)^.regs,diffregs,true,invalsmemwrite);
  354. if orgdiffregs <> diffregs then
  355. begin
  356. changedreginvalidatedbetween := true;
  357. newreginfo := oldreginfo;
  358. exit;
  359. end;
  360. getnextinstruction(runner,runner);
  361. until (runner = endp);
  362. end;
  363. changedreginvalidatedbetween := false;
  364. end;
  365. var
  366. prevreginfo: toptreginfo;
  367. hp2, hp3{, EndMod},highPrev, orgPrev: tai;
  368. {Cnt,} OldNrofMods: Longint;
  369. startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo;
  370. regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean;
  371. HighFound, OrgRegFound: longint;
  372. regcounter, regCounter2, tmpreg, base, index: tsuperregister;
  373. OrgRegResult: Boolean;
  374. TmpResult, flagResultsNeeded, stopchecking: Boolean;
  375. begin {CheckSequence}
  376. TmpResult := False;
  377. FillChar(OrgRegInfo, Sizeof(OrgRegInfo), 0);
  378. FillChar(startRegInfo, sizeof(startRegInfo), 0);
  379. OrgRegFound := 0;
  380. HighFound := 0;
  381. OrgRegResult := False;
  382. with startRegInfo do
  383. begin
  384. newRegsEncountered := [RS_EBP, RS_ESP];
  385. fillword(new2oldreg,sizeof(new2oldreg),RS_INVALID);
  386. new2OldReg[RS_EBP] := RS_EBP;
  387. new2OldReg[RS_ESP] := RS_ESP;
  388. oldRegsEncountered := newRegsEncountered;
  389. end;
  390. checkingPrevSequences := false;
  391. passedFlagsModifyingInstr := false;
  392. flagResultsNeeded := false;
  393. regsNotRead := [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESP,RS_EBP,RS_EDI,RS_ESI];
  394. regsStillValid := regsNotRead;
  395. GetLastInstruction(p, prev);
  396. tmpreg:=RS_INVALID;
  397. regCounter := getNextRegToTest(prev,tmpreg);
  398. while (regcounter <> RS_INVALID) do
  399. begin
  400. fillchar(regModified,sizeof(regModified),0);
  401. fillchar(lastregloadremoved,sizeof(lastregloadremoved),0);
  402. reginfo := startRegInfo;
  403. Found := 0;
  404. hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod;
  405. if (prev <> ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod) then
  406. OldNrofMods := ptaiprop(prev.optinfo)^.Regs[regcounter].NrofMods
  407. else
  408. OldNrofMods := 1;
  409. hp3 := p;
  410. if checkingprevsequences then
  411. prevreginfo := reginfo;
  412. stopchecking := false;
  413. while (Found <> OldNrofMods) and
  414. { old new }
  415. InstructionsEquivalent(hp2, hp3, reginfo) and
  416. (not(checkingprevsequences) or
  417. not(changedreginvalidatedbetween(prevreginfo,reginfo,prev,p,hp3))) do
  418. begin
  419. if checkingprevsequences then
  420. begin
  421. prevreginfo := reginfo;
  422. end;
  423. if (hp3.typ = ait_instruction) and
  424. ((taicpu(hp3).opcode = A_MOV) or
  425. (taicpu(hp3).opcode = A_MOVZX) or
  426. (taicpu(hp3).opcode = A_LEA) or
  427. (taicpu(hp3).opcode = A_MOVSX)) and
  428. (taicpu(hp3).oper[1]^.typ = top_reg) and
  429. not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then
  430. begin
  431. tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg);
  432. lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved;
  433. reginfo.lastReload[tmpreg] := hp3;
  434. case taicpu(hp3).oper[0]^.typ of
  435. top_ref:
  436. begin
  437. base := getsupreg(taicpu(hp3).oper[0]^.ref^.base);
  438. index := getsupreg(taicpu(hp3).oper[0]^.ref^.index);
  439. if (found <> 0) and
  440. ((taicpu(hp3).oper[0]^.ref^.base = NR_NO) or
  441. regModified[base] or
  442. (base = getsupreg(current_procinfo.framepointer))) and
  443. ((taicpu(hp3).oper[0]^.ref^.index = NR_NO) or
  444. regModified[index]) and
  445. not(regInRef(tmpReg,taicpu(hp3).oper[0]^.ref^)) then
  446. begin
  447. with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
  448. if nrofMods > (oldNrofMods - found) then
  449. oldNrofMods := found + nrofMods;
  450. { next is safe because instructions are equivalent }
  451. with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
  452. if nrofMods > (oldNrofMods - found) then
  453. oldNrofMods := found + nrofMods;
  454. end;
  455. end;
  456. top_reg:
  457. if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then
  458. begin
  459. with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
  460. if nrofMods > (oldNrofMods - found) then
  461. oldNrofMods := found + nrofMods;
  462. with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
  463. if nrofMods > (oldNrofMods - found) then
  464. oldNrofMods := found + nrofMods;
  465. end;
  466. end;
  467. end;
  468. for regCounter2 := RS_EAX to RS_EDI do
  469. regModified[regCounter2] := regModified[regCounter2] or
  470. regModifiedByInstruction(regCounter2,hp3);
  471. if flagResultsNeeded then
  472. flagResultsNeeded := not instrReadsFlags(hp3);
  473. if not flagResultsNeeded then
  474. flagResultsNeeded := ptaiprop(hp3.optinfo)^.FlagsUsed;
  475. GetNextInstruction(hp2, hp2);
  476. GetNextInstruction(hp3, hp3);
  477. inc(Found);
  478. end;
  479. for regCounter2 := RS_EAX to RS_EDI do
  480. if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
  481. (regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
  482. not regLoadedWithNewValue(regCounter2,false,hp3) and
  483. lastregloadremoved[regcounter2] then
  484. found := 0;
  485. if checkingPrevSequences then
  486. begin
  487. for regCounter2 := RS_EAX to RS_EDI do
  488. if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
  489. (reginfo.new2OldReg[regCounter2] <> regCounter2) and
  490. (not(regCounter2 in (regsNotRead * regsStillValid)) or
  491. not(reginfo.new2OldReg[regCounter2] in regsStillValid)) then
  492. begin
  493. found := 0;
  494. break;
  495. end;
  496. if passedFlagsModifyingInstr and flagResultsNeeded then
  497. found := 0;
  498. end;
  499. TmpResult := true;
  500. if (found <> OldNrofMods) then
  501. TmpResult := false
  502. else if assigned(hp3) then
  503. for regcounter2 := RS_EAX to RS_EDI do
  504. if (regcounter2 in reginfo.regsLoadedforRef) and
  505. (regcounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
  506. not regLoadedWithNewValue(regcounter2,false,hp3) then
  507. begin
  508. TmpResult := False;
  509. if (found > 0) then
  510. {this is correct because we only need to turn off the CanBeRemoved flag
  511. when an instruction has already been processed by CheckSequence
  512. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  513. if it has already been processed by CheckSequence and flagged to be
  514. removed, it means that it has been checked against a previous sequence
  515. and that it was equal (otherwise CheckSequence would have returned false
  516. and the instruction wouldn't have been removed). if this "if found > 0"
  517. check is left out, incorrect optimizations are performed.}
  518. Found := ptaiprop(tai(p).optinfo)^.Regs[supreg].NrofMods;
  519. break;
  520. end;
  521. if TmpResult and
  522. (Found > HighFound) then
  523. begin
  524. highPrev := prev;
  525. HighFound := Found;
  526. HighRegInfo := reginfo;
  527. end;
  528. if (regcounter = supreg) then
  529. begin
  530. orgPrev := prev;
  531. OrgRegFound := Found;
  532. OrgRegResult := TmpResult;
  533. OrgRegInfo := reginfo
  534. end;
  535. regCounter := getNextRegToTest(prev,regCounter);
  536. end;
  537. if (HighFound > 0) and
  538. (not(OrgRegResult) Or
  539. (HighFound > OrgRegFound))
  540. then
  541. begin
  542. {$ifndef fpc}
  543. TmpResult := True;
  544. {$else fpc}
  545. CheckSequence := True;
  546. {$endif fpc}
  547. prev := highPrev;
  548. reginfo := HighRegInfo;
  549. Found := HighFound
  550. end
  551. else
  552. begin
  553. {$ifndef fpc}
  554. TmpResult := OrgRegResult;
  555. {$else fpc}
  556. CheckSequence := OrgRegResult;
  557. {$endif fpc}
  558. prev := orgPrev;
  559. Found := OrgRegFound;
  560. reginfo := OrgRegInfo;
  561. end;
  562. {$ifndef fpc}
  563. CheckSequence := TmpResult;
  564. {$endif fpc}
  565. end; {CheckSequence}
  566. procedure SetAlignReg(p: tai);
  567. Const alignSearch = 12;
  568. var regsUsable: TRegSet;
  569. prevInstrCount, nextInstrCount: Longint;
  570. prevState, nextWState,nextRState: Array[RS_EAX..RS_EDI] of byte;
  571. regCounter, lastRemoved: tsuperregister;
  572. prev, next: tai;
  573. {$ifdef alignregdebug}
  574. temp: tai;
  575. {$endif alignregdebug}
  576. begin
  577. regsUsable := [RS_EAX,RS_ECX,RS_EDX,RS_EBX,{R_ESP,RS_EBP,}RS_ESI,RS_EDI];
  578. for regCounter := RS_EAX to RS_EDI do
  579. begin
  580. prevState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
  581. nextWState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
  582. nextRState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].rState;
  583. end;
  584. getLastInstruction(p,prev);
  585. getNextInstruction(p,next);
  586. lastRemoved := getsupreg(tai_align(p).reg);
  587. nextInstrCount := 0;
  588. prevInstrCount := 0;
  589. while ((assigned(prev) and
  590. assigned(prev.optinfo) and
  591. (prevInstrCount < alignSearch)) or
  592. (assigned(next) and
  593. assigned(next.optinfo) and
  594. (nextInstrCount < alignSearch))) and
  595. (regsUsable <> []) do
  596. begin
  597. {$ifdef alignregdebug}
  598. if assigned(prev) then
  599. begin
  600. temp := tai_comment.Create(strpnew('got here'));
  601. temp.next := prev.next;
  602. temp.previous := prev;
  603. prev.next := temp;
  604. if assigned(temp.next) then
  605. temp.next.previous := temp;
  606. end;
  607. {$endif alignregdebug}
  608. if assigned(prev) and assigned(prev.optinfo) and
  609. (prevInstrCount < alignSearch) then
  610. begin
  611. if (prev.typ = ait_instruction) and
  612. (insProp[taicpu(prev).opcode].ch[1] <> Ch_ALL) and
  613. (taicpu(prev).opcode <> A_JMP) then
  614. begin
  615. inc(prevInstrCount);
  616. for regCounter := RS_EAX to RS_EDI do
  617. begin
  618. if (regCounter in regsUsable) and
  619. (ptaiprop(prev.optinfo)^.Regs[regCounter].wState <>
  620. prevState[regCounter]) then
  621. begin
  622. lastRemoved := regCounter;
  623. exclude(regsUsable,regCounter);
  624. {$ifdef alignregdebug}
  625. temp := tai_comment.Create(strpnew(
  626. std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
  627. temp.next := prev.next;
  628. temp.previous := prev;
  629. prev.next := temp;
  630. if assigned(temp.next) then
  631. temp.next.previous := temp;
  632. if regsUsable = [] then
  633. begin
  634. temp := tai_comment.Create(strpnew(
  635. 'regsUsable empty here')));
  636. temp.next := prev.next;
  637. temp.previous := prev;
  638. prev.next := temp;
  639. if assigned(temp.next) then
  640. temp.next.previous := temp;
  641. end;
  642. {$endif alignregdebug}
  643. end;
  644. prevState[regCounter] :=
  645. ptaiprop(prev.optinfo)^.Regs[regCounter].wState;
  646. end;
  647. getLastInstruction(prev,prev);
  648. end
  649. else
  650. if GetLastInstruction(prev,prev) and
  651. assigned(prev.optinfo) then
  652. for regCounter := RS_EAX to RS_EDI do
  653. prevState[regCounter] :=
  654. ptaiprop(prev.optinfo)^.Regs[regCounter].wState
  655. end;
  656. if assigned(next) and assigned(next.optinfo) and
  657. (nextInstrCount < alignSearch) then
  658. begin
  659. if (next.typ = ait_instruction) and
  660. (insProp[taicpu(next).opcode].ch[1] <> Ch_ALL) and
  661. (taicpu(next).opcode <> A_JMP) then
  662. begin
  663. inc(nextInstrCount);
  664. for regCounter := RS_EAX to RS_EDI do
  665. begin
  666. if (regCounter in regsUsable) and
  667. ((ptaiprop(next.optinfo)^.Regs[regCounter].wState <>
  668. nextWState[regCounter]) or
  669. (ptaiprop(next.optinfo)^.Regs[regCounter].rState <>
  670. nextRState[regCounter])) then
  671. begin
  672. lastRemoved := regCounter;
  673. exclude(regsUsable,regCounter);
  674. {$ifdef alignregdebug}
  675. temp := tai_comment.Create(strpnew(
  676. std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
  677. temp.next := next.next;
  678. temp.previous := next;
  679. next.next := temp;
  680. if assigned(temp.next) then
  681. temp.next.previous := temp;
  682. if regsUsable = [] then
  683. begin
  684. temp := tai_comment.Create(strpnew(
  685. 'regsUsable empty here')));
  686. temp.next := next.next;
  687. temp.previous := next;
  688. next.next := temp;
  689. if assigned(temp.next) then
  690. temp.next.previous := temp;
  691. end;
  692. {$endif alignregdebug}
  693. end;
  694. nextWState[regCounter] :=
  695. ptaiprop(next.optinfo)^.Regs[regCounter].wState;
  696. nextRState[regCounter] :=
  697. ptaiprop(next.optinfo)^.Regs[regCounter].rState;
  698. end
  699. end
  700. else
  701. for regCounter := RS_EAX to RS_EDI do
  702. begin
  703. nextWState[regCounter] :=
  704. ptaiprop(next.optinfo)^.Regs[regCounter].wState;
  705. nextRState[regCounter] :=
  706. ptaiprop(next.optinfo)^.Regs[regCounter].rState;
  707. end;
  708. getNextInstruction(next,next);
  709. end;
  710. end;
  711. if regsUsable <> [] then
  712. for regCounter := RS_EAX to RS_EDI do
  713. if regCounter in regsUsable then
  714. begin
  715. lastRemoved := regCounter;
  716. break
  717. end;
  718. {$ifdef alignregdebug}
  719. next := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,lastremoved,R_SUBWHOLE))+
  720. ' chosen as alignment register')));
  721. next.next := p.next;
  722. next.previous := p;
  723. p.next := next;
  724. if assigned(next.next) then
  725. next.next.previous := next;
  726. {$endif alignregdebug}
  727. tai_align(p).reg := newreg(R_INTREGISTER,lastRemoved,R_SUBWHOLE);
  728. end;
  729. procedure clearmemwrites(p: tai; supreg: tsuperregister);
  730. var
  731. beginmemwrite: tai;
  732. begin
  733. beginmemwrite := ptaiprop(p.optinfo)^.regs[supreg].memwrite;
  734. repeat
  735. ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
  736. until not getnextinstruction(p,p) or
  737. (ptaiprop(p.optinfo)^.regs[supreg].memwrite <> beginmemwrite);
  738. end;
  739. procedure ClearRegContentsFrom(supreg: tsuperregister; p, endP: tai);
  740. { first clears the contents of reg from p till endP. then the contents are }
  741. { cleared until the first instruction that changes reg }
  742. var
  743. {$ifdef replaceregdebug}
  744. hp: tai;
  745. l: longint;
  746. {$endif replaceregdebug}
  747. regcounter: tsuperregister;
  748. oldStartmod: tai;
  749. begin
  750. {$ifdef replaceregdebug}
  751. l := random(1000);
  752. hp := tai_comment.Create(strpnew(
  753. 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' from here... '+tostr(l)));
  754. hp.next := p;
  755. hp.previous := p.previous;
  756. p.previous := hp;
  757. if assigned(hp.previous) then
  758. hp.previous.next := hp;
  759. {$endif replaceregdebug}
  760. ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
  761. while (p <> endP) do
  762. begin
  763. for regcounter := RS_EAX to RS_EDI do
  764. if (regcounter <> supreg) and
  765. assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
  766. reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
  767. clearmemwrites(p,regcounter);
  768. with ptaiprop(p.optinfo)^.Regs[supreg] do
  769. begin
  770. typ := con_unknown;
  771. memwrite := nil;
  772. end;
  773. getNextInstruction(p,p);
  774. end;
  775. oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
  776. repeat
  777. with ptaiprop(p.optinfo)^.Regs[supreg] do
  778. begin
  779. typ := con_unknown;
  780. memwrite := nil;
  781. end;
  782. until not getNextInstruction(p,p) or
  783. (ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
  784. {$ifdef replaceregdebug}
  785. if assigned(p) then
  786. begin
  787. hp := tai_comment.Create(strpnew(
  788. 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
  789. hp.next := p;
  790. hp.previous := p.previous;
  791. p.previous := hp;
  792. if assigned(hp.previous) then
  793. hp.previous.next := hp;
  794. end;
  795. {$endif replaceregdebug}
  796. end;
  797. procedure RestoreRegContentsTo(supreg: tsuperregister; const c: TContent; p, endP: tai);
  798. var
  799. {$ifdef replaceregdebug}
  800. l: longint;
  801. {$endif replaceregdebug}
  802. hp: tai;
  803. dummyregs: tregset;
  804. tmpState, newrstate: byte;
  805. prevcontenttyp: byte;
  806. memconflict: boolean;
  807. invalsmemwrite: boolean;
  808. begin
  809. {$ifdef replaceregdebug}
  810. l := random(1000);
  811. hp := tai_comment.Create(strpnew(
  812. 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' with data from here... '+tostr(l)));
  813. hp.next := p;
  814. hp.previous := p.previous;
  815. p.previous := hp;
  816. if assigned(hp.previous) then
  817. hp.previous.next := hp;
  818. {$endif replaceregdebug}
  819. { ptaiprop(p.optinfo)^.Regs[reg] := c;}
  820. newrstate := c.rstate;
  821. incstate(newrstate,$7f);
  822. while (p <> endP) do
  823. begin
  824. if not(ptaiprop(p.optinfo)^.canberemoved) and
  825. regreadbyinstruction(supreg,p) then
  826. incstate(newrstate,1);
  827. ptaiprop(p.optinfo)^.Regs[supreg] := c;
  828. ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
  829. getNextInstruction(p,p);
  830. end;
  831. tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
  832. if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
  833. begin
  834. incstate(ptaiprop(p.optinfo)^.regs[supreg].rstate,63);
  835. if getnextinstruction(p,hp) and
  836. (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
  837. internalerror(2004122710);
  838. end;
  839. dummyregs := [supreg];
  840. repeat
  841. newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
  842. prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
  843. // is this a write to memory that destroys the contents we are restoring?
  844. memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite);
  845. if not memconflict and not invalsmemwrite then
  846. begin
  847. ptaiprop(p.optinfo)^.Regs[supreg] := c;
  848. ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
  849. end;
  850. until invalsmemwrite or
  851. memconflict or
  852. not getNextInstruction(p,p) or
  853. (ptaiprop(p.optinfo)^.Regs[supreg].wState <> tmpState) or
  854. (p.typ = ait_label) or
  855. ((prevcontenttyp <> con_invalid) and
  856. (ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid));
  857. if assigned(p) and
  858. (p.typ <> ait_marker) then
  859. if ((p.typ = ait_label) or
  860. memconflict or
  861. invalsmemwrite) then
  862. clearRegContentsFrom(supreg,p,p)
  863. else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then
  864. incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20);
  865. {$ifdef replaceregdebug}
  866. if assigned(p) then
  867. begin
  868. hp := tai_comment.Create(strpnew(
  869. 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
  870. hp.next := p;
  871. hp.previous := p.previous;
  872. p.previous := hp;
  873. if assigned(hp.previous) then
  874. hp.previous.next := hp;
  875. end;
  876. {$endif replaceregdebug}
  877. end;
  878. function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
  879. var
  880. chCount: byte;
  881. begin
  882. case p.opcode of
  883. A_IMUL: noHardCodedRegs := p.ops <> 1;
  884. A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
  885. (p.oper[0]^.typ <> top_reg) or
  886. ((orgReg <> RS_ECX) and (newReg <> RS_ECX));
  887. else
  888. begin
  889. NoHardCodedRegs := true;
  890. with InsProp[p.opcode] do
  891. for chCount := 1 to maxinschanges do
  892. if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
  893. begin
  894. NoHardCodedRegs := false;
  895. break
  896. end;
  897. end;
  898. end;
  899. end;
  900. function ChangeReg(var Reg: TRegister; newReg, orgReg: tsuperregister): boolean;
  901. begin
  902. changereg := false;
  903. if (reg <> NR_NO) and
  904. (getregtype(reg) = R_INTREGISTER) and
  905. (getsupreg(reg) = newreg) then
  906. begin
  907. changereg := true;
  908. setsupreg(reg,orgreg);
  909. end;
  910. end;
  911. function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
  912. var
  913. tmpresult: boolean;
  914. begin
  915. changeOp := false;
  916. case o.typ of
  917. top_reg: changeOp := changeReg(o.reg,newReg,orgReg);
  918. top_ref:
  919. begin
  920. tmpresult := changeReg(o.ref^.base,newReg,orgReg);
  921. changeop := changeReg(o.ref^.index,newReg,orgReg) or tmpresult;
  922. end;
  923. end;
  924. end;
  925. procedure updateStates(orgReg,newReg: tsuperregister; hp: tai; writeStateToo: boolean);
  926. var
  927. prev: tai;
  928. newOrgRegRState, newOrgRegWState: byte;
  929. begin
  930. if getLastInstruction(hp,prev) then
  931. with ptaiprop(prev.optinfo)^ do
  932. begin
  933. {$ifopt r+}
  934. {$define rangeon}
  935. {$r-}
  936. {$endif}
  937. newOrgRegRState := regs[orgReg].rState +
  938. ptaiprop(hp.optinfo)^.regs[newReg].rState - regs[newReg].rstate;
  939. if writeStateToo then
  940. newOrgRegWState := regs[orgReg].wState +
  941. ptaiprop(hp.optinfo)^.regs[newReg].wState - regs[newReg].wstate;
  942. {$ifdef rangeon}
  943. {$undef rangeon}
  944. {$r+}
  945. {$endif}
  946. end
  947. else
  948. with ptaiprop(hp.optinfo)^.regs[newReg] do
  949. begin
  950. newOrgRegRState := rState;
  951. if writeStateToo then
  952. newOrgRegWState := wState;
  953. end;
  954. with ptaiprop(hp.optinfo)^.regs[orgReg] do
  955. begin
  956. rState := newOrgRegRState;
  957. if writeStateToo then
  958. wState := newOrgRegwState;
  959. end;
  960. end;
  961. function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
  962. var
  963. opCount: longint;
  964. tmpResult: boolean;
  965. begin
  966. tmpresult := false;
  967. for opCount := 0 to hp.ops-1 do
  968. tmpResult :=
  969. changeOp(hp.oper[opCount]^,newReg,orgReg) or tmpResult;
  970. doReplaceReg := tmpResult;
  971. end;
  972. function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
  973. { oldreg and newreg must be 32bit components }
  974. var
  975. opCount: longint;
  976. tmpreg: tsuperregister;
  977. begin
  978. RegSizesOK := true;
  979. { if only one of them is a general purpose register ... }
  980. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  981. begin
  982. for opCount := 0 to p.ops-1 do
  983. if (p.oper[opCount]^.typ = top_reg) and
  984. (getsubreg(p.oper[opCount]^.reg) in [R_SUBL,R_SUBH]) then
  985. begin
  986. tmpreg := getsupreg(p.oper[opCount]^.reg);
  987. if (tmpreg = oldreg) or
  988. (tmpreg = newreg) then
  989. begin
  990. RegSizesOK := false;
  991. break
  992. end
  993. end;
  994. end;
  995. end;
  996. function doReplaceReadReg(p: taicpu; newReg,orgReg: tsuperregister): boolean;
  997. var
  998. opCount: byte;
  999. begin
  1000. doReplaceReadReg := false;
  1001. { handle special case }
  1002. case p.opcode of
  1003. A_IMUL:
  1004. begin
  1005. case p.ops of
  1006. 1: internalerror(1301001);
  1007. 2,3:
  1008. begin
  1009. if changeOp(p.oper[0]^,newReg,orgReg) then
  1010. begin
  1011. { updateStates(orgReg,newReg,p,false);}
  1012. doReplaceReadReg := true;
  1013. end;
  1014. if p.ops = 3 then
  1015. if changeOp(p.oper[1]^,newReg,orgReg) then
  1016. begin
  1017. { updateStates(orgReg,newReg,p,false);}
  1018. doReplaceReadReg := true;
  1019. end;
  1020. end;
  1021. end;
  1022. end;
  1023. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  1024. else
  1025. begin
  1026. for opCount := 0 to p.ops-1 do
  1027. if p.oper[opCount]^.typ = top_ref then
  1028. if changeOp(p.oper[opCount]^,newReg,orgReg) then
  1029. begin
  1030. { updateStates(orgReg,newReg,p,false);}
  1031. doReplaceReadReg := true;
  1032. end;
  1033. for opCount := 1 to maxinschanges do
  1034. case InsProp[p.opcode].Ch[opCount] of
  1035. Ch_ROp1:
  1036. if p.oper[0]^.typ = top_reg then
  1037. if changeReg(p.oper[0]^.reg,newReg,orgReg) then
  1038. begin
  1039. { updateStates(orgReg,newReg,p,false);}
  1040. doReplaceReadReg := true;
  1041. end;
  1042. Ch_ROp2:
  1043. if p.oper[1]^.typ = top_reg then
  1044. if changeReg(p.oper[1]^.reg,newReg,orgReg) then
  1045. begin
  1046. { updateStates(orgReg,newReg,p,false);}
  1047. doReplaceReadReg := true;
  1048. end;
  1049. Ch_ROp3:
  1050. if p.oper[2]^.typ = top_reg then
  1051. if changeReg(p.oper[2]^.reg,newReg,orgReg) then
  1052. begin
  1053. { updateStates(orgReg,newReg,p,false);}
  1054. doReplaceReadReg := true;
  1055. end;
  1056. end;
  1057. end;
  1058. end;
  1059. end;
  1060. procedure updateState(supreg: tsuperregister; p: tai);
  1061. { this procedure updates the read and write states of the instructions }
  1062. { coming after p. It's called when the read/write state of p has been }
  1063. { changed and this change has to be propagated to the following }
  1064. { instructions as well }
  1065. var
  1066. newRState, newWState: byte;
  1067. prevRState, prevWState: byte;
  1068. doRState, doWState: boolean;
  1069. begin
  1070. { get the new read/write states from p }
  1071. with ptaiprop(p.optinfo)^.regs[supreg] do
  1072. begin
  1073. newRState := rState;
  1074. newWState := wState;
  1075. end;
  1076. if not GetNextInstruction(p,p) then
  1077. exit;
  1078. { get the old read/write states from the next instruction, to know }
  1079. { when we can stop updating }
  1080. with ptaiprop(p.optinfo)^.regs[supreg] do
  1081. begin
  1082. prevRState := rState;
  1083. prevWState := wState;
  1084. end;
  1085. { adjust the states if this next instruction reads/writes the register }
  1086. if regReadByInstruction(supreg,p) then
  1087. incState(newRState,1);
  1088. if regModifiedByInstruction(supreg,p) then
  1089. incState(newWState,1);
  1090. { do we still have to update the read and/or write states? }
  1091. doRState := true;
  1092. doWState := true;
  1093. repeat
  1094. { update the states }
  1095. with ptaiprop(p.optinfo)^.regs[supreg] do
  1096. begin
  1097. if doRState then
  1098. rState := newRState;
  1099. if doWState then
  1100. wState := newWState;
  1101. end;
  1102. if not getNextInstruction(p,p) then
  1103. break;
  1104. with ptaiprop(p.optinfo)^.regs[supreg] do
  1105. begin
  1106. { stop updating the read state if it changes }
  1107. doRState :=
  1108. doRState and (rState = prevRState);
  1109. { if, by accident, this changed state is the same as the one }
  1110. { we've been using, change it to a value that's definitely }
  1111. { different from the previous and next state }
  1112. if not doRState and
  1113. (rState = newRState) then
  1114. begin
  1115. incState(newRState,1);
  1116. prevRState := rState;
  1117. doRState := true;
  1118. end;
  1119. { ditto for the write state }
  1120. doWState :=
  1121. doWState and (WState = prevWState);
  1122. if not doWState and
  1123. (wState = newWState) then
  1124. begin
  1125. incState(newWState,1);
  1126. prevWState := wState;
  1127. doWState := true;
  1128. end;
  1129. end;
  1130. { stop when we don't have to update either state anymore }
  1131. until not(doRState or doWState);
  1132. end;
  1133. function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
  1134. { returns true if p1 contains an instruction that stores the contents }
  1135. { of newReg back to orgReg }
  1136. begin
  1137. storeback := false;
  1138. if (current.typ = ait_instruction) and
  1139. (taicpu(current).opcode = A_MOV) and
  1140. (taicpu(current).oper[0]^.typ = top_reg) and
  1141. (getsupreg(taicpu(current).oper[0]^.reg) = newReg) and
  1142. (taicpu(current).oper[1]^.typ = top_reg) and
  1143. (getsupreg(taicpu(current).oper[1]^.reg) = orgReg) then
  1144. case taicpu(current).opsize of
  1145. S_B:
  1146. storeback := true;
  1147. S_W:
  1148. storeback := taicpu(start).opsize <> S_B;
  1149. S_L:
  1150. storeback := taicpu(start).opsize = S_L;
  1151. else
  1152. internalerror(2003121501);
  1153. end;
  1154. end;
  1155. function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai;
  1156. orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean;
  1157. var
  1158. endP, hp: tai;
  1159. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean;
  1160. begin
  1161. canreplacereg := false;
  1162. tmpResult := true;
  1163. sequenceEnd := false;
  1164. newRegModified := false;
  1165. orgRegRead := false;
  1166. removeLast := false;
  1167. endP := p;
  1168. while tmpResult and not sequenceEnd do
  1169. begin
  1170. tmpResult :=
  1171. getNextInstruction(endP,endP) and
  1172. (endp.typ = ait_instruction) and
  1173. not(taicpu(endp).is_jmp);
  1174. if tmpresult and not assigned(endp.optinfo) then
  1175. begin
  1176. { hp := tai_comment.Create(strpnew('next no optinfo'));
  1177. hp.next := endp;
  1178. hp.previous := endp.previous;
  1179. endp.previous := hp;
  1180. if assigned(hp.previous) then
  1181. hp.previous.next := hp;}
  1182. exit;
  1183. end;
  1184. if tmpResult and
  1185. { don't take into account instructions that will be removed }
  1186. not (ptaiprop(endp.optinfo)^.canBeRemoved) then
  1187. begin
  1188. { if the newsupreg gets stored back to the oldReg, we can change }
  1189. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  1190. { %oldReg" to "<operations on %oldReg>" }
  1191. removeLast := storeBack(p,endP, orgsupreg, newsupreg);
  1192. sequenceEnd :=
  1193. { no support for (i)div, mul and imul with hardcoded operands }
  1194. noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1195. { if newsupreg gets loaded with a new value, we can stop }
  1196. { replacing newsupreg with oldReg here (possibly keeping }
  1197. { the original contents of oldReg so we still know them }
  1198. { afterwards) }
  1199. (RegLoadedWithNewValue(newsupreg,true,taicpu(endP)) or
  1200. { we can also stop if we reached the end of the use of }
  1201. { newReg's current contents }
  1202. (GetNextInstruction(endp,hp) and
  1203. FindRegDealloc(newsupreg,hp)));
  1204. { to be able to remove the first and last instruction of }
  1205. { movl %reg1, %reg2 }
  1206. { <operations on %reg2> (replacing reg2 with reg1 here) }
  1207. { movl %reg2, %reg1 }
  1208. { %reg2 must not be use afterwards (it can be as the }
  1209. { result of a peepholeoptimization) }
  1210. removeLast := removeLast and sequenceEnd;
  1211. newRegModified :=
  1212. newRegModified or
  1213. (not(regLoadedWithNewValue(newsupreg,true,taicpu(endP))) and
  1214. RegModifiedByInstruction(newsupreg,endP));
  1215. orgRegRead := newRegModified and RegReadByInstruction(orgsupreg,endP);
  1216. sequenceEnd := SequenceEnd and
  1217. (removeLast or
  1218. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1219. { gets modified if orgsupreg is still read afterwards (since after }
  1220. { replacing, this would mean that orgsupreg first gets modified and then }
  1221. { gets read in the assumption it still contains the unmodified value) }
  1222. not(newRegModified and orgRegRead)) (* and
  1223. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1224. { gets modified if orgRegCanBeModified = false }
  1225. { this now gets checked after the loop (JM) }
  1226. (orgRegCanBeModified or not(newRegModified)) *);
  1227. tmpResult :=
  1228. not(removeLast) and
  1229. not(newRegModified and orgRegRead) and
  1230. (* (orgRegCanBeModified or not(newRegModified)) and *)
  1231. (* already checked at the top
  1232. (endp.typ = ait_instruction) and *)
  1233. NoHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1234. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1235. not RegModifiedByInstruction(orgsupreg,endP);
  1236. end;
  1237. end;
  1238. canreplacereg := sequenceEnd and
  1239. (removeLast or
  1240. (orgRegCanBeModified or not(newRegModified))) and
  1241. (not(assigned(endp)) or
  1242. not(endp.typ = ait_instruction) or
  1243. (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1244. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1245. not(newRegModified and
  1246. (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
  1247. not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
  1248. if canreplacereg then
  1249. begin
  1250. resnewregmodified := newregmodified;
  1251. resorgregread := orgregread;
  1252. resremovelast := removelast;
  1253. returnendp := endp;
  1254. end;
  1255. end;
  1256. function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p,
  1257. seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
  1258. var returnEndP: tai): Boolean;
  1259. { Tries to replace orgsupreg with newsupreg in all instructions coming after p }
  1260. { until orgsupreg gets loaded with a new value. Returns true if successful, }
  1261. { false otherwise. if successful, the contents of newsupreg are set to c, }
  1262. { which should hold the contents of newsupreg before the current sequence }
  1263. { started }
  1264. { if the function returns true, returnEndP holds the last instruction }
  1265. { where newsupreg was replaced by orgsupreg }
  1266. var
  1267. endP, hp: tai;
  1268. removeLast, sequenceEnd, newRegModified, orgRegRead,
  1269. stateChanged, readStateChanged: Boolean;
  1270. begin
  1271. replacereg := false;
  1272. if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then
  1273. begin
  1274. {$ifdef replaceregdebug}
  1275. hp := tai_comment.Create(strpnew(
  1276. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1277. ' from here...'));
  1278. hp.next := p;
  1279. hp.previous := p.previous;
  1280. p.previous := hp;
  1281. if assigned(hp.previous) then
  1282. hp.previous.next := hp;
  1283. hp := tai_comment.Create(strpnew(
  1284. 'replaced '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1285. ' till here'));
  1286. hp.next := endp.next;
  1287. hp.previous := endp;
  1288. endp.next := hp;
  1289. if assigned(hp.next) then
  1290. hp.next.previous := hp;
  1291. {$endif replaceregdebug}
  1292. replaceReg := true;
  1293. returnEndP := endP;
  1294. getNextInstruction(p,hp);
  1295. stateChanged := false;
  1296. while hp <> endP do
  1297. begin
  1298. if {not(ptaiprop(hp.optinfo)^.canBeRemoved) and }
  1299. (hp.typ = ait_instruction) then
  1300. stateChanged :=
  1301. doReplaceReg(taicpu(hp),newsupreg,orgsupreg) or stateChanged;
  1302. if stateChanged then
  1303. updateStates(orgsupreg,newsupreg,hp,true);
  1304. getNextInstruction(hp,hp)
  1305. end;
  1306. if assigned(endp) and (endp.typ = ait_instruction) then
  1307. readStateChanged :=
  1308. doReplaceReadReg(taicpu(endP),newsupreg,orgsupreg);
  1309. if stateChanged or readStateChanged then
  1310. updateStates(orgsupreg,newsupreg,endP,stateChanged);
  1311. if stateChanged or readStateChanged then
  1312. updateState(orgsupreg,endP);
  1313. { We replaced newreg with oldreg between p and endp, so restore the contents }
  1314. { of newreg there with its contents from before the sequence. }
  1315. if removeLast or
  1316. RegLoadedWithNewValue(newsupreg,true,endP) then
  1317. GetLastInstruction(endP,hp)
  1318. else hp := endP;
  1319. RestoreRegContentsTo(newsupreg,c,seqstart,hp);
  1320. { Ot is possible that the new register was modified (e.g. an add/sub), so if }
  1321. { it was replaced by oldreg in that instruction, oldreg's contents have been }
  1322. { changed. To take this into account, we simply set the contents of orgsupreg }
  1323. { to "unknown" after this sequence }
  1324. if newRegModified then
  1325. ClearRegContentsFrom(orgsupreg,p,hp);
  1326. if removeLast then
  1327. ptaiprop(endp.optinfo)^.canBeRemoved := true;
  1328. allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP,ptaiprop(p.optinfo)^.usedregs);
  1329. end
  1330. {$ifdef replaceregdebug}
  1331. else
  1332. begin
  1333. hp := tai_comment.Create(strpnew(
  1334. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1335. ' from here...'));
  1336. hp.previous := p.previous;
  1337. hp.next := p;
  1338. p.previous := hp;
  1339. if assigned(hp.previous) then
  1340. hp.previous.next := hp;
  1341. hp := tai_comment.Create(strpnew(
  1342. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1343. ' failed here'));
  1344. hp.next := endp.next;
  1345. hp.previous := endp;
  1346. endp.next := hp;
  1347. if assigned(hp.next) then
  1348. hp.next.previous := hp;
  1349. end;
  1350. {$endif replaceregdebug}
  1351. end;
  1352. function FindRegWithConst(p: tai; size: topsize; l: aint; var Res: TRegister): Boolean;
  1353. {Finds a register which contains the constant l}
  1354. var
  1355. Counter: tsuperregister;
  1356. {$ifdef testing}
  1357. hp: tai;
  1358. {$endif testing}
  1359. begin
  1360. Result:=false;
  1361. Counter := RS_EAX;
  1362. repeat
  1363. {$ifdef testing}
  1364. if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  1365. begin
  1366. hp := tai_comment.Create(strpnew(
  1367. 'checking const load of '+tostr(l)+' here...'));
  1368. hp.next := ptaiprop(p.optinfo)^.Regs[Counter].StartMod;
  1369. hp.previous := ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous;
  1370. ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous := hp;
  1371. if assigned(hp.previous) then
  1372. hp.previous.next := hp;
  1373. end;
  1374. {$endif testing}
  1375. if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) and
  1376. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).opsize = size) and
  1377. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.typ = top_const) and
  1378. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.val = l) then
  1379. begin
  1380. res:=taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[1]^.reg;
  1381. result:=true;
  1382. exit;
  1383. end;
  1384. inc(counter);
  1385. until (Counter > RS_EDI);
  1386. end;
  1387. procedure removePrevNotUsedLoad(p: tai; supreg: tsuperregister; check: boolean);
  1388. { if check = true, it means the procedure has to check whether it isn't }
  1389. { possible that the contents are still used after p (used when removing }
  1390. { instructions because of a "call"), otherwise this is not necessary }
  1391. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  1392. { value of %eax isn't used anymore later on) }
  1393. var
  1394. hp1, next, beforestartmod: tai;
  1395. begin
  1396. if getLastInstruction(p,hp1) then
  1397. with ptaiprop(hp1.optinfo)^.regs[supreg] do
  1398. if (typ in [con_ref,con_invalid,con_const]) and
  1399. (nrofMods = 1) and
  1400. (rState = ptaiprop(startmod.optinfo)^.regs[supreg].rState) and
  1401. (not(check) or
  1402. (not(regInInstruction(supreg,p)) and
  1403. (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
  1404. findRegDealloc(supreg,p)))) then
  1405. begin
  1406. ptaiprop(startMod.optinfo)^.canBeRemoved := true;
  1407. getnextinstruction(p,next);
  1408. { give the register that was modified by this instruction again }
  1409. { the contents it had before this instruction }
  1410. if getlastinstruction(startmod,beforestartmod) then
  1411. RestoreRegContentsTo(supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg],
  1412. startmod,p)
  1413. else
  1414. ClearRegContentsFrom(supreg,startmod,hp1);
  1415. end;
  1416. end;
  1417. {$ifdef notused}
  1418. function is_mov_for_div(p: taicpu): boolean;
  1419. begin
  1420. is_mov_for_div :=
  1421. (p.opcode = A_MOV) and
  1422. (p.oper[0]^.typ = top_const) and
  1423. (p.oper[1]^.typ = top_reg) and
  1424. (p.oper[1]^.reg = RS_EDX) and
  1425. getNextInstruction(p,p) and
  1426. (p.typ = ait_instruction) and
  1427. ((p.opcode = A_DIV) or
  1428. (p.opcode = A_IDIV));
  1429. end;
  1430. {$endif notused}
  1431. function memtoreg(t: taicpu; const ref: treference; var startp: tai): tregister;
  1432. var
  1433. hp: tai;
  1434. p: ptaiprop;
  1435. regcounter: tsuperregister;
  1436. optimizable: boolean;
  1437. begin
  1438. if not getlastinstruction(t,hp) or
  1439. not issimplememloc(ref) then
  1440. begin
  1441. memtoreg := NR_NO;
  1442. exit;
  1443. end;
  1444. p := ptaiprop(hp.optinfo);
  1445. optimizable := false;
  1446. for regcounter := RS_EAX to RS_EDI do
  1447. begin
  1448. if (assigned(p^.regs[regcounter].memwrite) and
  1449. refsequal(ref,p^.regs[regcounter].memwrite.oper[1]^.ref^)) then
  1450. begin
  1451. optimizable := true;
  1452. hp := p^.regs[regcounter].memwrite;
  1453. end
  1454. else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
  1455. (p^.regs[regcounter].nrofmods = 1) and
  1456. ((taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
  1457. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
  1458. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
  1459. (taicpu(p^.regs[regcounter].startmod).oper[0]^.typ = top_ref) and
  1460. refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0]^.ref^)) then
  1461. begin
  1462. optimizable := true;
  1463. hp := p^.regs[regcounter].startmod;
  1464. end;
  1465. if optimizable then
  1466. if ((t.opsize <> S_B) or
  1467. not(regcounter in [RS_ESI,RS_EDI])) and
  1468. sizescompatible(taicpu(hp).opsize,t.opsize) then
  1469. begin
  1470. case t.opsize of
  1471. S_B:
  1472. begin
  1473. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBL)
  1474. end;
  1475. S_W,S_BW:
  1476. begin
  1477. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBW);
  1478. if (t.opsize = S_BW) then
  1479. begin
  1480. t.opcode := A_MOV;
  1481. t.opsize := S_W;
  1482. end;
  1483. end;
  1484. S_L,S_BL,S_WL:
  1485. begin
  1486. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBWHOLE);
  1487. if (t.opsize <> S_L) then
  1488. begin
  1489. t.opcode := A_MOV;
  1490. t.opsize := S_L;
  1491. end;
  1492. end;
  1493. end;
  1494. startp := hp;
  1495. exit;
  1496. end;
  1497. end;
  1498. memtoreg := NR_NO;
  1499. end;
  1500. procedure removeLocalStores(const t1: tai);
  1501. {var
  1502. p: tai;
  1503. regcount: tregister; }
  1504. begin
  1505. {
  1506. for regcount := LoGPReg to HiGPReg do
  1507. if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
  1508. (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1]^.ref^.base
  1509. = current_procinfo.framepointer) then
  1510. begin
  1511. pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
  1512. clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
  1513. end;
  1514. }
  1515. end;
  1516. procedure loadcseregs(asml: taasmoutput; const reginfo: toptreginfo; curseqend, prevseqstart, curseqstart, curprev: tai; cnt: longint);
  1517. var
  1518. regsloaded: tregset;
  1519. regloads: array[RS_EAX..RS_EDI] of tai;
  1520. regcounter: tsuperregister;
  1521. hp, hp2: tai;
  1522. insertpos, prevseq_next: tai;
  1523. i: longint;
  1524. begin
  1525. regsloaded := [];
  1526. fillchar(regloads,sizeof(regloads),0);
  1527. getnextinstruction(prevseqstart,prevseq_next);
  1528. for regcounter := RS_EAX To RS_EDI do
  1529. if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
  1530. begin
  1531. include(regsloaded,regcounter);
  1532. if assigned(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod) then
  1533. AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
  1534. ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart,
  1535. ptaiprop(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod.optinfo)^.usedregs)
  1536. else
  1537. AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
  1538. prevseqstart,curseqstart,ptaiprop(prevseqstart.optinfo)^.usedregs);
  1539. if curprev <> prevseqstart then
  1540. begin
  1541. if assigned(reginfo.lastReload[regCounter]) then
  1542. getLastInstruction(reginfo.lastReload[regCounter],hp)
  1543. else if assigned(reginfo.lastReload[reginfo.new2oldreg[regCounter]]) then
  1544. getLastInstruction(reginfo.lastReload[reginfo.new2OldReg[regCounter]],hp)
  1545. else
  1546. hp := curprev;
  1547. clearRegContentsFrom(regCounter,prevSeq_next,hp);
  1548. getnextInstruction(hp,hp);
  1549. allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp,
  1550. ptaiprop(prevseqstart.optinfo)^.usedregs);
  1551. end;
  1552. if not(regcounter in reginfo.RegsLoadedforRef) and
  1553. {old reg new reg}
  1554. (reginfo.new2oldreg[regcounter] <> regcounter) then
  1555. begin
  1556. getLastInstruction(curseqend,hp);
  1557. if (curprev <> prevseqstart) or
  1558. {not(regCounter in rg.usableregsint + [RS_EDI,RS_ESI]) or}
  1559. not(regCounter in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_EDI,RS_ESI]) or
  1560. not ReplaceReg(asml,reginfo.new2oldreg[regcounter],
  1561. regCounter,hp,curseqstart,
  1562. ptaiprop(prevseqstart.optinfo)^.Regs[regCounter],true,hp2) then
  1563. begin
  1564. if not(reginfo.new2oldreg[regcounter] in regsloaded) or
  1565. { happens if the register has been replaced }
  1566. not(assigned(regloads[reginfo.new2oldreg[regcounter]])) then
  1567. insertpos := prevseq_next
  1568. else
  1569. begin
  1570. {$warning add cycle detection for register loads and use xchg if necessary}
  1571. insertpos := regloads[reginfo.new2oldreg[regcounter]];
  1572. end;
  1573. hp := Tai_Marker.Create(NoPropInfoStart);
  1574. InsertLLItem(asml, insertpos.previous,insertpos, hp);
  1575. hp2 := taicpu.Op_Reg_Reg(A_MOV, S_L,
  1576. {old reg new reg}
  1577. newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
  1578. regloads[regcounter] := hp2;
  1579. new(ptaiprop(hp2.optinfo));
  1580. ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
  1581. ptaiprop(hp2.optinfo)^.canBeRemoved := false;
  1582. InsertLLItem(asml, insertpos.previous, insertpos, hp2);
  1583. hp := Tai_Marker.Create(NoPropInfoEnd);
  1584. InsertLLItem(asml, insertpos.previous, insertpos, hp);
  1585. { adjusts states in previous instruction so that it will }
  1586. { definitely be different from the previous or next state }
  1587. incstate(ptaiprop(hp2.optinfo)^.
  1588. regs[reginfo.new2oldreg[regcounter]].rstate,20);
  1589. incstate(ptaiprop(hp2.optinfo)^.
  1590. regs[regCounter].wstate,20);
  1591. updateState(reginfo.new2oldreg[regcounter],hp2);
  1592. updateState(regcounter,hp2);
  1593. end
  1594. else
  1595. begin
  1596. // replace the new register with the old register in the
  1597. // sequence itself as well so later comparisons get the
  1598. // correct knowledge about which registers are used
  1599. hp2 := curseqstart;
  1600. // curseqend = instruction following last instruction of this
  1601. // sequence
  1602. while hp2 <> curseqend do
  1603. begin
  1604. doreplacereg(taicpu(hp2),regcounter,reginfo.new2oldreg[regcounter]);
  1605. getnextinstruction(hp2,hp2);
  1606. end;
  1607. end;
  1608. end
  1609. else
  1610. { imagine the following code: }
  1611. { normal wrong optimized }
  1612. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  1613. { movl (%eax), %eax movl (%eax), %eax }
  1614. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  1615. { jne l1 jne l1 }
  1616. { movl 8(%ebp), %eax }
  1617. { movl (%eax), %edi movl %eax, %edi }
  1618. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  1619. { movl 8(%ebp), %eax }
  1620. { pushl 70(%eax) pushl 70(%eax) }
  1621. { }
  1622. { The error is that at the moment that the last instruction is executed, }
  1623. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  1624. { registers that are completely removed from a sequence (= registers in }
  1625. { RegLoadedforRef), have to be changed to their contents from before the }
  1626. { sequence. }
  1627. { if regcounter in reginfo.RegsLoadedforRef then }
  1628. begin
  1629. hp := curseqstart;
  1630. { cnt still holds the number of instructions }
  1631. { of the sequence, so go to the end of it }
  1632. for i := 1 to pred(cnt) do
  1633. getNextInstruction(hp,hp);
  1634. { curprev = instruction prior to start of sequence }
  1635. restoreRegContentsTo(regCounter,
  1636. ptaiprop(curprev.optinfo)^.Regs[regcounter],
  1637. curseqstart,hp);
  1638. end;
  1639. end;
  1640. end;
  1641. procedure replaceoperandwithreg(asml: taasmoutput; p: tai; opnr: byte; reg: tregister);
  1642. var
  1643. hp: tai;
  1644. begin
  1645. { new instruction -> it's info block is not in the big one allocated at the start }
  1646. hp := Tai_Marker.Create(NoPropInfoStart);
  1647. InsertLLItem(asml, p.previous,p, hp);
  1648. { duplicate the original instruction and replace it's designated operant with the register }
  1649. hp := tai(p.getcopy);
  1650. taicpu(hp).loadreg(opnr,reg);
  1651. { add optimizer state info }
  1652. new(ptaiprop(hp.optinfo));
  1653. ptaiprop(hp.optinfo)^ := ptaiprop(p.optinfo)^;
  1654. { new instruction can not be removed }
  1655. ptaiprop(hp.optinfo)^.canBeRemoved := false;
  1656. { but the old one can }
  1657. ptaiprop(p.optinfo)^.canBeRemoved := true;
  1658. { insert end marker }
  1659. InsertLLItem(asml, p.previous, p, hp);
  1660. hp := Tai_Marker.Create(NoPropInfoEnd);
  1661. InsertLLItem(asml, p.previous, p, hp);
  1662. end;
  1663. procedure doCSE(asml: TAAsmOutput; First, Last: tai; findPrevSeqs, doSubOpts: boolean);
  1664. {marks the instructions that can be removed by RemoveInstructs. They're not
  1665. removed immediately because sometimes an instruction needs to be checked in
  1666. two different sequences}
  1667. var cnt, cnt2, {cnt3,} orgNrofMods: longint;
  1668. p, hp1, hp2, prevSeq: tai;
  1669. hp3, hp4: tai;
  1670. hp5 : tai;
  1671. reginfo: toptreginfo;
  1672. memreg: tregister;
  1673. regcounter: tsuperregister;
  1674. begin
  1675. p := First;
  1676. SkipHead(p);
  1677. while (p <> Last) do
  1678. begin
  1679. case p.typ of
  1680. ait_align:
  1681. if not(tai_align(p).use_op) then
  1682. SetAlignReg(p);
  1683. ait_instruction:
  1684. begin
  1685. case taicpu(p).opcode of
  1686. {
  1687. Does not work anymore with register calling because the registers are
  1688. released before the call
  1689. A_CALL:
  1690. for regCounter := RS_EAX to RS_EBX do
  1691. removePrevNotUsedLoad(p,regCounter,true);
  1692. }
  1693. A_CLD: if GetLastInstruction(p, hp1) and
  1694. (ptaiprop(hp1.optinfo)^.DirFlag = F_NotSet) then
  1695. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1696. A_LEA, A_MOV, A_MOVZX, A_MOVSX:
  1697. begin
  1698. hp2 := p;
  1699. case taicpu(p).oper[0]^.typ of
  1700. top_ref, top_reg:
  1701. if (taicpu(p).oper[1]^.typ = top_reg) then
  1702. begin
  1703. With ptaiprop(p.optinfo)^.Regs[getsupreg(taicpu(p).oper[1]^.reg)] do
  1704. begin
  1705. if (startmod = p) then
  1706. orgNrofMods := nrofMods
  1707. else
  1708. orgNrofMods := 0;
  1709. if (p = StartMod) and
  1710. GetLastInstruction (p, hp1) and
  1711. not(hp1.typ in [ait_marker,ait_label]) then
  1712. {so we don't try to check a sequence when p is the first instruction of the block}
  1713. begin
  1714. {$ifdef csdebug}
  1715. hp5 := tai_comment.Create(strpnew(
  1716. 'cse checking '+std_regname(taicpu(p).oper[1]^.reg)));
  1717. insertLLItem(asml,p,p.next,hp5);
  1718. {$endif csdebug}
  1719. if CheckSequence(p,prevSeq,getsupreg(taicpu(p).oper[1]^.reg), Cnt, reginfo, findPrevSeqs) and
  1720. (Cnt > 0) then
  1721. begin
  1722. (*
  1723. hp1 := nil;
  1724. { although it's perfectly ok to remove an instruction which doesn't contain }
  1725. { the register that we've just checked (CheckSequence takes care of that), }
  1726. { the sequence containing this other register should also be completely }
  1727. { checked and removed, otherwise we may get situations like this: }
  1728. { }
  1729. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  1730. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  1731. { movl 8(%edx), %edx movl 8(%edx), %edx }
  1732. { movl (%eax), eax movl (%eax), eax }
  1733. { cmpl %eax, %edx cmpl %eax, %edx }
  1734. { jnz l123 getting converted to jnz l123 }
  1735. { movl 12(%ebp), %edx movl 4(%eax), eax }
  1736. { movl 16(%ebp), %eax }
  1737. { movl 8(%edx), %edx }
  1738. { movl 4(%eax), eax }
  1739. *)
  1740. { not anymore: if the start of a new sequence is found while checking (e.g. }
  1741. { above that of eax while checking edx, this new sequence is automatically }
  1742. { also checked }
  1743. Cnt2 := 1;
  1744. while Cnt2 <= Cnt do
  1745. begin
  1746. {$ifndef noremove}
  1747. ptaiprop(p.optinfo)^.CanBeRemoved := True
  1748. {$endif noremove}
  1749. ; inc(Cnt2);
  1750. GetNextInstruction(p, p);
  1751. end;
  1752. {hp4 is used to get the contents of the registers before the sequence}
  1753. GetLastInstruction(hp2, hp4);
  1754. {$IfDef CSDebug}
  1755. for regcounter := RS_EAX To RS_EDI do
  1756. if (regcounter in reginfo.RegsLoadedforRef) then
  1757. begin
  1758. hp5 := tai_comment.Create(strpnew('New: '+std_regname(newreg(R_INTREGISTER,regcounter,R_SUBNONE))+', Old: '+
  1759. std_regname(newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBNONE))));
  1760. InsertLLItem(asml, tai(hp2.previous), hp2, hp5);
  1761. end;
  1762. {$EndIf CSDebug}
  1763. { if some registers were different in the old and the new sequence, move }
  1764. { the contents of those old registers to the new ones }
  1765. loadcseregs(asml,reginfo,p,prevseq,hp2,hp4,cnt);
  1766. continue;
  1767. end
  1768. end;
  1769. end;
  1770. { try to replace the new reg with the old reg }
  1771. if not(ptaiprop(p.optinfo)^.canBeRemoved) then
  1772. if (taicpu(p).oper[0]^.typ = top_reg) and
  1773. (taicpu(p).oper[1]^.typ = top_reg) and
  1774. { only remove if we're not storing something in a regvar }
  1775. (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) and
  1776. { (taicpu(p).oper[1]^.reg in (rg.usableregsint+[RS_EDI])) and}
  1777. (taicpu(p).opcode = A_MOV) and
  1778. getLastInstruction(p,hp4) and
  1779. { we only have to start replacing from the instruction after the mov, }
  1780. { but replacereg only starts with getnextinstruction(p,p) }
  1781. replaceReg(asml,getsupreg(taicpu(p).oper[0]^.reg),
  1782. getsupreg(taicpu(p).oper[1]^.reg),p,p,
  1783. ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
  1784. begin
  1785. ptaiprop(p.optinfo)^.canBeRemoved := true;
  1786. { this is just a regular move that was here, so the source register should be }
  1787. { allocated already at this point -> only allocate from here onwards }
  1788. if not(getsupreg(taicpu(p).oper[0]^.reg) in pTaiProp(p.optinfo)^.usedregs) then
  1789. internalerror(2004101011);
  1790. allocRegBetween(asml,taicpu(p).oper[0]^.reg,
  1791. p,hp1,pTaiProp(p.optinfo)^.usedregs)
  1792. end
  1793. else
  1794. begin
  1795. if (taicpu(p).oper[1]^.typ = top_reg) and
  1796. not regInOp(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^) then
  1797. removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1798. if doSubOpts and
  1799. (taicpu(p).opcode <> A_LEA) and
  1800. (taicpu(p).oper[0]^.typ = top_ref) then
  1801. begin
  1802. memreg :=
  1803. memtoreg(taicpu(p),
  1804. taicpu(p).oper[0]^.ref^,hp5);
  1805. if memreg <> NR_NO then
  1806. if (taicpu(p).opcode = A_MOV) and
  1807. (taicpu(p).oper[1]^.typ = top_reg) and
  1808. (taicpu(p).oper[1]^.reg = memreg) then
  1809. begin
  1810. pTaiProp(p.optinfo)^.canberemoved := true;
  1811. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1812. end
  1813. else
  1814. begin
  1815. replaceoperandwithreg(asml,p,0,memreg);
  1816. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1817. regcounter := getsupreg(memreg);
  1818. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1819. updatestate(regcounter,p);
  1820. end;
  1821. end;
  1822. end;
  1823. { at first, only try optimizations of large blocks, because doing }
  1824. { doing smaller ones may prevent bigger ones from completing in }
  1825. { in the next pass }
  1826. if not doSubOpts and (orgNrofMods <> 0) then
  1827. begin
  1828. p := hp2;
  1829. for cnt := 1 to pred(orgNrofMods) do
  1830. getNextInstruction(p,p);
  1831. end;
  1832. end;
  1833. top_Const:
  1834. begin
  1835. case taicpu(p).oper[1]^.typ of
  1836. Top_Reg:
  1837. begin
  1838. regCounter := getsupreg(taicpu(p).oper[1]^.reg);
  1839. if GetLastInstruction(p, hp1) then
  1840. With ptaiprop(hp1.optinfo)^.Regs[regCounter] do
  1841. if (typ in [con_const,con_noRemoveConst]) and
  1842. (taicpu(startMod).opsize >= taicpu(p).opsize) and
  1843. opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
  1844. begin
  1845. ptaiprop(p.optinfo)^.CanBeRemoved := True;
  1846. allocRegBetween(asml,taicpu(p).oper[1]^.reg,startmod,p,
  1847. ptaiprop(startmod.optinfo)^.usedregs);
  1848. end
  1849. else
  1850. removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1851. end;
  1852. Top_Ref:
  1853. if (taicpu(p).oper[0]^.typ = top_const) and
  1854. getLastInstruction(p,hp1) and
  1855. findRegWithConst(hp1,taicpu(p).opsize,taicpu(p).oper[0]^.val,memreg) then
  1856. begin
  1857. taicpu(p).loadreg(0,memreg);
  1858. allocRegBetween(asml,memreg,
  1859. ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p,
  1860. ptaiprop(ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod.optinfo)^.usedregs);
  1861. end;
  1862. end;
  1863. end;
  1864. end;
  1865. end;
  1866. A_LEAVE:
  1867. begin
  1868. if getlastinstruction(p,hp1) then
  1869. removeLocalStores(hp1);
  1870. end;
  1871. A_STD: if GetLastInstruction(p, hp1) and
  1872. (ptaiprop(hp1.optinfo)^.DirFlag = F_Set) then
  1873. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1874. else
  1875. begin
  1876. for cnt := 1 to maxinschanges do
  1877. begin
  1878. case InsProp[taicpu(p).opcode].Ch[cnt] of
  1879. Ch_ROp1:
  1880. if (taicpu(p).oper[0]^.typ = top_ref) and
  1881. ((taicpu(p).opcode < A_F2XM1) or
  1882. ((taicpu(p).opcode > A_IN) and
  1883. (taicpu(p).opcode < A_OUT)) or
  1884. (taicpu(p).opcode = A_PUSH) or
  1885. ((taicpu(p).opcode >= A_RCL) and
  1886. (taicpu(p).opcode <= A_XOR))) then
  1887. begin
  1888. memreg :=
  1889. memtoreg(taicpu(p),
  1890. taicpu(p).oper[0]^.ref^,hp5);
  1891. if memreg <> NR_NO then
  1892. begin
  1893. replaceoperandwithreg(asml,p,0,memreg);
  1894. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1895. regcounter := getsupreg(memreg);
  1896. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1897. updatestate(regcounter,p);
  1898. end;
  1899. end;
  1900. Ch_MOp1:
  1901. if not(CS_LittleSize in aktglobalswitches) and
  1902. (taicpu(p).oper[0]^.typ = top_ref) then
  1903. begin
  1904. memreg :=
  1905. memtoreg(taicpu(p),
  1906. taicpu(p).oper[0]^.ref^,hp5);
  1907. if (memreg <> NR_NO) and
  1908. (not getNextInstruction(p,hp1) or
  1909. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  1910. FindRegDealloc(getsupreg(memreg),hp1))) then
  1911. begin
  1912. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1913. insertllitem(asml,p,p.next,hp1);
  1914. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  1915. memreg,taicpu(p).oper[0]^.ref^);
  1916. new(ptaiprop(hp1.optinfo));
  1917. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1918. insertllitem(asml,p,p.next,hp1);
  1919. regcounter := getsupreg(memreg);
  1920. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  1921. updatestate(regcounter,hp1);
  1922. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1923. insertllitem(asml,p,p.next,hp1);
  1924. replaceoperandwithreg(asml,p,0,memreg);
  1925. allocregbetween(asml,memreg,hp5,
  1926. tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
  1927. ClearRegContentsFrom(regcounter,hp5,p);
  1928. end;
  1929. end;
  1930. Ch_ROp2:
  1931. if ((taicpu(p).opcode = A_CMP) or
  1932. (taicpu(p).opcode = A_TEST)) and
  1933. (taicpu(p).oper[1]^.typ = top_ref) then
  1934. begin
  1935. memreg :=
  1936. memtoreg(taicpu(p),
  1937. taicpu(p).oper[1]^.ref^,hp5);
  1938. if memreg <> NR_NO then
  1939. begin
  1940. replaceoperandwithreg(asml,p,1,memreg);
  1941. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1942. regcounter := getsupreg(memreg);
  1943. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1944. updatestate(regcounter,p);
  1945. end;
  1946. end;
  1947. Ch_MOp2:
  1948. if not(cs_littlesize in aktglobalswitches) and
  1949. (taicpu(p).oper[1]^.typ = top_ref) and
  1950. ((taicpu(p).opcode < A_BT) or
  1951. ((taicpu(p).opcode > A_IN) and
  1952. (taicpu(p).opcode < A_OUT)) or
  1953. (taicpu(p).opcode = A_PUSH) or
  1954. ((taicpu(p).opcode >= A_RCL) and
  1955. (taicpu(p).opcode <= A_XOR))) then
  1956. begin
  1957. memreg :=
  1958. memtoreg(taicpu(p),
  1959. taicpu(p).oper[1]^.ref^,hp5);
  1960. if (memreg <> NR_NO) and
  1961. (not getNextInstruction(p,hp1) or
  1962. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  1963. FindRegDealloc(getsupreg(memreg),hp1))) then
  1964. begin
  1965. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1966. insertllitem(asml,p,p.next,hp1);
  1967. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  1968. memreg,taicpu(p).oper[1]^.ref^);
  1969. new(ptaiprop(hp1.optinfo));
  1970. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1971. insertllitem(asml,p,p.next,hp1);
  1972. regcounter := getsupreg(memreg);
  1973. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  1974. updatestate(regcounter,hp1);
  1975. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1976. insertllitem(asml,p,p.next,hp1);
  1977. replaceoperandwithreg(asml,p,1,memreg);
  1978. allocregbetween(asml,memreg,hp5,
  1979. tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
  1980. ClearRegContentsFrom(regcounter,hp5,p);
  1981. end;
  1982. end;
  1983. end;
  1984. end;
  1985. end;
  1986. end
  1987. end;
  1988. end;
  1989. GetNextInstruction(p, p);
  1990. end;
  1991. end;
  1992. function removeInstructs(asml: TAAsmoutput; first, last: tai): boolean;
  1993. { Removes the marked instructions and disposes the PTaiProps of the other }
  1994. { instructions }
  1995. var
  1996. p, hp1: tai;
  1997. nopropinfolevel: longint;
  1998. begin
  1999. removeInstructs := false;
  2000. p := First;
  2001. nopropinfolevel := 0;
  2002. while (p <> Last) do
  2003. begin
  2004. if (p.typ = ait_marker) and
  2005. (Tai_marker(p).kind = noPropInfoStart) then
  2006. begin
  2007. hp1 := tai(p.next);
  2008. asml.remove(p);
  2009. p.free;
  2010. nopropinfolevel := 1;
  2011. while (nopropinfolevel <> 0) do
  2012. begin
  2013. p := tai(hp1.next);
  2014. {$ifndef noinstremove}
  2015. { allocregbetween can insert new ait_regalloc objects }
  2016. { without optinfo }
  2017. if (hp1.typ = ait_marker) then
  2018. begin
  2019. case Tai_marker(hp1).kind of
  2020. { they can be nested! }
  2021. noPropInfoStart: inc(nopropinfolevel);
  2022. noPropInfoEnd: dec(nopropinfolevel);
  2023. else
  2024. begin
  2025. hp1 := p;
  2026. continue;
  2027. end;
  2028. end;
  2029. asml.remove(hp1);
  2030. hp1.free;
  2031. end
  2032. else if assigned(hp1.optinfo) then
  2033. if ptaiprop(hp1.optinfo)^.canBeRemoved then
  2034. begin
  2035. dispose(ptaiprop(hp1.optinfo));
  2036. hp1.optinfo := nil;
  2037. asml.remove(hp1);
  2038. hp1.free;
  2039. end
  2040. else
  2041. {$endif noinstremove}
  2042. begin
  2043. dispose(ptaiprop(hp1.optinfo));
  2044. hp1.optinfo := nil;
  2045. end;
  2046. hp1 := p;
  2047. end;
  2048. end
  2049. else
  2050. {$ifndef noinstremove}
  2051. if assigned(p.optinfo) and
  2052. ptaiprop(p.optinfo)^.canBeRemoved then
  2053. begin
  2054. hp1 := tai(p.next);
  2055. asml.Remove(p);
  2056. p.free;
  2057. p := hp1;
  2058. removeInstructs := true;
  2059. end
  2060. else
  2061. {$endif noinstremove}
  2062. begin
  2063. p.optinfo := nil;
  2064. p := tai(p.next);;
  2065. end;
  2066. end;
  2067. end;
  2068. function CSE(asml: TAAsmOutput; First, Last: tai; pass: longint): boolean;
  2069. begin
  2070. doCSE(asml, First, Last, not(cs_slowoptimize in aktglobalswitches) or (pass >= 2),
  2071. not(cs_slowoptimize in aktglobalswitches) or (pass >= 1));
  2072. { register renaming }
  2073. if not(cs_slowoptimize in aktglobalswitches) or (pass > 0) then
  2074. doRenaming(asml, first, last);
  2075. cse := removeInstructs(asml, first, last);
  2076. end;
  2077. end.
  2078. {
  2079. $Log$
  2080. Revision 1.71 2004-12-27 15:20:03 jonas
  2081. * fixed internalerror when cycling with -O3p3u
  2082. Revision 1.70 2004/12/18 15:16:10 jonas
  2083. * fixed tracking of usage of flags register
  2084. * fixed destroying of "memwrite"'s
  2085. * fixed checking of entire sequences in all cases (previously this was
  2086. only guaranteed if the new sequence was longer than the old one, and
  2087. not if vice versa)
  2088. * fixed wrong removal of sequences if a register load was already
  2089. completely removed in the previous sequence (because in that case,
  2090. that register has to be removed and renamed in the new sequence as
  2091. well before removing the new sequence)
  2092. Revision 1.69 2004/10/31 21:45:03 peter
  2093. * generic tlocation
  2094. * move tlocation to cgutils
  2095. Revision 1.68 2004/10/10 15:01:19 jonas
  2096. * several fixes to allocregbetween()
  2097. Revision 1.67 2004/10/06 19:24:38 jonas
  2098. * take into account the size of a write to determine whether a write to
  2099. one reference influences the contents of another reference
  2100. Revision 1.66 2004/10/04 20:46:22 peter
  2101. * spilling code rewritten for x86. It now used the generic
  2102. spilling routines. Special x86 optimization still needs
  2103. to be added.
  2104. * Spilling fixed when both operands needed to be spilled
  2105. * Cleanup of spilling routine, do_spill_readwritten removed
  2106. Revision 1.65 2004/09/21 17:25:12 peter
  2107. * paraloc branch merged
  2108. Revision 1.64.4.1 2004/09/20 19:28:23 peter
  2109. * fixed valgrind warning
  2110. Revision 1.64 2004/07/23 13:30:19 jonas
  2111. * fixed some more potential regvar bugs
  2112. Revision 1.63 2004/06/20 08:55:31 florian
  2113. * logs truncated
  2114. Revision 1.62 2004/06/16 20:07:10 florian
  2115. * dwarf branch merged
  2116. Revision 1.61.2.2 2004/05/01 16:02:10 peter
  2117. * POINTER_SIZE replaced with sizeof(aint)
  2118. * aint,aword,tconst*int moved to globtype
  2119. Revision 1.61.2.1 2004/04/29 23:30:28 peter
  2120. * fix i386 compiler
  2121. Revision 1.61 2004/02/27 10:21:05 florian
  2122. * top_symbol killed
  2123. + refaddr to treference added
  2124. + refsymbol to treference added
  2125. * top_local stuff moved to an extra record to save memory
  2126. + aint introduced
  2127. * tppufile.get/putint64/aint implemented
  2128. Revision 1.60 2004/02/25 20:39:58 jonas
  2129. * fixed bugs that caused pasjpeg crashes
  2130. }