csopt386.pas 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179
  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 defines.inc}
  21. Interface
  22. Uses aasm, cpuinfo, cpubase, cpuasm;
  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, 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];
  325. new2OldReg[procinfo^.FramePointer] := procinfo^.FramePointer;
  326. new2OldReg[stack_pointer] := stack_pointer;
  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. gas_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. gas_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(gas_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 '+gas_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 '+gas_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 '+gas_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 '+gas_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 = regtoreg8(newReg) then
  785. reg := regtoreg8(orgReg)
  786. else if reg = regtoreg16(newReg) then
  787. reg := regtoreg16(orgReg)
  788. else changeReg := false;
  789. end;
  790. function changeOp(var o: toper; newReg, orgReg: tregister): boolean;
  791. var
  792. tmpresult: boolean;
  793. begin
  794. changeOp := false;
  795. case o.typ of
  796. top_reg: changeOp := changeReg(o.reg,newReg,orgReg);
  797. top_ref:
  798. begin
  799. tmpresult := changeReg(o.ref^.base,newReg,orgReg);
  800. changeop := changeReg(o.ref^.index,newReg,orgReg) or tmpresult;
  801. end;
  802. end;
  803. end;
  804. procedure updateStates(orgReg,newReg: tregister; hp: Tai; writeStateToo: boolean);
  805. var
  806. prev: Tai;
  807. newOrgRegRState, newOrgRegWState: byte;
  808. begin
  809. if getLastInstruction(hp,prev) then
  810. with pTaiprop(prev.optinfo)^ do
  811. begin
  812. {$ifopt r+}
  813. {$define rangeon}
  814. {$r-}
  815. {$endif}
  816. newOrgRegRState := regs[orgReg].rState +
  817. pTaiprop(hp.optinfo)^.regs[newReg].rState - regs[newReg].rstate;
  818. if writeStateToo then
  819. newOrgRegWState := regs[orgReg].wState +
  820. pTaiprop(hp.optinfo)^.regs[newReg].wState - regs[newReg].wstate;
  821. {$ifdef rangeon}
  822. {$undef rangeon}
  823. {$r+}
  824. {$endif}
  825. end
  826. else
  827. with pTaiprop(hp.optinfo)^.regs[newReg] do
  828. begin
  829. newOrgRegRState := rState;
  830. if writeStateToo then
  831. newOrgRegWState := wState;
  832. end;
  833. with pTaiprop(hp.optinfo)^.regs[orgReg] do
  834. begin
  835. rState := newOrgRegRState;
  836. if writeStateToo then
  837. wState := newOrgRegwState;
  838. end;
  839. end;
  840. function doReplaceReg(hp: Taicpu; newReg, orgReg: tregister): boolean;
  841. var
  842. opCount: longint;
  843. tmpResult: boolean;
  844. begin
  845. for opCount := 0 to hp.ops-1 do
  846. tmpResult :=
  847. changeOp(hp.oper[opCount],newReg,orgReg) or tmpResult;
  848. doReplaceReg := tmpResult;
  849. end;
  850. function RegSizesOK(oldReg,newReg: TRegister; p: Taicpu): boolean;
  851. { oldreg and newreg must be 32bit components }
  852. var opCount: byte;
  853. begin
  854. RegSizesOK := true;
  855. { if only one of them is a general purpose register ... }
  856. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  857. begin
  858. for opCount := 0 to 2 do
  859. if (p.oper[opCount].typ = top_reg) and
  860. (p.oper[opCount].reg in [R_AL..R_DH]) then
  861. begin
  862. RegSizesOK := false;
  863. break
  864. end
  865. end;
  866. end;
  867. function doReplaceReadReg(p: Taicpu; newReg,orgReg: tregister): boolean;
  868. var opCount: byte;
  869. begin
  870. doReplaceReadReg := false;
  871. { handle special case }
  872. case p.opcode of
  873. A_IMUL:
  874. begin
  875. case p.ops of
  876. 1: internalerror(1301001);
  877. 2,3:
  878. begin
  879. if changeOp(p.oper[0],newReg,orgReg) then
  880. begin
  881. { updateStates(orgReg,newReg,p,false);}
  882. doReplaceReadReg := true;
  883. end;
  884. if p.ops = 3 then
  885. if changeOp(p.oper[1],newReg,orgReg) then
  886. begin
  887. { updateStates(orgReg,newReg,p,false);}
  888. doReplaceReadReg := true;
  889. end;
  890. end;
  891. end;
  892. end;
  893. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  894. else
  895. begin
  896. for opCount := 0 to 2 do
  897. if p.oper[opCount].typ = top_ref then
  898. if changeOp(p.oper[opCount],newReg,orgReg) then
  899. begin
  900. { updateStates(orgReg,newReg,p,false);}
  901. doReplaceReadReg := true;
  902. end;
  903. for opCount := 1 to MaxCh do
  904. case InsProp[p.opcode].Ch[opCount] of
  905. Ch_ROp1:
  906. if p.oper[0].typ = top_reg then
  907. if changeReg(p.oper[0].reg,newReg,orgReg) then
  908. begin
  909. { updateStates(orgReg,newReg,p,false);}
  910. doReplaceReadReg := true;
  911. end;
  912. Ch_ROp2:
  913. if p.oper[1].typ = top_reg then
  914. if changeReg(p.oper[1].reg,newReg,orgReg) then
  915. begin
  916. { updateStates(orgReg,newReg,p,false);}
  917. doReplaceReadReg := true;
  918. end;
  919. Ch_ROp3:
  920. if p.oper[2].typ = top_reg then
  921. if changeReg(p.oper[2].reg,newReg,orgReg) then
  922. begin
  923. { updateStates(orgReg,newReg,p,false);}
  924. doReplaceReadReg := true;
  925. end;
  926. end;
  927. end;
  928. end;
  929. end;
  930. procedure updateState(reg: tregister; p: Tai);
  931. { this procedure updates the read and write states of the instructions }
  932. { coming after p. It's called when the read/write state of p has been }
  933. { changed and this change has to be propagated to the following }
  934. { instructions as well }
  935. var
  936. newRState, newWState: byte;
  937. prevRState, prevWState: byte;
  938. doRState, doWState: boolean;
  939. begin
  940. { get the new read/write states from p }
  941. with pTaiprop(p.optinfo)^.regs[reg] do
  942. begin
  943. newRState := rState;
  944. newWState := wState;
  945. end;
  946. if not GetNextInstruction(p,p) then
  947. exit;
  948. { get the old read/write states from the next instruction, to know }
  949. { when we can stop updating }
  950. with pTaiprop(p.optinfo)^.regs[reg] do
  951. begin
  952. prevRState := rState;
  953. prevWState := wState;
  954. end;
  955. { adjust the states if this next instruction reads/writes the register }
  956. if regReadByInstruction(reg,p) then
  957. incState(newRState,1);
  958. if regModifiedByInstruction(reg,p) then
  959. incState(newWState,1);
  960. { do we still have to update the read and/or write states? }
  961. doRState := true;
  962. doWState := true;
  963. repeat
  964. { update the states }
  965. with pTaiprop(p.optinfo)^.regs[reg] do
  966. begin
  967. if doRState then
  968. rState := newRState;
  969. if doWState then
  970. wState := newWState;
  971. end;
  972. if not getNextInstruction(p,p) then
  973. break;
  974. with pTaiprop(p.optinfo)^.regs[reg] do
  975. begin
  976. { stop updating the read state if it changes }
  977. doRState :=
  978. doRState and (rState = prevRState);
  979. { if, by accident, this changed state is the same as the one }
  980. { we've been using, change it to a value that's definitely }
  981. { different from the previous and next state }
  982. if not doRState and
  983. (rState = newRState) then
  984. begin
  985. incState(newRState,1);
  986. prevRState := rState;
  987. doRState := true;
  988. end;
  989. { ditto for the write state }
  990. doWState :=
  991. doWState and (WState = prevWState);
  992. if not doWState and
  993. (wState = newWState) then
  994. begin
  995. incState(newWState,1);
  996. prevWState := wState;
  997. doWState := true;
  998. end;
  999. end;
  1000. { stop when we don't have to update either state anymore }
  1001. until not(doRState or doWState);
  1002. end;
  1003. function storeBack(p1: Tai; orgReg, newReg: tregister): boolean;
  1004. { returns true if p1 contains an instruction that stores the contents }
  1005. { of newReg back to orgReg }
  1006. begin
  1007. storeBack :=
  1008. (p1.typ = ait_instruction) and
  1009. (Taicpu(p1).opcode = A_MOV) and
  1010. (Taicpu(p1).oper[0].typ = top_reg) and
  1011. (Taicpu(p1).oper[0].reg = newReg) and
  1012. (Taicpu(p1).oper[1].typ = top_reg) and
  1013. (Taicpu(p1).oper[1].reg = orgReg);
  1014. end;
  1015. function ReplaceReg(asmL: TAAsmOutput; orgReg, newReg: TRegister; p: Tai;
  1016. const c: TContent; orgRegCanBeModified: Boolean;
  1017. var returnEndP: Tai): Boolean;
  1018. { Tries to replace orgreg with newreg in all instructions coming after p }
  1019. { until orgreg gets loaded with a new value. Returns true if successful, }
  1020. { false otherwise. If successful, the contents of newReg are set to c, }
  1021. { which should hold the contents of newReg before the current sequence }
  1022. { started }
  1023. { if the function returns true, returnEndP holds the last instruction }
  1024. { where newReg was replaced by orgReg }
  1025. var endP, hp: Tai;
  1026. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead,
  1027. stateChanged, readStateChanged: Boolean;
  1028. begin
  1029. ReplaceReg := false;
  1030. tmpResult := true;
  1031. sequenceEnd := false;
  1032. newRegModified := false;
  1033. orgRegRead := false;
  1034. removeLast := false;
  1035. endP := p;
  1036. while tmpResult and not sequenceEnd do
  1037. begin
  1038. tmpResult :=
  1039. getNextInstruction(endP,endP) and
  1040. (endp.typ = ait_instruction) and
  1041. not(Taicpu(endp).is_jmp);
  1042. if tmpresult and not assigned(endp.optInfo) then
  1043. begin
  1044. { hp := Tai_asm_comment.Create(strpnew('next no optinfo'));
  1045. hp.next := endp;
  1046. hp.previous := endp.previous;
  1047. endp.previous := hp;
  1048. if assigned(hp.previous) then
  1049. hp.previous^.next := hp;}
  1050. exit;
  1051. end;
  1052. If tmpResult and
  1053. { don't take into account instructions that will be removed }
  1054. Not (PTaiProp(endp.optInfo)^.canBeRemoved) then
  1055. begin
  1056. { if the newReg gets stored back to the oldReg, we can change }
  1057. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  1058. { %oldReg" to "<operations on %oldReg>" }
  1059. removeLast := storeBack(endP, orgReg, newReg);
  1060. sequenceEnd :=
  1061. { no support for (i)div, mul and imul with hardcoded operands }
  1062. (noHardCodedRegs(Taicpu(endP),orgReg,newReg) and
  1063. { if newReg gets loaded with a new value, we can stop }
  1064. { replacing newReg with oldReg here (possibly keeping }
  1065. { the original contents of oldReg so we still know them }
  1066. { afterwards) }
  1067. RegLoadedWithNewValue(newReg,true,Taicpu(endP)) or
  1068. { we can also stop if we reached the end of the use of }
  1069. { newReg's current contents }
  1070. (GetNextInstruction(endp,hp) and
  1071. FindRegDealloc(newReg,hp)));
  1072. { to be able to remove the first and last instruction of }
  1073. { movl %reg1, %reg2 }
  1074. { <operations on %reg2> (replacing reg2 with reg1 here) }
  1075. { movl %reg2, %reg1 }
  1076. { %reg2 must not be use afterwards (it can be as the }
  1077. { result of a peepholeoptimization) }
  1078. removeLast := removeLast and sequenceEnd;
  1079. newRegModified :=
  1080. newRegModified or
  1081. (not(regLoadedWithNewValue(newReg,true,Taicpu(endP))) and
  1082. RegModifiedByInstruction(newReg,endP));
  1083. orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
  1084. sequenceEnd := SequenceEnd and
  1085. (removeLast or
  1086. { since newReg will be replaced by orgReg, we can't allow that newReg }
  1087. { gets modified if orgReg is still read afterwards (since after }
  1088. { replacing, this would mean that orgReg first gets modified and then }
  1089. { gets read in the assumption it still contains the unmodified value) }
  1090. not(newRegModified and orgRegRead)) (* and
  1091. { since newReg will be replaced by orgReg, we can't allow that newReg }
  1092. { gets modified if orgRegCanBeModified = false }
  1093. { this now gets checked after the loop (JM) }
  1094. (orgRegCanBeModified or not(newRegModified)) *);
  1095. tmpResult :=
  1096. not(removeLast) and
  1097. not(newRegModified and orgRegRead) and
  1098. (* (orgRegCanBeModified or not(newRegModified)) and *)
  1099. (* already check at the top
  1100. (endp.typ = ait_instruction) and *)
  1101. NoHardCodedRegs(Taicpu(endP),orgReg,newReg) and
  1102. RegSizesOk(orgReg,newReg,Taicpu(endP)) and
  1103. not RegModifiedByInstruction(orgReg,endP);
  1104. end;
  1105. end;
  1106. sequenceEnd := sequenceEnd and
  1107. (removeLast or
  1108. (orgRegCanBeModified or not(newRegModified))) and
  1109. (not(assigned(endp)) or
  1110. not(endp.typ = ait_instruction) or
  1111. (noHardCodedRegs(Taicpu(endP),orgReg,newReg) and
  1112. RegSizesOk(orgReg,newReg,Taicpu(endP)) and
  1113. not(newRegModified and
  1114. (orgReg in PTaiProp(endp.optInfo)^.usedRegs) and
  1115. not(RegLoadedWithNewValue(orgReg,true,Taicpu(endP))))));
  1116. if SequenceEnd then
  1117. begin
  1118. {$ifdef replaceregdebug}
  1119. hp := Tai_asm_comment.Create(strpnew(
  1120. 'replacing '+gas_reg2str[newreg]+' with '+gas_reg2str[orgreg]+
  1121. ' from here...')));
  1122. hp.next := p;
  1123. hp.previous := p.previous;
  1124. p.previous := hp;
  1125. if assigned(hp.previous) then
  1126. hp.previous^.next := hp;
  1127. hp := Tai_asm_comment.Create(strpnew(
  1128. 'replaced '+gas_reg2str[newreg]+' with '+gas_reg2str[orgreg]+
  1129. ' till here')));
  1130. hp.next := endp.next;
  1131. hp.previous := endp;
  1132. endp.next := hp;
  1133. if assigned(hp.next) then
  1134. hp.next.previous := hp;
  1135. {$endif replaceregdebug}
  1136. replaceReg := true;
  1137. returnEndP := endP;
  1138. getNextInstruction(p,hp);
  1139. stateChanged := false;
  1140. while hp <> endP do
  1141. begin
  1142. if {not(PTaiProp(hp.optInfo)^.canBeRemoved) and }
  1143. (hp.typ = ait_instruction) then
  1144. stateChanged :=
  1145. doReplaceReg(Taicpu(hp),newReg,orgReg) or stateChanged;
  1146. if stateChanged then
  1147. updateStates(orgReg,newReg,hp,true);
  1148. getNextInstruction(hp,hp)
  1149. end;
  1150. if assigned(endp) and (endp.typ = ait_instruction) then
  1151. readStateChanged :=
  1152. DoReplaceReadReg(Taicpu(endP),newReg,orgReg);
  1153. if stateChanged or readStateChanged then
  1154. updateStates(orgReg,newReg,endP,stateChanged);
  1155. if stateChanged or readStateChanged then
  1156. updateState(orgReg,endP);
  1157. { the replacing stops either at the moment that }
  1158. { a) the newreg gets loaded with a new value (one not depending on the }
  1159. { current value of newreg) }
  1160. { b) newreg is completely replaced in this sequence and it's current value }
  1161. { isn't used anymore }
  1162. { In case b, the newreg was completely replaced by oldreg, so it's contents }
  1163. { are unchanged compared the start of this sequence, so restore them }
  1164. If removeLast or
  1165. RegLoadedWithNewValue(newReg,true,endP) then
  1166. GetLastInstruction(endP,hp)
  1167. else hp := endP;
  1168. if removeLast or
  1169. (p <> endp) or
  1170. not RegLoadedWithNewValue(newReg,true,endP) then
  1171. RestoreRegContentsTo(newReg,c,p,hp);
  1172. { In both case a and b, it is possible that the new register was modified }
  1173. { (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
  1174. { oldreg's contents have been changed. To take this into account, we simply }
  1175. { set the contents of orgreg to "unknown" after this sequence }
  1176. if newRegModified then
  1177. ClearRegContentsFrom(orgReg,p,hp);
  1178. if removeLast then
  1179. pTaiprop(endp.optinfo)^.canBeRemoved := true;
  1180. allocRegBetween(asml,orgReg,p,endP);
  1181. end
  1182. {$ifdef replaceregdebug}
  1183. else
  1184. begin
  1185. hp := Tai_asm_comment.Create(strpnew(
  1186. 'replacing '+gas_reg2str[newreg]+' with '+gas_reg2str[orgreg]+
  1187. ' from here...')));
  1188. hp.previous := p.previous;
  1189. hp.next := p;
  1190. p.previous := hp;
  1191. if assigned(hp.previous) then
  1192. hp.previous^.next := hp;
  1193. hp := Tai_asm_comment.Create(strpnew(
  1194. 'replacing '+gas_reg2str[newreg]+' with '+gas_reg2str[orgreg]+
  1195. ' failed here')));
  1196. hp.next := endp.next;
  1197. hp.previous := endp;
  1198. endp.next := hp;
  1199. if assigned(hp.next) then
  1200. hp.next.previous := hp;
  1201. end;
  1202. {$endif replaceregdebug}
  1203. End;
  1204. Function FindRegWithConst(p: Tai; size: topsize; l: aword; Var Res: TRegister): Boolean;
  1205. {Finds a register which contains the constant l}
  1206. Var Counter: TRegister;
  1207. {$ifdef testing}
  1208. hp: Tai;
  1209. {$endif testing}
  1210. tmpresult: boolean;
  1211. Begin
  1212. Counter := R_NO;
  1213. repeat
  1214. inc(counter);
  1215. tmpresult := (pTaiprop(p.optInfo)^.regs[counter].typ in
  1216. [con_const,con_noRemoveConst]) and
  1217. (Taicpu(PTaiProp(p.OptInfo)^.Regs[Counter].StartMod).opsize = size) and
  1218. (Taicpu(PTaiProp(p.OptInfo)^.Regs[Counter].StartMod).oper[0].typ = top_const) and
  1219. (Taicpu(PTaiProp(p.OptInfo)^.Regs[Counter].StartMod).oper[0].val = l);
  1220. {$ifdef testing}
  1221. if (pTaiprop(p.optInfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  1222. begin
  1223. hp := Tai_asm_comment.Create(strpnew(
  1224. 'checking const load of '+tostr(l)+' here...')));
  1225. hp.next := PTaiProp(p.OptInfo)^.Regs[Counter].StartMod;
  1226. hp.previous := PTaiProp(p.OptInfo)^.Regs[Counter].StartMod^.previous;
  1227. PTaiProp(p.OptInfo)^.Regs[Counter].StartMod^.previous := hp;
  1228. if assigned(hp.previous) then
  1229. hp.previous^.next := hp;
  1230. end;
  1231. {$endif testing}
  1232. until tmpresult or (Counter = R_EDI);
  1233. if tmpResult then
  1234. res := Taicpu(PTaiProp(p.OptInfo)^.Regs[Counter].StartMod).oper[1].reg;
  1235. FindRegWithConst := tmpResult;
  1236. End;
  1237. procedure removePrevNotUsedLoad(p: Tai; reg: tRegister; check: boolean);
  1238. { If check = true, it means the procedure has to check whether it isn't }
  1239. { possible that the contents are still used after p (used when removing }
  1240. { instructions because of a "call"), otherwise this is not necessary }
  1241. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  1242. { value of %eax isn't used anymore later on) }
  1243. var
  1244. hp1: Tai;
  1245. begin
  1246. if getLastInstruction(p,hp1) then
  1247. with pTaiprop(hp1.optInfo)^.regs[reg] do
  1248. if (typ in [con_ref,con_invalid,con_const]) and
  1249. (nrOfMods = 1) and
  1250. (rState = pTaiprop(startmod.optInfo)^.regs[reg].rState) and
  1251. (not(check) or
  1252. (not(regInInstruction(reg,p)) and
  1253. (not(reg in rg.usableregsint) and
  1254. (startmod.typ = ait_instruction) and
  1255. ((Taicpu(startmod).opcode = A_MOV) or
  1256. (Taicpu(startmod).opcode = A_MOVZX) or
  1257. (Taicpu(startmod).opcode = A_MOVSX) or
  1258. (Taicpu(startmod).opcode = A_LEA)) and
  1259. (Taicpu(startmod).oper[0].typ = top_ref) and
  1260. (Taicpu(startmod).oper[0].ref^.base = stack_pointer)) or
  1261. not(reg in pTaiprop(hp1.optInfo)^.usedRegs) or
  1262. findRegDealloc(reg,p))) then
  1263. pTaiprop(startMod.optInfo)^.canBeRemoved := true;
  1264. end;
  1265. {$ifdef notused}
  1266. function is_mov_for_div(p: Taicpu): boolean;
  1267. begin
  1268. is_mov_for_div :=
  1269. (p.opcode = A_MOV) and
  1270. (p.oper[0].typ = top_const) and
  1271. (p.oper[1].typ = top_reg) and
  1272. (p.oper[1].reg = R_EDX) and
  1273. getNextInstruction(p,p) and
  1274. (p.typ = ait_instruction) and
  1275. ((p.opcode = A_DIV) or
  1276. (p.opcode = A_IDIV));
  1277. end;
  1278. {$endif notused}
  1279. function memtoreg(const t: Taicpu; const ref: treference; var startp: tai): tregister;
  1280. var
  1281. hp: tai;
  1282. p: pTaiprop;
  1283. regcounter: tregister;
  1284. optimizable: boolean;
  1285. begin
  1286. if not getlastinstruction(t,hp) or
  1287. not issimplememloc(ref) then
  1288. begin
  1289. memtoreg := R_NO;
  1290. exit;
  1291. end;
  1292. p := pTaiprop(hp.optinfo);
  1293. optimizable := false;
  1294. for regcounter := R_EAX to R_EDI do
  1295. begin
  1296. if (assigned(p^.regs[regcounter].memwrite) and
  1297. refsequal(ref,p^.regs[regcounter].memwrite.oper[1].ref^)) then
  1298. begin
  1299. optimizable := true;
  1300. hp := p^.regs[regcounter].memwrite;
  1301. end
  1302. else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
  1303. (p^.regs[regcounter].nrofmods = 1) and
  1304. ((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
  1305. (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
  1306. (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
  1307. (taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and
  1308. refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^)) then
  1309. begin
  1310. optimizable := true;
  1311. hp := p^.regs[regcounter].startmod;
  1312. end;
  1313. if optimizable then
  1314. if ((t.opsize <> S_B) or
  1315. (regcounter <> R_EDI)) and
  1316. sizescompatible(Taicpu(hp).opsize,t.opsize) then
  1317. begin
  1318. case t.opsize of
  1319. S_B,S_BW,S_BL:
  1320. memtoreg := reg32toreg8(regcounter);
  1321. S_W,S_WL:
  1322. memtoreg := reg32toreg16(regcounter);
  1323. S_L:
  1324. memtoreg := regcounter;
  1325. end;
  1326. startp := hp;
  1327. exit;
  1328. end;
  1329. end;
  1330. memtoreg := R_NO;
  1331. end;
  1332. procedure removeLocalStores(const t1: tai);
  1333. {var
  1334. p: tai;
  1335. regcount: tregister; }
  1336. begin
  1337. {
  1338. for regcount := LoGPReg to HiGPReg do
  1339. if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
  1340. (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1].ref^.base
  1341. = procinfo^.framepointer) then
  1342. begin
  1343. pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
  1344. clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
  1345. end;
  1346. }
  1347. end;
  1348. procedure DoCSE(AsmL: TAAsmOutput; First, Last: Tai; findPrevSeqs, doSubOpts: boolean);
  1349. {marks the instructions that can be removed by RemoveInstructs. They're not
  1350. removed immediately because sometimes an instruction needs to be checked in
  1351. two different sequences}
  1352. var cnt, cnt2, {cnt3,} orgNrOfMods: longint;
  1353. p, hp1, hp2, prevSeq, prevSeq_next: Tai;
  1354. hp3, hp4: Tai;
  1355. hp5 : Tai;
  1356. RegInfo: TRegInfo;
  1357. RegCounter: TRegister;
  1358. Begin
  1359. p := First;
  1360. SkipHead(p);
  1361. While (p <> Last) Do
  1362. Begin
  1363. Case p.typ Of
  1364. ait_align:
  1365. if not(Tai_align(p).use_op) then
  1366. SetAlignReg(p);
  1367. ait_instruction:
  1368. Begin
  1369. Case Taicpu(p).opcode Of
  1370. A_CALL:
  1371. for regCounter := R_EAX to R_EBX do
  1372. removePrevNotUsedLoad(p,regCounter,true);
  1373. A_CLD: If GetLastInstruction(p, hp1) And
  1374. (PTaiProp(hp1.OptInfo)^.DirFlag = F_NotSet) Then
  1375. PTaiProp(Tai(p).OptInfo)^.CanBeRemoved := True;
  1376. A_LEA, A_MOV, A_MOVZX, A_MOVSX:
  1377. Begin
  1378. hp2 := p;
  1379. Case Taicpu(p).oper[0].typ Of
  1380. top_ref, top_reg:
  1381. if (Taicpu(p).oper[1].typ = top_reg) then
  1382. Begin
  1383. With PTaiProp(p.OptInfo)^.Regs[Reg32(Taicpu(p).oper[1].reg)] Do
  1384. Begin
  1385. if (startmod = p) then
  1386. orgNrOfMods := nrOfMods
  1387. else
  1388. orgNrOfMods := 0;
  1389. If (p = StartMod) And
  1390. GetLastInstruction (p, hp1) And
  1391. not(hp1.typ in [ait_marker,ait_label]) then
  1392. {so we don't try to check a sequence when p is the first instruction of the block}
  1393. begin
  1394. {$ifdef csdebug}
  1395. hp5 := Tai_asm_comment.Create(strpnew(
  1396. 'cse checking '+gas_reg2str[Reg32(Taicpu(p).oper[1].reg)])));
  1397. insertLLItem(asml,p,p.next,hp5);
  1398. {$endif csdebug}
  1399. If CheckSequence(p,prevSeq,Taicpu(p).oper[1].reg, Cnt, RegInfo, findPrevSeqs) And
  1400. (Cnt > 0) Then
  1401. Begin
  1402. (*
  1403. hp1 := nil;
  1404. { although it's perfectly ok to remove an instruction which doesn't contain }
  1405. { the register that we've just checked (CheckSequence takes care of that), }
  1406. { the sequence containing this other register should also be completely }
  1407. { checked and removed, otherwise we may get situations like this: }
  1408. { }
  1409. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  1410. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  1411. { movl 8(%edx), %edx movl 8(%edx), %edx }
  1412. { movl (%eax), eax movl (%eax), eax }
  1413. { cmpl %eax, %edx cmpl %eax, %edx }
  1414. { jnz l123 getting converted to jnz l123 }
  1415. { movl 12(%ebp), %edx movl 4(%eax), eax }
  1416. { movl 16(%ebp), %eax }
  1417. { movl 8(%edx), %edx }
  1418. { movl 4(%eax), eax }
  1419. *)
  1420. { not anymore: if the start of a new sequence is found while checking (e.g. }
  1421. { above that of eax while checking edx, this new sequence is automatically }
  1422. { also checked }
  1423. Cnt2 := 1;
  1424. While Cnt2 <= Cnt Do
  1425. Begin
  1426. (*
  1427. If not(regInInstruction(Taicpu(hp2).oper[1].reg, p)) and
  1428. not(pTaiprop(p.optinfo)^.canBeRemoved) then
  1429. begin
  1430. if (p.typ = ait_instruction) And
  1431. ((Taicpu(p).OpCode = A_MOV) or
  1432. (Taicpu(p).opcode = A_MOVZX) or
  1433. (Taicpu(p).opcode = A_MOVSX)) And
  1434. (Taicpu(p).oper[1].typ = top_reg) then
  1435. if not is_mov_for_div(Taicpu(p)) then
  1436. begin
  1437. regCounter := reg32(Taicpu(p).oper[1].reg);
  1438. if (regCounter in reginfo.regsStillUsedAfterSeq) then
  1439. begin
  1440. if (hp1 = nil) then
  1441. hp1 := reginfo.lastReload[regCounter];
  1442. end
  1443. {$ifndef noremove}
  1444. else
  1445. begin
  1446. hp5 := p;
  1447. for cnt3 := pTaiprop(p.optinfo)^.regs[regCounter].nrofmods downto 1 do
  1448. begin
  1449. if regModifiedByInstruction(regCounter,hp5) then
  1450. PTaiProp(hp5.OptInfo)^.CanBeRemoved := True;
  1451. getNextInstruction(hp5,hp5);
  1452. end;
  1453. end
  1454. {$endif noremove}
  1455. end
  1456. {$ifndef noremove}
  1457. else
  1458. PTaiProp(p.OptInfo)^.CanBeRemoved := True
  1459. {$endif noremove}
  1460. end
  1461. *)
  1462. {$ifndef noremove}
  1463. (* else *)
  1464. PTaiProp(p.OptInfo)^.CanBeRemoved := True
  1465. {$endif noremove}
  1466. ; Inc(Cnt2);
  1467. GetNextInstruction(p, p);
  1468. End;
  1469. {hp4 is used to get the contents of the registers before the sequence}
  1470. GetLastInstruction(hp2, hp4);
  1471. getNextInstruction(prevSeq,prevSeq_next);
  1472. {$IfDef CSDebug}
  1473. For RegCounter := R_EAX To R_EDI Do
  1474. If (RegCounter in RegInfo.RegsLoadedForRef) Then
  1475. Begin
  1476. hp5 := Tai_asm_comment.Create(strpnew('New: '+gas_reg2str[RegCounter]+', Old: '+
  1477. gas_reg2str[RegInfo.New2OldReg[RegCounter]])));
  1478. InsertLLItem(AsmL, Tai(hp2.previous), hp2, hp5);
  1479. End;
  1480. {$EndIf CSDebug}
  1481. { If some registers were different in the old and the new sequence, move }
  1482. { the contents of those old registers to the new ones }
  1483. For RegCounter := R_EAX To R_EDI Do
  1484. If Not(RegCounter in [R_ESP,procinfo^.framepointer]) And
  1485. (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
  1486. Begin
  1487. AllocRegBetween(AsmL,RegInfo.New2OldReg[RegCounter],
  1488. PTaiProp(prevSeq.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,hp2);
  1489. if hp4 <> prevSeq then
  1490. begin
  1491. if assigned(reginfo.lastReload[regCounter]) then
  1492. getLastInstruction(reginfo.lastReload[regCounter],hp3)
  1493. else if assigned(reginfo.lastReload[regInfo.New2OldReg[regCounter]]) then
  1494. getLastInstruction(reginfo.lastReload[regInfo.new2OldReg[regCounter]],hp3)
  1495. else hp3 := hp4;
  1496. clearRegContentsFrom(regCounter,prevSeq_next,hp3);
  1497. getnextInstruction(hp3,hp3);
  1498. allocRegBetween(asmL,regCounter,prevSeq,hp3);
  1499. end;
  1500. If Not(RegCounter In RegInfo.RegsLoadedForRef) And
  1501. {old reg new reg}
  1502. (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
  1503. Begin
  1504. getLastInstruction(p,hp3);
  1505. If (hp4 <> prevSeq) or
  1506. not(regCounter in rg.usableregsint + [R_EDI,R_ESI]) or
  1507. not ReplaceReg(asmL,RegInfo.New2OldReg[RegCounter],
  1508. regCounter,hp3,
  1509. PTaiProp(PrevSeq.optInfo)^.Regs[regCounter],true,hp5) then
  1510. begin
  1511. hp3 := Tai_Marker.Create(NoPropInfoStart);
  1512. InsertLLItem(AsmL, prevSeq_next.previous,Tai(prevSeq_next), hp3);
  1513. hp5 := Taicpu.Op_Reg_Reg(A_MOV, S_L,
  1514. {old reg new reg}
  1515. RegInfo.New2OldReg[RegCounter], RegCounter);
  1516. new(pTaiprop(hp5.optinfo));
  1517. pTaiprop(hp5.optinfo)^ := pTaiprop(prevSeq_next.optinfo)^;
  1518. pTaiprop(hp5.optinfo)^.canBeRemoved := false;
  1519. InsertLLItem(AsmL, prevSeq_next.previous, Tai(prevSeq_next), hp5);
  1520. hp3 := Tai_Marker.Create(NoPropInfoEnd);
  1521. InsertLLItem(AsmL, prevSeq_next.previous, Tai(prevSeq_next), hp3);
  1522. { adjusts states in previous instruction so that it will }
  1523. { definitely be different from the previous or next state }
  1524. incstate(pTaiprop(hp5.optinfo)^.
  1525. regs[RegInfo.New2OldReg[RegCounter]].rstate,20);
  1526. incstate(pTaiprop(hp5.optinfo)^.
  1527. regs[regCounter].wstate,20);
  1528. updateState(RegInfo.New2OldReg[RegCounter],hp5);
  1529. end
  1530. End
  1531. Else
  1532. { imagine the following code: }
  1533. { normal wrong optimized }
  1534. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  1535. { movl (%eax), %eax movl (%eax), %eax }
  1536. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  1537. { jne l1 jne l1 }
  1538. { movl 8(%ebp), %eax }
  1539. { movl (%eax), %edi movl %eax, %edi }
  1540. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  1541. { movl 8(%ebp), %eax }
  1542. { pushl 70(%eax) pushl 70(%eax) }
  1543. { }
  1544. { The error is that at the moment that the last instruction is executed, }
  1545. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  1546. { registers that are completely removed from a sequence (= registers in }
  1547. { RegLoadedForRef, have to be changed to their contents from before the }
  1548. { sequence. }
  1549. If RegCounter in RegInfo.RegsLoadedForRef Then
  1550. Begin
  1551. hp3 := hp2;
  1552. { cnt still holds the number of instructions }
  1553. { of the sequence, so go to the end of it }
  1554. for cnt2 := 1 to pred(cnt) Do
  1555. getNextInstruction(hp3,hp3);
  1556. { hp4 = instruction prior to start of sequence }
  1557. restoreRegContentsTo(regCounter,
  1558. PTaiProp(hp4.OptInfo)^.Regs[RegCounter],
  1559. hp2,hp3);
  1560. End;
  1561. End;
  1562. (*
  1563. If hp1 <> nil Then
  1564. p := hp1;
  1565. *)
  1566. Continue;
  1567. End
  1568. (*
  1569. Else
  1570. If (PTaiProp(p.OptInfo)^.
  1571. regs[reg32(Taicpu(p).oper[1].reg)].typ
  1572. in [con_ref,con_noRemoveRef]) and
  1573. (PTaiProp(p.OptInfo)^.CanBeRemoved) Then
  1574. if (cnt > 0) then
  1575. begin
  1576. p := hp2;
  1577. Cnt2 := 1;
  1578. While Cnt2 <= Cnt Do
  1579. Begin
  1580. If RegInInstruction(Taicpu(hp2).oper[1].reg, p) Then
  1581. PTaiProp(p.OptInfo)^.CanBeRemoved := False;
  1582. Inc(Cnt2);
  1583. GetNextInstruction(p, p);
  1584. End;
  1585. Continue;
  1586. End
  1587. else
  1588. begin
  1589. { Fix for web bug 972 }
  1590. regCounter := Reg32(Taicpu(p).oper[1].reg);
  1591. cnt := PTaiProp(p.optInfo)^.Regs[regCounter].nrOfMods;
  1592. hp3 := p;
  1593. for cnt2 := 1 to cnt do
  1594. if not(regModifiedByInstruction(regCounter,hp3) and
  1595. not(PTaiProp(hp3.optInfo)^.canBeRemoved)) then
  1596. getNextInstruction(hp3,hp3)
  1597. else
  1598. break;
  1599. getLastInstruction(p,hp4);
  1600. RestoreRegContentsTo(regCounter,
  1601. PTaiProp(hp4.optInfo)^.Regs[regCounter],
  1602. p,hp3);
  1603. end;
  1604. *)
  1605. End;
  1606. End;
  1607. { try to replace the new reg with the old reg }
  1608. if not(PTaiProp(p.optInfo)^.canBeRemoved) then
  1609. if (Taicpu(p).oper[0].typ = top_reg) and
  1610. (Taicpu(p).oper[1].typ = top_reg) and
  1611. { only remove if we're not storing something in a regvar }
  1612. (Taicpu(p).oper[1].reg in (rg.usableregsint+[R_EDI])) and
  1613. (Taicpu(p).opcode = A_MOV) and
  1614. getLastInstruction(p,hp4) and
  1615. { we only have to start replacing from the instruction after the mov, }
  1616. { but replacereg only starts with getnextinstruction(p,p) }
  1617. replaceReg(asmL,Taicpu(p).oper[0].reg,
  1618. Taicpu(p).oper[1].reg,p,
  1619. pTaiprop(hp4.optInfo)^.regs[Taicpu(p).oper[1].reg],false,hp1) then
  1620. begin
  1621. pTaiprop(p.optInfo)^.canBeRemoved := true;
  1622. allocRegBetween(asmL,Taicpu(p).oper[0].reg,
  1623. pTaiProp(p.optInfo)^.regs[Taicpu(p).oper[0].reg].startMod,hp1);
  1624. end
  1625. else
  1626. begin
  1627. if (Taicpu(p).oper[1].typ = top_reg) and
  1628. not regInOp(Taicpu(p).oper[1].reg,Taicpu(p).oper[0]) then
  1629. removePrevNotUsedLoad(p,reg32(Taicpu(p).oper[1].reg),false);
  1630. if doSubOpts and
  1631. (Taicpu(p).opcode <> A_LEA) and
  1632. (Taicpu(p).oper[0].typ = top_ref) then
  1633. begin
  1634. regcounter :=
  1635. memtoreg(taicpu(p),
  1636. Taicpu(p).oper[0].ref^,hp5);
  1637. if regcounter <> R_NO then
  1638. if (taicpu(p).opcode = A_MOV) and
  1639. (taicpu(p).oper[1].typ = top_reg) and
  1640. (taicpu(p).oper[1].reg = regcounter) then
  1641. begin
  1642. pTaiProp(p.optinfo)^.canberemoved := true;
  1643. allocregbetween(asml,reg32(regcounter),hp5,p);
  1644. end
  1645. else
  1646. begin
  1647. Taicpu(p).loadreg(0,regcounter);
  1648. regcounter := reg32(regcounter);
  1649. allocregbetween(asml,regcounter,hp5,p);
  1650. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1651. updatestate(regcounter,p);
  1652. end;
  1653. end;
  1654. end;
  1655. { at first, only try optimizations of large blocks, because doing }
  1656. { doing smaller ones may prevent bigger ones from completing in }
  1657. { in the next pass }
  1658. if not doSubOpts and (orgNrOfMods <> 0) then
  1659. begin
  1660. p := hp2;
  1661. for cnt := 1 to pred(orgNrOfMods) do
  1662. getNextInstruction(p,p);
  1663. end;
  1664. End;
  1665. top_symbol,Top_Const:
  1666. Begin
  1667. Case Taicpu(p).oper[1].typ Of
  1668. Top_Reg:
  1669. Begin
  1670. regCounter := Reg32(Taicpu(p).oper[1].reg);
  1671. If GetLastInstruction(p, hp1) Then
  1672. With PTaiProp(hp1.OptInfo)^.Regs[regCounter] Do
  1673. if (typ in [con_const,con_noRemoveConst]) and
  1674. (Taicpu(startMod).opsize >= Taicpu(p).opsize) and
  1675. opsequal(Taicpu(StartMod).oper[0],Taicpu(p).oper[0]) Then
  1676. begin
  1677. PTaiProp(p.OptInfo)^.CanBeRemoved := True;
  1678. allocRegBetween(asmL,regCounter,startMod,p);
  1679. end
  1680. else
  1681. removePrevNotUsedLoad(p,reg32(Taicpu(p).oper[1].reg),false);
  1682. End;
  1683. Top_Ref:
  1684. if (Taicpu(p).oper[0].typ = top_const) and
  1685. getLastInstruction(p,hp1) and
  1686. findRegWithConst(hp1,Taicpu(p).opsize,Taicpu(p).oper[0].val,regCounter) then
  1687. begin
  1688. Taicpu(p).loadreg(0,regCounter);
  1689. allocRegBetween(AsmL,reg32(regCounter),
  1690. PTaiProp(hp1.optinfo)^.regs[reg32(regCounter)].startMod,p);
  1691. end;
  1692. End;
  1693. End;
  1694. End;
  1695. End;
  1696. A_LEAVE:
  1697. begin
  1698. if getlastinstruction(p,hp1) then
  1699. removeLocalStores(hp1);
  1700. end;
  1701. A_STD: If GetLastInstruction(p, hp1) And
  1702. (PTaiProp(hp1.OptInfo)^.DirFlag = F_Set) Then
  1703. PTaiProp(Tai(p).OptInfo)^.CanBeRemoved := True;
  1704. else
  1705. begin
  1706. for cnt := 1 to maxch do
  1707. begin
  1708. case InsProp[taicpu(p).opcode].Ch[cnt] of
  1709. Ch_ROp1:
  1710. if (taicpu(p).oper[0].typ = top_ref) and
  1711. ((taicpu(p).opcode < A_F2XM1) or
  1712. ((taicpu(p).opcode > A_IN) and
  1713. (taicpu(p).opcode < A_OUT)) or
  1714. (taicpu(p).opcode = A_PUSH) or
  1715. ((taicpu(p).opcode >= A_RCL) and
  1716. (taicpu(p).opcode <= A_XOR))) then
  1717. begin
  1718. regcounter :=
  1719. memtoreg(taicpu(p),
  1720. Taicpu(p).oper[0].ref^,hp5);
  1721. if regcounter <> R_NO then
  1722. begin
  1723. Taicpu(p).loadreg(0,regcounter);
  1724. regcounter := reg32(regcounter);
  1725. allocregbetween(asml,regcounter,hp5,p);
  1726. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1727. updatestate(regcounter,p);
  1728. end;
  1729. end;
  1730. Ch_MOp1:
  1731. if Not(CS_LittleSize in aktglobalswitches) And
  1732. (taicpu(p).oper[0].typ = top_ref) then
  1733. begin
  1734. regcounter :=
  1735. memtoreg(taicpu(p),
  1736. Taicpu(p).oper[0].ref^,hp5);
  1737. if (regcounter <> R_NO) (* and
  1738. (not getNextInstruction(p,hp1) or
  1739. (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
  1740. FindRegDealloc(reg32(regcounter),hp1))) *) then
  1741. begin
  1742. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1743. insertllitem(asml,p,p.next,hp1);
  1744. hp1 := taicpu.op_reg_ref(A_MOV,
  1745. regsize(regcounter),regcounter,
  1746. taicpu(p).oper[0].ref^);
  1747. new(pTaiprop(hp1.optinfo));
  1748. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1749. insertllitem(asml,p,p.next,hp1);
  1750. incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
  1751. updatestate(reg32(regcounter),hp1);
  1752. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1753. insertllitem(asml,p,p.next,hp1);
  1754. Taicpu(p).loadreg(0,regcounter);
  1755. regcounter := reg32(regcounter);
  1756. allocregbetween(asml,regcounter,hp5,
  1757. tai(p.next.next));
  1758. end;
  1759. end;
  1760. Ch_ROp2:
  1761. if ((taicpu(p).opcode = A_CMP) or
  1762. (taicpu(p).opcode = A_TEST)) and
  1763. (taicpu(p).oper[1].typ = top_ref) then
  1764. begin
  1765. regcounter :=
  1766. memtoreg(taicpu(p),
  1767. Taicpu(p).oper[1].ref^,hp5);
  1768. if regcounter <> R_NO then
  1769. begin
  1770. Taicpu(p).loadreg(1,regcounter);
  1771. regcounter := reg32(regcounter);
  1772. allocregbetween(asml,regcounter,hp5,p);
  1773. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1774. updatestate(regcounter,p);
  1775. end;
  1776. end;
  1777. Ch_MOp2:
  1778. if not(cs_littlesize in aktglobalswitches) and
  1779. (taicpu(p).oper[1].typ = top_ref) and
  1780. ((taicpu(p).opcode < A_BT) or
  1781. ((taicpu(p).opcode > A_IN) and
  1782. (taicpu(p).opcode < A_OUT)) or
  1783. (taicpu(p).opcode = A_PUSH) or
  1784. ((taicpu(p).opcode >= A_RCL) and
  1785. (taicpu(p).opcode <= A_XOR))) then
  1786. begin
  1787. regcounter :=
  1788. memtoreg(taicpu(p),
  1789. Taicpu(p).oper[1].ref^,hp5);
  1790. if (regcounter <> R_NO) (* and
  1791. (not getNextInstruction(p,hp1) or
  1792. (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
  1793. FindRegDealloc(reg32(regcounter),hp1))) *) then
  1794. begin
  1795. hp1 := Tai_Marker.Create(NoPropInfoEnd);
  1796. insertllitem(asml,p,p.next,hp1);
  1797. hp1 := taicpu.op_reg_ref(A_MOV,
  1798. regsize(regcounter),regcounter,
  1799. taicpu(p).oper[1].ref^);
  1800. new(pTaiprop(hp1.optinfo));
  1801. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1802. insertllitem(asml,p,p.next,hp1);
  1803. incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
  1804. updatestate(reg32(regcounter),hp1);
  1805. hp1 := Tai_Marker.Create(NoPropInfoStart);
  1806. insertllitem(asml,p,p.next,hp1);
  1807. Taicpu(p).loadreg(1,regcounter);
  1808. regcounter := reg32(regcounter);
  1809. allocregbetween(asml,regcounter,hp5,
  1810. tai(p.next.next));
  1811. end;
  1812. end;
  1813. end;
  1814. end;
  1815. end;
  1816. End
  1817. End;
  1818. End;
  1819. GetNextInstruction(p, p);
  1820. End;
  1821. End;
  1822. function removeInstructs(asmL: TAAsmoutput; first, last: Tai): boolean;
  1823. { Removes the marked instructions and disposes the PTaiProps of the other }
  1824. { instructions }
  1825. Var
  1826. p, hp1: Tai;
  1827. nopropinfolevel: longint;
  1828. begin
  1829. removeInstructs := false;
  1830. p := First;
  1831. nopropinfolevel := 0;
  1832. While (p <> Last) Do
  1833. Begin
  1834. If (p.typ = ait_marker) and
  1835. (Tai_marker(p).kind = noPropInfoStart) then
  1836. begin
  1837. hp1 := Tai(p.next);
  1838. asmL.remove(p);
  1839. p.free;
  1840. nopropinfolevel := 1;
  1841. while (nopropinfolevel <> 0) do
  1842. begin
  1843. p := Tai(hp1.next);
  1844. {$ifndef noinstremove}
  1845. { allocregbetween can insert new ait_regalloc objects }
  1846. { without optinfo }
  1847. if (hp1.typ = ait_marker) then
  1848. begin
  1849. case Tai_marker(hp1).kind of
  1850. { they can be nested! }
  1851. noPropInfoStart: inc(nopropinfolevel);
  1852. noPropInfoEnd: dec(nopropinfolevel);
  1853. else
  1854. begin
  1855. hp1 := p;
  1856. continue;
  1857. end;
  1858. end;
  1859. asmL.remove(hp1);
  1860. hp1.free;
  1861. end
  1862. else if assigned(hp1.optinfo) then
  1863. if pTaiprop(hp1.optinfo)^.canBeRemoved then
  1864. begin
  1865. dispose(pTaiprop(hp1.optinfo));
  1866. hp1.optinfo := nil;
  1867. asmL.remove(hp1);
  1868. hp1.free;
  1869. end
  1870. else
  1871. {$endif noinstremove}
  1872. begin
  1873. dispose(pTaiprop(hp1.optinfo));
  1874. hp1.optinfo := nil;
  1875. end;
  1876. hp1 := p;
  1877. end;
  1878. end
  1879. else
  1880. {$ifndef noinstremove}
  1881. if assigned(p.optInfo) and
  1882. PTaiProp(p.optInfo)^.canBeRemoved then
  1883. begin
  1884. hp1 := Tai(p.next);
  1885. AsmL.Remove(p);
  1886. p.free;
  1887. p := hp1;
  1888. removeInstructs := true;
  1889. End
  1890. Else
  1891. {$endif noinstremove}
  1892. Begin
  1893. p.OptInfo := nil;
  1894. p := Tai(p.next);;
  1895. End;
  1896. End;
  1897. FreeMem(TaiPropBlock, NrOfTaiObjs*SizeOf(TTaiProp))
  1898. End;
  1899. function CSE(AsmL: TAAsmOutput; First, Last: Tai; pass: longint): boolean;
  1900. Begin
  1901. DoCSE(AsmL, First, Last, not(cs_slowoptimize in aktglobalswitches) or (pass >= 2),
  1902. not(cs_slowoptimize in aktglobalswitches) or (pass >= 1));
  1903. { register renaming }
  1904. if not(cs_slowoptimize in aktglobalswitches) or (pass > 0) then
  1905. doRenaming(asmL, first, last);
  1906. cse := removeInstructs(asmL, first, last);
  1907. End;
  1908. End.
  1909. {
  1910. $Log$
  1911. Revision 1.28 2002-04-14 17:00:49 carl
  1912. + att_reg2str -> gas_reg2str
  1913. Revision 1.27 2002/04/04 19:06:10 peter
  1914. * removed unused units
  1915. * use tlocation.size in cg.a_*loc*() routines
  1916. Revision 1.26 2002/04/02 17:11:34 peter
  1917. * tlocation,treference update
  1918. * LOC_CONSTANT added for better constant handling
  1919. * secondadd splitted in multiple routines
  1920. * location_force_reg added for loading a location to a register
  1921. of a specified size
  1922. * secondassignment parses now first the right and then the left node
  1923. (this is compatible with Kylix). This saves a lot of push/pop especially
  1924. with string operations
  1925. * adapted some routines to use the new cg methods
  1926. Revision 1.25 2002/03/31 20:26:38 jonas
  1927. + a_loadfpu_* and a_loadmm_* methods in tcg
  1928. * register allocation is now handled by a class and is mostly processor
  1929. independent (+rgobj.pas and i386/rgcpu.pas)
  1930. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1931. * some small improvements and fixes to the optimizer
  1932. * some register allocation fixes
  1933. * some fpuvaroffset fixes in the unary minus node
  1934. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1935. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1936. also better optimizable)
  1937. * fixed and optimized register saving/restoring for new/dispose nodes
  1938. * LOC_FPU locations now also require their "register" field to be set to
  1939. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1940. - list field removed of the tnode class because it's not used currently
  1941. and can cause hard-to-find bugs
  1942. Revision 1.24 2002/03/04 19:10:12 peter
  1943. * removed compiler warnings
  1944. Revision 1.23 2001/12/04 15:58:13 jonas
  1945. * unnecessary loads of constants are now also remove by
  1946. removePrevNotUsedLoad()
  1947. Revision 1.22 2001/11/30 16:35:02 jonas
  1948. * added missing allocregbetween() call for a memtoreg() optimization
  1949. Revision 1.21 2001/10/27 10:20:43 jonas
  1950. + replace mem accesses to locations to which a reg was stored recently with that reg
  1951. Revision 1.20 2001/10/14 11:50:21 jonas
  1952. + also replace mem references in modify operands with regs
  1953. Revision 1.19 2001/10/12 13:58:05 jonas
  1954. + memory references are now replaced by register reads in "regular"
  1955. instructions (e.g. "addl ref1,%eax" will be replaced by "addl %ebx,%eax"
  1956. if %ebx contains ref1). Previously only complete load sequences were
  1957. optimized away, but not such small accesses in other instructions than
  1958. mov/movzx/movsx
  1959. Revision 1.18 2001/09/04 14:01:03 jonas
  1960. * commented out some inactive code in csopt386
  1961. + small improvement: lea is now handled the same as mov/zx/sx
  1962. Revision 1.17 2001/08/29 14:07:43 jonas
  1963. * the optimizer now keeps track of flags register usage. This fixes some
  1964. optimizer bugs with int64 calculations (because of the carry flag usage)
  1965. * fixed another bug which caused wrong optimizations with complex
  1966. array expressions
  1967. Revision 1.16 2001/08/26 13:36:55 florian
  1968. * some cg reorganisation
  1969. * some PPC updates
  1970. Revision 1.15 2001/04/06 16:24:38 jonas
  1971. * fixed bug due to short boolean evaluation
  1972. Revision 1.14 2001/04/02 21:20:36 peter
  1973. * resulttype rewrite
  1974. Revision 1.13 2001/01/10 08:52:40 michael
  1975. + Patch from jonas so 1.0.2 can be used to cycle
  1976. Revision 1.12 2001/01/07 15:51:17 jonas
  1977. * fixed crashing bug to due previous changes
  1978. Revision 1.11 2001/01/06 23:35:05 jonas
  1979. * fixed webbug 1323
  1980. Revision 1.10 2000/12/25 00:07:31 peter
  1981. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1982. tlinkedlist objects)
  1983. Revision 1.9 2000/12/05 09:33:42 jonas
  1984. * when searching for constants in registers, the returned register
  1985. sometimes didn't have the same size as the requested size
  1986. Revision 1.8 2000/11/29 00:30:43 florian
  1987. * unused units removed from uses clause
  1988. * some changes for widestrings
  1989. Revision 1.7 2000/11/28 16:32:11 jonas
  1990. + support for optimizing simple sequences with div/idiv/mul opcodes
  1991. Revision 1.6 2000/11/14 12:17:34 jonas
  1992. * fixed some bugs in checksequence
  1993. Revision 1.5 2000/11/09 12:34:44 jonas
  1994. * fixed range check error
  1995. Revision 1.4 2000/11/03 17:53:24 jonas
  1996. * some small improvements
  1997. Revision 1.3 2000/11/01 22:53:30 jonas
  1998. * register contents were not cleared if there was only 1 instruction
  1999. between de previous sequence and the current one
  2000. Revision 1.2 2000/10/24 10:40:53 jonas
  2001. + register renaming ("fixes" bug1088)
  2002. * changed command line options meanings for optimizer:
  2003. O2 now means peepholopts, CSE and register renaming in 1 pass
  2004. O3 is the same, but repeated until no further optimizations are
  2005. possible or until 5 passes have been done (to avoid endless loops)
  2006. * changed aopt386 so it does this looping
  2007. * added some procedures from csopt386 to the interface because they're
  2008. used by rropt386 as well
  2009. * some changes to csopt386 and daopt386 so that newly added instructions
  2010. by the CSE get optimizer info (they were simply skipped previously),
  2011. this fixes some bugs
  2012. Revision 1.1 2000/10/15 09:47:43 peter
  2013. * moved to i386/
  2014. Revision 1.14 2000/09/30 13:07:23 jonas
  2015. * fixed support for -Or with new features of CSE
  2016. Revision 1.13 2000/09/29 23:14:45 jonas
  2017. * search much further back for CSE sequences (non-conflicting stores are
  2018. now passed)
  2019. * remove more unnecessary loads of registers (especially the self pointer)
  2020. Revision 1.12 2000/09/26 11:49:41 jonas
  2021. * writes to register variables and to the self pointer now also count as
  2022. memore writes
  2023. Revision 1.11 2000/09/25 09:50:29 jonas
  2024. - removed TP conditional code
  2025. Revision 1.10 2000/09/24 15:06:14 peter
  2026. * use defines.inc
  2027. Revision 1.9 2000/09/22 15:01:59 jonas
  2028. * fixed some bugs in the previous improvements: in some cases, esi was
  2029. still being replaced before a conditional jump (the code that
  2030. detected conditional jumps sometimes skipped over them)
  2031. Revision 1.8 2000/09/20 15:00:58 jonas
  2032. + much improved CSE: the CSE now searches further back for sequences it
  2033. can reuse. After I've also implemented register renaming, the effect
  2034. should be even better (afaik web bug 1088 will then even be optimized
  2035. properly). I don't know about the slow down factor this adds. Maybe
  2036. a new optimization level should be introduced?
  2037. Revision 1.7 2000/08/25 19:40:45 jonas
  2038. * refined previous fix a bit, some instructions weren't being removed
  2039. while they could (merged from fixes branch)
  2040. * made checksequence a bit faster
  2041. Revision 1.6 2000/08/23 12:55:10 jonas
  2042. * fix for web bug 1112 and a bit of clean up in csopt386 (merged from
  2043. fixes branch)
  2044. Revision 1.5 2000/08/04 20:08:03 jonas
  2045. * improved detection of range of instructions which use a register
  2046. (merged from fixes branch)
  2047. Revision 1.4 2000/07/21 15:19:54 jonas
  2048. * daopt386: changes to getnextinstruction/getlastinstruction so they
  2049. ignore labels who have is_addr set
  2050. + daopt386/csopt386: remove loads of registers which are overwritten
  2051. before their contents are used (especially usefull for removing superfluous
  2052. maybe_loadself outputs and push/pops transformed by below optimization
  2053. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  2054. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  2055. currently because I don't know whether it's safe to do this under Win32/
  2056. Linux (because of problems we had when using esp as frame pointer on
  2057. those os'es)
  2058. Revision 1.3 2000/07/14 05:11:48 michael
  2059. + Patch to 1.1
  2060. Revision 1.2 2000/07/13 11:32:39 michael
  2061. + removed logs
  2062. }