csopt386.pas 85 KB

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