csopt386.pas 89 KB

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