csopt386.pas 86 KB

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