csopt386.pas 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  4. development team
  5. This unit contains the common subexpression elimination procedure.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit CSOpt386;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses aasmbase,aasmtai,aasmcpu, cpuinfo, cpubase, optbase, cgbase;
  23. function CSE(asml: TAAsmoutput; first, last: tai; pass: longint): boolean;
  24. function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
  25. function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
  26. function storeBack(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. begin
  913. RegSizesOK := true;
  914. { if only one of them is a general purpose register ... }
  915. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  916. begin
  917. for opCount := 0 to p.ops-1 do
  918. if (p.oper[opCount]^.typ = top_reg) and
  919. (getsubreg(p.oper[opCount]^.reg) in [R_SUBL,R_SUBH]) then
  920. begin
  921. RegSizesOK := false;
  922. break
  923. end
  924. end;
  925. end;
  926. function doReplaceReadReg(p: taicpu; newReg,orgReg: tsuperregister): boolean;
  927. var
  928. opCount: byte;
  929. begin
  930. doReplaceReadReg := false;
  931. { handle special case }
  932. case p.opcode of
  933. A_IMUL:
  934. begin
  935. case p.ops of
  936. 1: internalerror(1301001);
  937. 2,3:
  938. begin
  939. if changeOp(p.oper[0]^,newReg,orgReg) then
  940. begin
  941. { updateStates(orgReg,newReg,p,false);}
  942. doReplaceReadReg := true;
  943. end;
  944. if p.ops = 3 then
  945. if changeOp(p.oper[1]^,newReg,orgReg) then
  946. begin
  947. { updateStates(orgReg,newReg,p,false);}
  948. doReplaceReadReg := true;
  949. end;
  950. end;
  951. end;
  952. end;
  953. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  954. else
  955. begin
  956. for opCount := 0 to p.ops-1 do
  957. if p.oper[opCount]^.typ = top_ref then
  958. if changeOp(p.oper[opCount]^,newReg,orgReg) then
  959. begin
  960. { updateStates(orgReg,newReg,p,false);}
  961. doReplaceReadReg := true;
  962. end;
  963. for opCount := 1 to MaxCh do
  964. case InsProp[p.opcode].Ch[opCount] of
  965. Ch_ROp1:
  966. if p.oper[0]^.typ = top_reg then
  967. if changeReg(p.oper[0]^.reg,newReg,orgReg) then
  968. begin
  969. { updateStates(orgReg,newReg,p,false);}
  970. doReplaceReadReg := true;
  971. end;
  972. Ch_ROp2:
  973. if p.oper[1]^.typ = top_reg then
  974. if changeReg(p.oper[1]^.reg,newReg,orgReg) then
  975. begin
  976. { updateStates(orgReg,newReg,p,false);}
  977. doReplaceReadReg := true;
  978. end;
  979. Ch_ROp3:
  980. if p.oper[2]^.typ = top_reg then
  981. if changeReg(p.oper[2]^.reg,newReg,orgReg) then
  982. begin
  983. { updateStates(orgReg,newReg,p,false);}
  984. doReplaceReadReg := true;
  985. end;
  986. end;
  987. end;
  988. end;
  989. end;
  990. procedure updateState(supreg: tsuperregister; p: tai);
  991. { this procedure updates the read and write states of the instructions }
  992. { coming after p. It's called when the read/write state of p has been }
  993. { changed and this change has to be propagated to the following }
  994. { instructions as well }
  995. var
  996. newRState, newWState: byte;
  997. prevRState, prevWState: byte;
  998. doRState, doWState: boolean;
  999. begin
  1000. { get the new read/write states from p }
  1001. with ptaiprop(p.optinfo)^.regs[supreg] do
  1002. begin
  1003. newRState := rState;
  1004. newWState := wState;
  1005. end;
  1006. if not GetNextInstruction(p,p) then
  1007. exit;
  1008. { get the old read/write states from the next instruction, to know }
  1009. { when we can stop updating }
  1010. with ptaiprop(p.optinfo)^.regs[supreg] do
  1011. begin
  1012. prevRState := rState;
  1013. prevWState := wState;
  1014. end;
  1015. { adjust the states if this next instruction reads/writes the register }
  1016. if regReadByInstruction(supreg,p) then
  1017. incState(newRState,1);
  1018. if regModifiedByInstruction(supreg,p) then
  1019. incState(newWState,1);
  1020. { do we still have to update the read and/or write states? }
  1021. doRState := true;
  1022. doWState := true;
  1023. repeat
  1024. { update the states }
  1025. with ptaiprop(p.optinfo)^.regs[supreg] do
  1026. begin
  1027. if doRState then
  1028. rState := newRState;
  1029. if doWState then
  1030. wState := newWState;
  1031. end;
  1032. if not getNextInstruction(p,p) then
  1033. break;
  1034. with ptaiprop(p.optinfo)^.regs[supreg] do
  1035. begin
  1036. { stop updating the read state if it changes }
  1037. doRState :=
  1038. doRState and (rState = prevRState);
  1039. { if, by accident, this changed state is the same as the one }
  1040. { we've been using, change it to a value that's definitely }
  1041. { different from the previous and next state }
  1042. if not doRState and
  1043. (rState = newRState) then
  1044. begin
  1045. incState(newRState,1);
  1046. prevRState := rState;
  1047. doRState := true;
  1048. end;
  1049. { ditto for the write state }
  1050. doWState :=
  1051. doWState and (WState = prevWState);
  1052. if not doWState and
  1053. (wState = newWState) then
  1054. begin
  1055. incState(newWState,1);
  1056. prevWState := wState;
  1057. doWState := true;
  1058. end;
  1059. end;
  1060. { stop when we don't have to update either state anymore }
  1061. until not(doRState or doWState);
  1062. end;
  1063. function storeBack(p1: tai; orgReg, newReg: tsuperregister): boolean;
  1064. { returns true if p1 contains an instruction that stores the contents }
  1065. { of newReg back to orgReg }
  1066. begin
  1067. storeBack :=
  1068. (p1.typ = ait_instruction) and
  1069. (taicpu(p1).opcode = A_MOV) and
  1070. (taicpu(p1).oper[0]^.typ = top_reg) and
  1071. (getsupreg(taicpu(p1).oper[0]^.reg) = newReg) and
  1072. (taicpu(p1).oper[1]^.typ = top_reg) and
  1073. (getsupreg(taicpu(p1).oper[1]^.reg) = orgReg);
  1074. end;
  1075. function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p: tai;
  1076. const c: TContent; orgRegCanBeModified: Boolean;
  1077. var returnEndP: tai): Boolean;
  1078. { Tries to replace orgsupreg with newsupreg in all instructions coming after p }
  1079. { until orgsupreg gets loaded with a new value. Returns true if successful, }
  1080. { false otherwise. if successful, the contents of newsupreg are set to c, }
  1081. { which should hold the contents of newsupreg before the current sequence }
  1082. { started }
  1083. { if the function returns true, returnEndP holds the last instruction }
  1084. { where newsupreg was replaced by orgsupreg }
  1085. var
  1086. endP, hp: tai;
  1087. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead,
  1088. stateChanged, readStateChanged: Boolean;
  1089. begin
  1090. ReplaceReg := false;
  1091. tmpResult := true;
  1092. sequenceEnd := false;
  1093. newRegModified := false;
  1094. orgRegRead := false;
  1095. removeLast := false;
  1096. endP := p;
  1097. while tmpResult and not sequenceEnd do
  1098. begin
  1099. tmpResult :=
  1100. getNextInstruction(endP,endP) and
  1101. (endp.typ = ait_instruction) and
  1102. not(taicpu(endp).is_jmp);
  1103. if tmpresult and not assigned(endp.optinfo) then
  1104. begin
  1105. { hp := tai_comment.Create(strpnew('next no optinfo'));
  1106. hp.next := endp;
  1107. hp.previous := endp.previous;
  1108. endp.previous := hp;
  1109. if assigned(hp.previous) then
  1110. hp.previous^.next := hp;}
  1111. exit;
  1112. end;
  1113. if tmpResult and
  1114. { don't take into account instructions that will be removed }
  1115. not (ptaiprop(endp.optinfo)^.canBeRemoved) then
  1116. begin
  1117. { if the newsupreg gets stored back to the oldReg, we can change }
  1118. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  1119. { %oldReg" to "<operations on %oldReg>" }
  1120. removeLast := storeBack(endP, orgsupreg, newsupreg);
  1121. sequenceEnd :=
  1122. { no support for (i)div, mul and imul with hardcoded operands }
  1123. (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1124. { if newsupreg gets loaded with a new value, we can stop }
  1125. { replacing newsupreg with oldReg here (possibly keeping }
  1126. { the original contents of oldReg so we still know them }
  1127. { afterwards) }
  1128. RegLoadedWithNewValue(newsupreg,true,taicpu(endP)) or
  1129. { we can also stop if we reached the end of the use of }
  1130. { newReg's current contents }
  1131. (GetNextInstruction(endp,hp) and
  1132. FindRegDealloc(newsupreg,hp)));
  1133. { to be able to remove the first and last instruction of }
  1134. { movl %reg1, %reg2 }
  1135. { <operations on %reg2> (replacing reg2 with reg1 here) }
  1136. { movl %reg2, %reg1 }
  1137. { %reg2 must not be use afterwards (it can be as the }
  1138. { result of a peepholeoptimization) }
  1139. removeLast := removeLast and sequenceEnd;
  1140. newRegModified :=
  1141. newRegModified or
  1142. (not(regLoadedWithNewValue(newsupreg,true,taicpu(endP))) and
  1143. RegModifiedByInstruction(newsupreg,endP));
  1144. orgRegRead := newRegModified and RegReadByInstruction(orgsupreg,endP);
  1145. sequenceEnd := SequenceEnd and
  1146. (removeLast or
  1147. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1148. { gets modified if orgsupreg is still read afterwards (since after }
  1149. { replacing, this would mean that orgsupreg first gets modified and then }
  1150. { gets read in the assumption it still contains the unmodified value) }
  1151. not(newRegModified and orgRegRead)) (* and
  1152. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1153. { gets modified if orgRegCanBeModified = false }
  1154. { this now gets checked after the loop (JM) }
  1155. (orgRegCanBeModified or not(newRegModified)) *);
  1156. tmpResult :=
  1157. not(removeLast) and
  1158. not(newRegModified and orgRegRead) and
  1159. (* (orgRegCanBeModified or not(newRegModified)) and *)
  1160. (* already checked at the top
  1161. (endp.typ = ait_instruction) and *)
  1162. NoHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1163. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1164. not RegModifiedByInstruction(orgsupreg,endP);
  1165. end;
  1166. end;
  1167. sequenceEnd := sequenceEnd and
  1168. (removeLast or
  1169. (orgRegCanBeModified or not(newRegModified))) and
  1170. (not(assigned(endp)) or
  1171. not(endp.typ = ait_instruction) or
  1172. (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1173. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1174. not(newRegModified and
  1175. (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
  1176. not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
  1177. if SequenceEnd then
  1178. begin
  1179. {$ifdef replaceregdebug}
  1180. hp := tai_comment.Create(strpnew(
  1181. 'replacing '+std_reg2str[newsupreg]+' with '+std_reg2str[orgsupreg]+
  1182. ' from here...')));
  1183. hp.next := p;
  1184. hp.previous := p.previous;
  1185. p.previous := hp;
  1186. if assigned(hp.previous) then
  1187. hp.previous^.next := hp;
  1188. hp := tai_comment.Create(strpnew(
  1189. 'replaced '+std_reg2str[newsupreg]+' with '+std_reg2str[orgsupreg]+
  1190. ' till here')));
  1191. hp.next := endp.next;
  1192. hp.previous := endp;
  1193. endp.next := hp;
  1194. if assigned(hp.next) then
  1195. hp.next.previous := hp;
  1196. {$endif replaceregdebug}
  1197. replaceReg := true;
  1198. returnEndP := endP;
  1199. getNextInstruction(p,hp);
  1200. stateChanged := false;
  1201. while hp <> endP do
  1202. begin
  1203. if {not(ptaiprop(hp.optinfo)^.canBeRemoved) and }
  1204. (hp.typ = ait_instruction) then
  1205. stateChanged :=
  1206. doReplaceReg(taicpu(hp),newsupreg,orgsupreg) or stateChanged;
  1207. if stateChanged then
  1208. updateStates(orgsupreg,newsupreg,hp,true);
  1209. getNextInstruction(hp,hp)
  1210. end;
  1211. if assigned(endp) and (endp.typ = ait_instruction) then
  1212. readStateChanged :=
  1213. doReplaceReadReg(taicpu(endP),newsupreg,orgsupreg);
  1214. if stateChanged or readStateChanged then
  1215. updateStates(orgsupreg,newsupreg,endP,stateChanged);
  1216. if stateChanged or readStateChanged then
  1217. updateState(orgsupreg,endP);
  1218. { the replacing stops either at the moment that }
  1219. { a) the newsupreg gets loaded with a new value (one not depending on the }
  1220. { current value of newsupreg) }
  1221. { b) newsupreg is completely replaced in this sequence and it's current value }
  1222. { isn't used anymore }
  1223. { in case b, the newsupreg was completely replaced by oldreg, so it's contents }
  1224. { are unchanged compared the start of this sequence, so restore them }
  1225. if removeLast or
  1226. RegLoadedWithNewValue(newsupreg,true,endP) then
  1227. GetLastInstruction(endP,hp)
  1228. else hp := endP;
  1229. if removeLast or
  1230. (p <> endp) or
  1231. not RegLoadedWithNewValue(newsupreg,true,endP) then
  1232. RestoreRegContentsTo(newsupreg,c,p,hp);
  1233. { in both case a and b, it is possible that the new register was modified }
  1234. { (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
  1235. { oldreg's contents have been changed. To take this into account, we simply }
  1236. { set the contents of orgsupreg to "unknown" after this sequence }
  1237. if newRegModified then
  1238. ClearRegContentsFrom(orgsupreg,p,hp);
  1239. if removeLast then
  1240. ptaiprop(endp.optinfo)^.canBeRemoved := true;
  1241. allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP);
  1242. end
  1243. {$ifdef replaceregdebug}
  1244. else
  1245. begin
  1246. hp := tai_comment.Create(strpnew(
  1247. 'replacing '+std_reg2str[newsupreg]+' with '+std_reg2str[orgsupreg]+
  1248. ' from here...')));
  1249. hp.previous := p.previous;
  1250. hp.next := p;
  1251. p.previous := hp;
  1252. if assigned(hp.previous) then
  1253. hp.previous^.next := hp;
  1254. hp := tai_comment.Create(strpnew(
  1255. 'replacing '+std_reg2str[newsupreg]+' with '+std_reg2str[orgsupreg]+
  1256. ' failed here')));
  1257. hp.next := endp.next;
  1258. hp.previous := endp;
  1259. endp.next := hp;
  1260. if assigned(hp.next) then
  1261. hp.next.previous := hp;
  1262. end;
  1263. {$endif replaceregdebug}
  1264. end;
  1265. function FindRegWithConst(p: tai; size: topsize; l: aword; var Res: TRegister): Boolean;
  1266. {Finds a register which contains the constant l}
  1267. var
  1268. Counter: tsuperregister;
  1269. {$ifdef testing}
  1270. hp: tai;
  1271. {$endif testing}
  1272. tmpresult: boolean;
  1273. begin
  1274. Counter := RS_EAX;
  1275. repeat
  1276. tmpresult := (ptaiprop(p.optinfo)^.regs[counter].typ in
  1277. [con_const,con_noRemoveConst]) and
  1278. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).opsize = size) and
  1279. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.typ = top_const) and
  1280. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.val = l);
  1281. {$ifdef testing}
  1282. if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  1283. begin
  1284. hp := tai_comment.Create(strpnew(
  1285. 'checking const load of '+tostr(l)+' here...')));
  1286. hp.next := ptaiprop(p.optinfo)^.Regs[Counter].StartMod;
  1287. hp.previous := ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous;
  1288. ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous := hp;
  1289. if assigned(hp.previous) then
  1290. hp.previous^.next := hp;
  1291. end;
  1292. {$endif testing}
  1293. inc(counter);
  1294. until tmpresult or (Counter > RS_EDI);
  1295. if tmpResult then
  1296. res := taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[1]^.reg;
  1297. FindRegWithConst := tmpResult;
  1298. end;
  1299. procedure removePrevNotUsedLoad(p: tai; supreg: tsuperregister; check: boolean);
  1300. { if check = true, it means the procedure has to check whether it isn't }
  1301. { possible that the contents are still used after p (used when removing }
  1302. { instructions because of a "call"), otherwise this is not necessary }
  1303. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  1304. { value of %eax isn't used anymore later on) }
  1305. var
  1306. hp1: tai;
  1307. begin
  1308. if getLastInstruction(p,hp1) then
  1309. with ptaiprop(hp1.optinfo)^.regs[supreg] do
  1310. if (typ in [con_ref,con_invalid,con_const]) and
  1311. (nrofMods = 1) and
  1312. (rState = ptaiprop(startmod.optinfo)^.regs[supreg].rState) and
  1313. (not(check) or
  1314. (not(regInInstruction(supreg,p)) and
  1315. (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
  1316. findRegDealloc(supreg,p)))) then
  1317. ptaiprop(startMod.optinfo)^.canBeRemoved := true;
  1318. end;
  1319. {$ifdef notused}
  1320. function is_mov_for_div(p: taicpu): boolean;
  1321. begin
  1322. is_mov_for_div :=
  1323. (p.opcode = A_MOV) and
  1324. (p.oper[0]^.typ = top_const) and
  1325. (p.oper[1]^.typ = top_reg) and
  1326. (p.oper[1]^.reg = RS_EDX) and
  1327. getNextInstruction(p,p) and
  1328. (p.typ = ait_instruction) and
  1329. ((p.opcode = A_DIV) or
  1330. (p.opcode = A_IDIV));
  1331. end;
  1332. {$endif notused}
  1333. function memtoreg(t: taicpu; const ref: treference; var startp: tai): tregister;
  1334. var
  1335. hp: tai;
  1336. p: ptaiprop;
  1337. regcounter: tsuperregister;
  1338. optimizable: boolean;
  1339. begin
  1340. if not getlastinstruction(t,hp) or
  1341. not issimplememloc(ref) then
  1342. begin
  1343. memtoreg := NR_NO;
  1344. exit;
  1345. end;
  1346. p := ptaiprop(hp.optinfo);
  1347. optimizable := false;
  1348. for regcounter := RS_EAX to RS_EDI do
  1349. begin
  1350. if (assigned(p^.regs[regcounter].memwrite) and
  1351. refsequal(ref,p^.regs[regcounter].memwrite.oper[1]^.ref^)) then
  1352. begin
  1353. optimizable := true;
  1354. hp := p^.regs[regcounter].memwrite;
  1355. end
  1356. else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
  1357. (p^.regs[regcounter].nrofmods = 1) and
  1358. ((taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
  1359. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
  1360. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
  1361. (taicpu(p^.regs[regcounter].startmod).oper[0]^.typ = top_ref) and
  1362. refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0]^.ref^)) then
  1363. begin
  1364. optimizable := true;
  1365. hp := p^.regs[regcounter].startmod;
  1366. end;
  1367. if optimizable then
  1368. if ((t.opsize <> S_B) or
  1369. not(regcounter in [RS_ESI,RS_EDI])) and
  1370. sizescompatible(taicpu(hp).opsize,t.opsize) then
  1371. begin
  1372. case t.opsize of
  1373. S_B:
  1374. begin
  1375. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBL)
  1376. end;
  1377. S_W,S_BW:
  1378. begin
  1379. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBW);
  1380. if (t.opsize = S_BW) then
  1381. begin
  1382. t.opcode := A_MOV;
  1383. t.opsize := S_W;
  1384. end;
  1385. end;
  1386. S_L,S_BL,S_WL:
  1387. begin
  1388. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBWHOLE);
  1389. if (t.opsize <> S_L) then
  1390. begin
  1391. t.opcode := A_MOV;
  1392. t.opsize := S_L;
  1393. end;
  1394. end;
  1395. end;
  1396. startp := hp;
  1397. exit;
  1398. end;
  1399. end;
  1400. memtoreg := NR_NO;
  1401. end;
  1402. procedure removeLocalStores(const t1: tai);
  1403. {var
  1404. p: tai;
  1405. regcount: tregister; }
  1406. begin
  1407. {
  1408. for regcount := LoGPReg to HiGPReg do
  1409. if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
  1410. (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1]^.ref^.base
  1411. = current_procinfo.framepointer) then
  1412. begin
  1413. pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
  1414. clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
  1415. end;
  1416. }
  1417. end;
  1418. procedure loadcseregs(asml: taasmoutput; const reginfo: toptreginfo; curseqend, prevseqstart, curseqstart, curprev: tai; cnt: longint);
  1419. var
  1420. regsloaded: tregset;
  1421. regloads: array[RS_EAX..RS_EDI] of tai;
  1422. regcounter: tsuperregister;
  1423. hp, hp2: tai;
  1424. insertpos, prevseq_next: tai;
  1425. i: longint;
  1426. begin
  1427. regsloaded := [];
  1428. fillchar(regloads,sizeof(regloads),0);
  1429. getnextinstruction(prevseqstart,prevseq_next);
  1430. for regcounter := RS_EAX To RS_EDI do
  1431. if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
  1432. begin
  1433. include(regsloaded,regcounter);
  1434. AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
  1435. ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart);
  1436. if curprev <> prevseqstart then
  1437. begin
  1438. if assigned(reginfo.lastReload[regCounter]) then
  1439. getLastInstruction(reginfo.lastReload[regCounter],hp)
  1440. else if assigned(reginfo.lastReload[reginfo.new2oldreg[regCounter]]) then
  1441. getLastInstruction(reginfo.lastReload[reginfo.new2OldReg[regCounter]],hp)
  1442. else
  1443. hp := curprev;
  1444. clearRegContentsFrom(regCounter,prevSeq_next,hp);
  1445. getnextInstruction(hp,hp);
  1446. allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp);
  1447. end;
  1448. if not(regcounter in reginfo.RegsLoadedforRef) and
  1449. {old reg new reg}
  1450. (reginfo.new2oldreg[regcounter] <> regcounter) then
  1451. begin
  1452. getLastInstruction(curseqend,hp);
  1453. if (curprev <> prevseqstart) or
  1454. {not(regCounter in rg.usableregsint + [RS_EDI,RS_ESI]) or}
  1455. not(regCounter in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_EDI,RS_ESI]) or
  1456. not ReplaceReg(asml,reginfo.new2oldreg[regcounter],
  1457. regCounter,hp,
  1458. ptaiprop(prevseqstart.optinfo)^.Regs[regCounter],true,hp2) then
  1459. begin
  1460. if not(reginfo.new2oldreg[regcounter] in regsloaded) or
  1461. { happens if the register has been replaced }
  1462. not(assigned(regloads[reginfo.new2oldreg[regcounter]])) then
  1463. insertpos := prevseq_next
  1464. else
  1465. begin
  1466. {$warning add cycle detection for register loads and use xchg if necessary}
  1467. insertpos := regloads[reginfo.new2oldreg[regcounter]];
  1468. end;
  1469. hp := Tai_Marker.Create(NoPropInfoStart);
  1470. InsertLLItem(asml, insertpos.previous,insertpos, hp);
  1471. hp2 := taicpu.Op_Reg_Reg(A_MOV, S_L,
  1472. {old reg new reg}
  1473. newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
  1474. regloads[regcounter] := hp2;
  1475. new(ptaiprop(hp2.optinfo));
  1476. ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
  1477. ptaiprop(hp2.optinfo)^.canBeRemoved := false;
  1478. InsertLLItem(asml, insertpos.previous, insertpos, hp2);
  1479. hp := Tai_Marker.Create(NoPropInfoEnd);
  1480. InsertLLItem(asml, insertpos.previous, insertpos, hp);
  1481. { adjusts states in previous instruction so that it will }
  1482. { definitely be different from the previous or next state }
  1483. incstate(ptaiprop(hp2.optinfo)^.
  1484. regs[reginfo.new2oldreg[regcounter]].rstate,20);
  1485. incstate(ptaiprop(hp2.optinfo)^.
  1486. regs[regCounter].wstate,20);
  1487. updateState(reginfo.new2oldreg[regcounter],hp2);
  1488. updateState(regcounter,hp2);
  1489. end
  1490. end
  1491. else
  1492. { imagine the following code: }
  1493. { normal wrong optimized }
  1494. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  1495. { movl (%eax), %eax movl (%eax), %eax }
  1496. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  1497. { jne l1 jne l1 }
  1498. { movl 8(%ebp), %eax }
  1499. { movl (%eax), %edi movl %eax, %edi }
  1500. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  1501. { movl 8(%ebp), %eax }
  1502. { pushl 70(%eax) pushl 70(%eax) }
  1503. { }
  1504. { The error is that at the moment that the last instruction is executed, }
  1505. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  1506. { registers that are completely removed from a sequence (= registers in }
  1507. { RegLoadedforRef), have to be changed to their contents from before the }
  1508. { sequence. }
  1509. { if regcounter in reginfo.RegsLoadedforRef then }
  1510. begin
  1511. hp := curseqstart;
  1512. { cnt still holds the number of instructions }
  1513. { of the sequence, so go to the end of it }
  1514. for i := 1 to pred(cnt) do
  1515. getNextInstruction(hp,hp);
  1516. { curprev = instruction prior to start of sequence }
  1517. restoreRegContentsTo(regCounter,
  1518. ptaiprop(curprev.optinfo)^.Regs[regcounter],
  1519. curseqstart,hp);
  1520. end;
  1521. end;
  1522. end;
  1523. procedure doCSE(asml: TAAsmOutput; First, Last: tai; findPrevSeqs, doSubOpts: boolean);
  1524. {marks the instructions that can be removed by RemoveInstructs. They're not
  1525. removed immediately because sometimes an instruction needs to be checked in
  1526. two different sequences}
  1527. var cnt, cnt2, {cnt3,} orgNrofMods: longint;
  1528. p, hp1, hp2, prevSeq: tai;
  1529. hp3, hp4: tai;
  1530. hp5 : tai;
  1531. reginfo: toptreginfo;
  1532. memreg: tregister;
  1533. regcounter: tsuperregister;
  1534. begin
  1535. p := First;
  1536. SkipHead(p);
  1537. while (p <> Last) do
  1538. begin
  1539. case p.typ of
  1540. ait_align:
  1541. if not(tai_align(p).use_op) then
  1542. SetAlignReg(p);
  1543. ait_instruction:
  1544. begin
  1545. case taicpu(p).opcode of
  1546. A_CALL:
  1547. for regCounter := RS_EAX to RS_EBX do
  1548. removePrevNotUsedLoad(p,regCounter,true);
  1549. A_CLD: if GetLastInstruction(p, hp1) and
  1550. (ptaiprop(hp1.optinfo)^.DirFlag = F_NotSet) then
  1551. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1552. A_LEA, A_MOV, A_MOVZX, A_MOVSX:
  1553. begin
  1554. hp2 := p;
  1555. case taicpu(p).oper[0]^.typ of
  1556. top_ref, top_reg:
  1557. if (taicpu(p).oper[1]^.typ = top_reg) then
  1558. begin
  1559. With ptaiprop(p.optinfo)^.Regs[getsupreg(taicpu(p).oper[1]^.reg)] do
  1560. begin
  1561. if (startmod = p) then
  1562. orgNrofMods := nrofMods
  1563. else
  1564. orgNrofMods := 0;
  1565. if (p = StartMod) and
  1566. GetLastInstruction (p, hp1) and
  1567. not(hp1.typ in [ait_marker,ait_label]) then
  1568. {so we don't try to check a sequence when p is the first instruction of the block}
  1569. begin
  1570. {$ifdef csdebug}
  1571. hp5 := tai_comment.Create(strpnew(
  1572. 'cse checking '+std_reg2str[getsupreg(taicpu(p).oper[1]^.reg)])));
  1573. insertLLItem(asml,p,p.next,hp5);
  1574. {$endif csdebug}
  1575. if CheckSequence(p,prevSeq,getsupreg(taicpu(p).oper[1]^.reg), Cnt, reginfo, findPrevSeqs) and
  1576. (Cnt > 0) then
  1577. begin
  1578. (*
  1579. hp1 := nil;
  1580. { although it's perfectly ok to remove an instruction which doesn't contain }
  1581. { the register that we've just checked (CheckSequence takes care of that), }
  1582. { the sequence containing this other register should also be completely }
  1583. { checked and removed, otherwise we may get situations like this: }
  1584. { }
  1585. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  1586. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  1587. { movl 8(%edx), %edx movl 8(%edx), %edx }
  1588. { movl (%eax), eax movl (%eax), eax }
  1589. { cmpl %eax, %edx cmpl %eax, %edx }
  1590. { jnz l123 getting converted to jnz l123 }
  1591. { movl 12(%ebp), %edx movl 4(%eax), eax }
  1592. { movl 16(%ebp), %eax }
  1593. { movl 8(%edx), %edx }
  1594. { movl 4(%eax), eax }
  1595. *)
  1596. { not anymore: if the start of a new sequence is found while checking (e.g. }
  1597. { above that of eax while checking edx, this new sequence is automatically }
  1598. { also checked }
  1599. Cnt2 := 1;
  1600. while Cnt2 <= Cnt do
  1601. begin
  1602. (*
  1603. if not(regInInstruction(getsupreg(taicpu(hp2).oper[1]^.reg), p)) and
  1604. not(ptaiprop(p.optinfo)^.canBeRemoved) then
  1605. begin
  1606. if (p.typ = ait_instruction) and
  1607. ((taicpu(p).OpCode = A_MOV) or
  1608. (taicpu(p).opcode = A_MOVZX) or
  1609. (taicpu(p).opcode = A_MOVSX)) and
  1610. (taicpu(p).oper[1]^.typ = top_reg) then
  1611. if not is_mov_for_div(taicpu(p)) then
  1612. begin
  1613. regCounter := getsupreg(taicpu(p).oper[1]^.reg);
  1614. if (regCounter in reginfo.regsStillUsedAfterSeq) then
  1615. begin
  1616. if (hp1 = nil) then
  1617. hp1 := reginfo.lastReload[regCounter];
  1618. end
  1619. {$ifndef noremove}
  1620. else
  1621. begin
  1622. hp5 := p;
  1623. for cnt3 := ptaiprop(p.optinfo)^.regs[regCounter].nrofmods downto 1 do
  1624. begin
  1625. if regModifiedByInstruction(regCounter,hp5) then
  1626. ptaiprop(hp5.optinfo)^.CanBeRemoved := True;
  1627. getNextInstruction(hp5,hp5);
  1628. end;
  1629. end
  1630. {$endif noremove}
  1631. end
  1632. {$ifndef noremove}
  1633. else
  1634. ptaiprop(p.optinfo)^.CanBeRemoved := True
  1635. {$endif noremove}
  1636. end
  1637. *)
  1638. {$ifndef noremove}
  1639. (* else *)
  1640. ptaiprop(p.optinfo)^.CanBeRemoved := True
  1641. {$endif noremove}
  1642. ; inc(Cnt2);
  1643. GetNextInstruction(p, p);
  1644. end;
  1645. {hp4 is used to get the contents of the registers before the sequence}
  1646. GetLastInstruction(hp2, hp4);
  1647. {$IfDef CSDebug}
  1648. for regcounter := RS_EAX To RS_EDI do
  1649. if (regcounter in reginfo.RegsLoadedforRef) then
  1650. begin
  1651. hp5 := tai_comment.Create(strpnew('New: '+std_reg2str[regcounter]+', Old: '+
  1652. std_reg2str[reginfo.new2oldreg[regcounter]])));
  1653. InsertLLItem(asml, tai(hp2.previous), hp2, hp5);
  1654. end;
  1655. {$EndIf CSDebug}
  1656. { if some registers were different in the old and the new sequence, move }
  1657. { the contents of those old registers to the new ones }
  1658. loadcseregs(asml,reginfo,p,prevseq,hp2,hp4,cnt);
  1659. continue;
  1660. end
  1661. (*
  1662. else
  1663. if (ptaiprop(p.optinfo)^.
  1664. regs[getsupreg(taicpu(p).oper[1]^.reg)].typ
  1665. in [con_ref,con_noRemoveRef]) and
  1666. (ptaiprop(p.optinfo)^.CanBeRemoved) then
  1667. if (cnt > 0) then
  1668. begin
  1669. p := hp2;
  1670. Cnt2 := 1;
  1671. while Cnt2 <= Cnt do
  1672. begin
  1673. if RegInInstruction(getsupregtaicpu(hp2).oper[1]^.reg), p) then
  1674. ptaiprop(p.optinfo)^.CanBeRemoved := False;
  1675. inc(Cnt2);
  1676. GetNextInstruction(p, p);
  1677. end;
  1678. Continue;
  1679. end
  1680. else
  1681. begin
  1682. { Fix for web bug 972 }
  1683. regCounter := getsupreg(taicpu(p).oper[1]^.reg);
  1684. cnt := ptaiprop(p.optinfo)^.Regs[regCounter].nrofMods;
  1685. hp3 := p;
  1686. for cnt2 := 1 to cnt do
  1687. if not(regModifiedByInstruction(regCounter,hp3) and
  1688. not(ptaiprop(hp3.optinfo)^.canBeRemoved)) then
  1689. getNextInstruction(hp3,hp3)
  1690. else
  1691. break;
  1692. getLastInstruction(p,hp4);
  1693. RestoreRegContentsTo(regCounter,
  1694. ptaiprop(hp4.optinfo)^.Regs[regCounter],
  1695. p,hp3);
  1696. end;
  1697. *)
  1698. end;
  1699. end;
  1700. { try to replace the new reg with the old reg }
  1701. if not(ptaiprop(p.optinfo)^.canBeRemoved) then
  1702. if (taicpu(p).oper[0]^.typ = top_reg) and
  1703. (taicpu(p).oper[1]^.typ = top_reg) and
  1704. { only remove if we're not storing something in a regvar }
  1705. (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) and
  1706. { (taicpu(p).oper[1]^.reg in (rg.usableregsint+[RS_EDI])) and}
  1707. (taicpu(p).opcode = A_MOV) and
  1708. getLastInstruction(p,hp4) and
  1709. { we only have to start replacing from the instruction after the mov, }
  1710. { but replacereg only starts with getnextinstruction(p,p) }
  1711. replaceReg(asml,getsupreg(taicpu(p).oper[0]^.reg),
  1712. getsupreg(taicpu(p).oper[1]^.reg),p,
  1713. ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
  1714. begin
  1715. ptaiprop(p.optinfo)^.canBeRemoved := true;
  1716. allocRegBetween(asml,taicpu(p).oper[0]^.reg,
  1717. pTaiProp(p.optinfo)^.regs[getsupreg(taicpu(p).oper[0]^.reg)].startMod,hp1);
  1718. end
  1719. else
  1720. begin
  1721. if (taicpu(p).oper[1]^.typ = top_reg) and
  1722. not regInOp(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^) then
  1723. removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1724. if doSubOpts and
  1725. (taicpu(p).opcode <> A_LEA) and
  1726. (taicpu(p).oper[0]^.typ = top_ref) then
  1727. begin
  1728. memreg :=
  1729. memtoreg(taicpu(p),
  1730. taicpu(p).oper[0]^.ref^,hp5);
  1731. if memreg <> NR_NO then
  1732. if (taicpu(p).opcode = A_MOV) and
  1733. (taicpu(p).oper[1]^.typ = top_reg) and
  1734. (taicpu(p).oper[1]^.reg = memreg) then
  1735. begin
  1736. pTaiProp(p.optinfo)^.canberemoved := true;
  1737. allocregbetween(asml,memreg,hp5,p);
  1738. end
  1739. else
  1740. begin
  1741. taicpu(p).loadreg(0,memreg);
  1742. allocregbetween(asml,memreg,hp5,p);
  1743. regcounter := getsupreg(memreg);
  1744. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1745. updatestate(regcounter,p);
  1746. end;
  1747. end;
  1748. end;
  1749. { at first, only try optimizations of large blocks, because doing }
  1750. { doing smaller ones may prevent bigger ones from completing in }
  1751. { in the next pass }
  1752. if not doSubOpts and (orgNrofMods <> 0) then
  1753. begin
  1754. p := hp2;
  1755. for cnt := 1 to pred(orgNrofMods) do
  1756. getNextInstruction(p,p);
  1757. end;
  1758. end;
  1759. top_symbol,Top_Const:
  1760. begin
  1761. case taicpu(p).oper[1]^.typ of
  1762. Top_Reg:
  1763. begin
  1764. regCounter := getsupreg(taicpu(p).oper[1]^.reg);
  1765. if GetLastInstruction(p, hp1) then
  1766. With ptaiprop(hp1.optinfo)^.Regs[regCounter] do
  1767. if (typ in [con_const,con_noRemoveConst]) and
  1768. (taicpu(startMod).opsize >= taicpu(p).opsize) and
  1769. opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
  1770. begin
  1771. ptaiprop(p.optinfo)^.CanBeRemoved := True;
  1772. allocRegBetween(asml,taicpu(p).oper[1]^.reg,startMod,p);
  1773. end
  1774. else
  1775. removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1776. end;
  1777. Top_Ref:
  1778. if (taicpu(p).oper[0]^.typ = top_const) and
  1779. getLastInstruction(p,hp1) and
  1780. findRegWithConst(hp1,taicpu(p).opsize,taicpu(p).oper[0]^.val,memreg) then
  1781. begin
  1782. taicpu(p).loadreg(0,memreg);
  1783. allocRegBetween(asml,memreg,
  1784. ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p);
  1785. end;
  1786. end;
  1787. end;
  1788. end;
  1789. end;
  1790. A_LEAVE:
  1791. begin
  1792. if getlastinstruction(p,hp1) then
  1793. removeLocalStores(hp1);
  1794. end;
  1795. A_STD: if GetLastInstruction(p, hp1) and
  1796. (ptaiprop(hp1.optinfo)^.DirFlag = F_Set) then
  1797. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1798. else
  1799. begin
  1800. for cnt := 1 to maxch do
  1801. begin
  1802. case InsProp[taicpu(p).opcode].Ch[cnt] of
  1803. Ch_ROp1:
  1804. if (taicpu(p).oper[0]^.typ = top_ref) and
  1805. ((taicpu(p).opcode < A_F2XM1) or
  1806. ((taicpu(p).opcode > A_IN) and
  1807. (taicpu(p).opcode < A_OUT)) or
  1808. (taicpu(p).opcode = A_PUSH) or
  1809. ((taicpu(p).opcode >= A_RCL) and
  1810. (taicpu(p).opcode <= A_XOR))) then
  1811. begin
  1812. memreg :=
  1813. memtoreg(taicpu(p),
  1814. taicpu(p).oper[0]^.ref^,hp5);
  1815. if memreg <> NR_NO then
  1816. begin
  1817. taicpu(p).loadreg(0,memreg);
  1818. allocregbetween(asml,memreg,hp5,p);
  1819. regcounter := getsupreg(memreg);
  1820. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1821. updatestate(regcounter,p);
  1822. end;
  1823. end;
  1824. Ch_MOp1:
  1825. if not(CS_LittleSize in aktglobalswitches) and
  1826. (taicpu(p).oper[0]^.typ = top_ref) then
  1827. begin
  1828. memreg :=
  1829. memtoreg(taicpu(p),
  1830. taicpu(p).oper[0]^.ref^,hp5);
  1831. if (memreg <> NR_NO) and
  1832. (not getNextInstruction(p,hp1) or
  1833. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  1834. FindRegDealloc(getsupreg(memreg),hp1))) then
  1835. begin
  1836. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1837. insertllitem(asml,p,p.next,hp1);
  1838. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  1839. memreg,taicpu(p).oper[0]^.ref^);
  1840. new(ptaiprop(hp1.optinfo));
  1841. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1842. insertllitem(asml,p,p.next,hp1);
  1843. regcounter := getsupreg(memreg);
  1844. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  1845. updatestate(regcounter,hp1);
  1846. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1847. insertllitem(asml,p,p.next,hp1);
  1848. taicpu(p).loadreg(0,memreg);
  1849. allocregbetween(asml,memreg,hp5,
  1850. tai(p.next.next));
  1851. end;
  1852. end;
  1853. Ch_ROp2:
  1854. if ((taicpu(p).opcode = A_CMP) or
  1855. (taicpu(p).opcode = A_TEST)) and
  1856. (taicpu(p).oper[1]^.typ = top_ref) then
  1857. begin
  1858. memreg :=
  1859. memtoreg(taicpu(p),
  1860. taicpu(p).oper[1]^.ref^,hp5);
  1861. if memreg <> NR_NO then
  1862. begin
  1863. taicpu(p).loadreg(1,memreg);
  1864. allocregbetween(asml,memreg,hp5,p);
  1865. regcounter := getsupreg(memreg);
  1866. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1867. updatestate(regcounter,p);
  1868. end;
  1869. end;
  1870. Ch_MOp2:
  1871. if not(cs_littlesize in aktglobalswitches) and
  1872. (taicpu(p).oper[1]^.typ = top_ref) and
  1873. ((taicpu(p).opcode < A_BT) or
  1874. ((taicpu(p).opcode > A_IN) and
  1875. (taicpu(p).opcode < A_OUT)) or
  1876. (taicpu(p).opcode = A_PUSH) or
  1877. ((taicpu(p).opcode >= A_RCL) and
  1878. (taicpu(p).opcode <= A_XOR))) then
  1879. begin
  1880. memreg :=
  1881. memtoreg(taicpu(p),
  1882. taicpu(p).oper[1]^.ref^,hp5);
  1883. if (memreg <> NR_NO) and
  1884. (not getNextInstruction(p,hp1) or
  1885. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  1886. FindRegDealloc(getsupreg(regcounter),hp1))) then
  1887. begin
  1888. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1889. insertllitem(asml,p,p.next,hp1);
  1890. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  1891. memreg,taicpu(p).oper[1]^.ref^);
  1892. new(ptaiprop(hp1.optinfo));
  1893. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1894. insertllitem(asml,p,p.next,hp1);
  1895. regcounter := getsupreg(memreg);
  1896. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  1897. updatestate(regcounter,hp1);
  1898. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1899. insertllitem(asml,p,p.next,hp1);
  1900. taicpu(p).loadreg(1,memreg);
  1901. allocregbetween(asml,memreg,hp5,
  1902. tai(p.next.next));
  1903. end;
  1904. end;
  1905. end;
  1906. end;
  1907. end;
  1908. end
  1909. end;
  1910. end;
  1911. GetNextInstruction(p, p);
  1912. end;
  1913. end;
  1914. function removeInstructs(asml: TAAsmoutput; first, last: tai): boolean;
  1915. { Removes the marked instructions and disposes the PTaiProps of the other }
  1916. { instructions }
  1917. var
  1918. p, hp1: tai;
  1919. nopropinfolevel: longint;
  1920. begin
  1921. removeInstructs := false;
  1922. p := First;
  1923. nopropinfolevel := 0;
  1924. while (p <> Last) do
  1925. begin
  1926. if (p.typ = ait_marker) and
  1927. (Tai_marker(p).kind = noPropInfoStart) then
  1928. begin
  1929. hp1 := tai(p.next);
  1930. asml.remove(p);
  1931. p.free;
  1932. nopropinfolevel := 1;
  1933. while (nopropinfolevel <> 0) do
  1934. begin
  1935. p := tai(hp1.next);
  1936. {$ifndef noinstremove}
  1937. { allocregbetween can insert new ait_regalloc objects }
  1938. { without optinfo }
  1939. if (hp1.typ = ait_marker) then
  1940. begin
  1941. case Tai_marker(hp1).kind of
  1942. { they can be nested! }
  1943. noPropInfoStart: inc(nopropinfolevel);
  1944. noPropInfoEnd: dec(nopropinfolevel);
  1945. else
  1946. begin
  1947. hp1 := p;
  1948. continue;
  1949. end;
  1950. end;
  1951. asml.remove(hp1);
  1952. hp1.free;
  1953. end
  1954. else if assigned(hp1.optinfo) then
  1955. if ptaiprop(hp1.optinfo)^.canBeRemoved then
  1956. begin
  1957. dispose(ptaiprop(hp1.optinfo));
  1958. hp1.optinfo := nil;
  1959. asml.remove(hp1);
  1960. hp1.free;
  1961. end
  1962. else
  1963. {$endif noinstremove}
  1964. begin
  1965. dispose(ptaiprop(hp1.optinfo));
  1966. hp1.optinfo := nil;
  1967. end;
  1968. hp1 := p;
  1969. end;
  1970. end
  1971. else
  1972. {$ifndef noinstremove}
  1973. if assigned(p.optinfo) and
  1974. ptaiprop(p.optinfo)^.canBeRemoved then
  1975. begin
  1976. hp1 := tai(p.next);
  1977. asml.Remove(p);
  1978. p.free;
  1979. p := hp1;
  1980. removeInstructs := true;
  1981. end
  1982. else
  1983. {$endif noinstremove}
  1984. begin
  1985. p.optinfo := nil;
  1986. p := tai(p.next);;
  1987. end;
  1988. end;
  1989. end;
  1990. function CSE(asml: TAAsmOutput; First, Last: tai; pass: longint): boolean;
  1991. begin
  1992. doCSE(asml, First, Last, not(cs_slowoptimize in aktglobalswitches) or (pass >= 2),
  1993. not(cs_slowoptimize in aktglobalswitches) or (pass >= 1));
  1994. { register renaming }
  1995. if not(cs_slowoptimize in aktglobalswitches) or (pass > 0) then
  1996. doRenaming(asml, first, last);
  1997. cse := removeInstructs(asml, first, last);
  1998. end;
  1999. end.
  2000. {
  2001. $Log$
  2002. Revision 1.52 2003-11-28 18:49:05 jonas
  2003. * fixed bug which only showed up in the ppc crosscompiler :)
  2004. Revision 1.51 2003/11/22 13:10:32 jonas
  2005. * fixed double unit usage
  2006. Revision 1.50 2003/11/22 00:40:19 jonas
  2007. * fixed optimiser so it compiles again
  2008. * fixed several bugs which were in there already for a long time, but
  2009. which only popped up now :) -O2/-O3 will now optimise less than in
  2010. the past (and correctly so), but -O2u/-O3u will optimise a bit more
  2011. * some more small improvements for -O3 are still possible
  2012. Revision 1.49 2003/07/24 10:45:40 jonas
  2013. * fixed nil pointer access
  2014. Revision 1.48 2003/06/08 18:48:03 jonas
  2015. * first small steps towards an oop optimizer
  2016. Revision 1.47 2003/06/03 21:09:05 peter
  2017. * internal changeregsize for optimizer
  2018. * fix with a hack to not remove the first instruction of a block
  2019. which will leave blockstart pointing to invalid memory
  2020. Revision 1.46 2003/05/30 23:57:08 peter
  2021. * more sparc cleanup
  2022. * accumulator removed, splitted in function_return_reg (called) and
  2023. function_result_reg (caller)
  2024. Revision 1.45 2003/05/16 14:33:31 peter
  2025. * regvar fixes
  2026. Revision 1.44 2003/04/27 11:21:35 peter
  2027. * aktprocdef renamed to current_procdef
  2028. * procinfo renamed to current_procinfo
  2029. * procinfo will now be stored in current_module so it can be
  2030. cleaned up properly
  2031. * gen_main_procsym changed to create_main_proc and release_main_proc
  2032. to also generate a tprocinfo structure
  2033. * fixed unit implicit initfinal
  2034. Revision 1.43 2003/03/28 19:16:57 peter
  2035. * generic constructor working for i386
  2036. * remove fixed self register
  2037. * esi added as address register for i386
  2038. Revision 1.42 2003/03/18 18:15:53 peter
  2039. * changed reg2opsize to function
  2040. Revision 1.41 2003/02/26 21:15:43 daniel
  2041. * Fixed the optimizer
  2042. Revision 1.40 2003/02/19 22:00:15 daniel
  2043. * Code generator converted to new register notation
  2044. - Horribily outdated todo.txt removed
  2045. Revision 1.39 2003/01/08 18:43:57 daniel
  2046. * Tregister changed into a record
  2047. Revision 1.38 2002/08/18 20:06:29 peter
  2048. * inlining is now also allowed in interface
  2049. * renamed write/load to ppuwrite/ppuload
  2050. * tnode storing in ppu
  2051. * nld,ncon,nbas are already updated for storing in ppu
  2052. Revision 1.37 2002/08/17 09:23:44 florian
  2053. * first part of procinfo rewrite
  2054. Revision 1.36 2002/07/01 18:46:31 peter
  2055. * internal linker
  2056. * reorganized aasm layer
  2057. Revision 1.35 2002/05/18 13:34:22 peter
  2058. * readded missing revisions
  2059. Revision 1.34 2002/05/16 19:46:51 carl
  2060. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2061. + try to fix temp allocation (still in ifdef)
  2062. + generic constructor calls
  2063. + start of tassembler / tmodulebase class cleanup
  2064. Revision 1.32 2002/04/21 15:32:59 carl
  2065. * changeregsize -> rg.makeregsize
  2066. Revision 1.31 2002/04/20 21:37:07 carl
  2067. + generic FPC_CHECKPOINTER
  2068. + first parameter offset in stack now portable
  2069. * rename some constants
  2070. + move some cpu stuff to other units
  2071. - remove unused constents
  2072. * fix stacksize for some targets
  2073. * fix generic size problems which depend now on EXTEND_SIZE constant
  2074. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  2075. Revision 1.30 2002/04/15 19:44:20 peter
  2076. * fixed stackcheck that would be called recursively when a stack
  2077. error was found
  2078. * generic changeregsize(reg,size) for i386 register resizing
  2079. * removed some more routines from cga unit
  2080. * fixed returnvalue handling
  2081. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  2082. Revision 1.29 2002/04/15 19:12:09 carl
  2083. + target_info.size_of_pointer -> pointer_size
  2084. + some cleanup of unused types/variables
  2085. * move several constants from cpubase to their specific units
  2086. (where they are used)
  2087. + att_Reg2str -> gas_reg2str
  2088. + int_reg2str -> std_reg2str
  2089. Revision 1.28 2002/04/14 17:00:49 carl
  2090. + att_reg2str -> std_reg2str
  2091. Revision 1.27 2002/04/04 19:06:10 peter
  2092. * removed unused units
  2093. * use tlocation.size in cg.a_*loc*() routines
  2094. Revision 1.26 2002/04/02 17:11:34 peter
  2095. * tlocation,treference update
  2096. * LOC_CONSTANT added for better constant handling
  2097. * secondadd splitted in multiple routines
  2098. * location_force_reg added for loading a location to a register
  2099. of a specified size
  2100. * secondassignment parses now first the right and then the left node
  2101. (this is compatible with Kylix). This saves a lot of push/pop especially
  2102. with string operations
  2103. * adapted some routines to use the new cg methods
  2104. Revision 1.25 2002/03/31 20:26:38 jonas
  2105. + a_loadfpu_* and a_loadmm_* methods in tcg
  2106. * register allocation is now handled by a class and is mostly processor
  2107. independent (+rgobj.pas and i386/rgcpu.pas)
  2108. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  2109. * some small improvements and fixes to the optimizer
  2110. * some register allocation fixes
  2111. * some fpuvaroffset fixes in the unary minus node
  2112. * push/popusedregisters is now called rg.save/restoreusedregisters and
  2113. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  2114. also better optimizable)
  2115. * fixed and optimized register saving/restoring for new/dispose nodes
  2116. * LOC_FPU locations now also require their "register" field to be set to
  2117. RS_ST, not RS_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  2118. - list field removed of the tnode class because it's not used currently
  2119. and can cause hard-to-find bugs
  2120. Revision 1.24 2002/03/04 19:10:12 peter
  2121. * removed compiler warnings
  2122. }