csopt386.pas 83 KB

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