csopt386.pas 90 KB

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