csopt386.pas 87 KB

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