csopt386.pas 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694
  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;
  23. {Procedure CSOpt386(First, Last: Pai);}
  24. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  25. Implementation
  26. Uses
  27. {$ifdef replaceregdebug}cutils,{$endif}
  28. verbose, hcodegen, globals,cpubase,cpuasm,DAOpt386, tgeni386;
  29. {
  30. Function PaiInSequence(P: Pai; Const Seq: TContent): Boolean;
  31. Var P1: Pai;
  32. Counter: Byte;
  33. TmpResult: Boolean;
  34. Begin
  35. TmpResult := False;
  36. P1 := Seq.StartMod;
  37. Counter := 1;
  38. While Not(TmpResult) And
  39. (Counter <= Seq.NrOfMods) Do
  40. Begin
  41. If (P = P1) Then TmpResult := True;
  42. Inc(Counter);
  43. p1 := Pai(p1^.Next);
  44. End;
  45. PaiInSequence := TmpResult;
  46. End;
  47. }
  48. function modifiesConflictingMemLocation(p1: pai; reg: tregister; c: tregContent;
  49. var regsStillValid: tregset): boolean;
  50. var
  51. p, hp: paicpu;
  52. tmpRef: treference;
  53. regCounter: tregister;
  54. opCount: byte;
  55. begin
  56. modifiesConflictingMemLocation := false;
  57. if p1^.typ <> ait_instruction then
  58. exit;
  59. p := paicpu(p1);
  60. case p^.opcode of
  61. A_MOV,A_MOVSX,A_MOVZX:
  62. if p^.oper[1].typ = top_ref then
  63. for regCounter := R_EAX to R_EDI do
  64. begin
  65. if writeToMemDestroysContents(reg32(p^.oper[0].reg),p^.oper[1].ref^,
  66. regCounter,c[regCounter]) then
  67. begin
  68. exclude(regsStillValid,regCounter);
  69. modifiesConflictingMemLocation := not(reg in regsStillValid);
  70. end;
  71. end
  72. else
  73. if is_reg_var[reg32(p^.oper[1].reg)] then
  74. for regCounter := R_EAX to R_EDI do
  75. begin
  76. if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
  77. begin
  78. exclude(regsStillValid,regCounter);
  79. modifiesConflictingMemLocation := not(reg in regsStillValid);
  80. end
  81. end;
  82. A_DIV, A_IDIV, A_MUL, A_IMUL:
  83. begin
  84. if (p^.ops = 1) then
  85. begin
  86. if is_reg_var[R_EDX] and
  87. (not getNextInstruction(p,hp) or
  88. not((hp^.typ = ait_instruction) and
  89. (hp^.opcode = A_MOV) and
  90. (hp^.oper[0].typ = top_reg) and
  91. (reg32(hp^.oper[0].reg) = R_EDX) and
  92. getNextInstruction(hp,hp) and
  93. (hp^.typ = ait_instruction) and
  94. (hp^.opcode = A_POP) and
  95. (hp^.oper[0].reg = R_EDX))) then
  96. for regCounter := R_EAX to R_EDI do
  97. if writeToRegDestroysContents(R_EDX,regCounter,c[regCounter]) then
  98. begin
  99. exclude(regsStillValid,R_EDX);
  100. modifiesConflictingMemLocation := not(reg in regsStillValid);
  101. end
  102. end
  103. else
  104. { only possible for imul }
  105. { last operand is always destination }
  106. if is_reg_var[reg32(p^.oper[p^.ops-1].reg)] then
  107. for regCounter := R_EAX to R_EDI do
  108. begin
  109. if writeDestroysContents(p^.oper[p^.ops-1],regCounter,c[regCounter]) then
  110. begin
  111. exclude(regsStillValid,regCounter);
  112. modifiesConflictingMemLocation := not(reg in regsStillValid);
  113. end
  114. end
  115. end;
  116. else
  117. for opCount := 1 to MaxCh do
  118. case InsProp[p^.opcode].Ch[opCount] of
  119. Ch_MOp1,CH_WOp1,CH_RWOp1:
  120. if (p^.oper[0].typ = top_ref) or
  121. ((p^.oper[0].typ = top_reg) and
  122. is_reg_var[reg32(p^.oper[0].reg)]) then
  123. for regCounter := R_EAX to R_EDI do
  124. if writeDestroysContents(p^.oper[0],regCounter,c[regCounter]) then
  125. begin
  126. exclude(regsStillValid,regCounter);
  127. modifiesConflictingMemLocation := not(reg in regsStillValid);
  128. end;
  129. Ch_MOp2,CH_WOp2,CH_RWOp2:
  130. if (p^.oper[1].typ = top_ref) or
  131. ((p^.oper[1].typ = top_reg) and
  132. is_reg_var[reg32(p^.oper[1].reg)]) then
  133. for regCounter := R_EAX to R_EDI do
  134. if writeDestroysContents(p^.oper[1],regCounter,c[regCounter]) then
  135. begin
  136. exclude(regsStillValid,regCounter);
  137. modifiesConflictingMemLocation := not(reg in regsStillValid);
  138. end;
  139. Ch_MOp3,CH_WOp3,CH_RWOp3:
  140. if (p^.oper[2].typ = top_ref) or
  141. ((p^.oper[2].typ = top_reg) and
  142. is_reg_var[reg32(p^.oper[2].reg)]) then
  143. for regCounter := R_EAX to R_EDI do
  144. if writeDestroysContents(p^.oper[2],regCounter,c[regCounter]) then
  145. begin
  146. exclude(regsStillValid,regCounter);
  147. modifiesConflictingMemLocation := not(reg in regsStillValid);
  148. end;
  149. Ch_WMemEDI:
  150. begin
  151. fillchar(tmpref,sizeof(tmpref),0);
  152. tmpRef.base := R_EDI;
  153. tmpRef.index := R_EDI;
  154. for regCounter := R_EAX to R_EDI do
  155. if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter]) then
  156. begin
  157. exclude(regsStillValid,regCounter);
  158. modifiesConflictingMemLocation := not(reg in regsStillValid);
  159. end;
  160. end;
  161. end;
  162. end;
  163. end;
  164. function getPrevSequence(p: pai; reg: tregister; currentPrev: pai; var newPrev: pai;
  165. var passedJump: boolean; var regsNotRead, regsStillValid: tregset): tregister;
  166. const
  167. current_reg: tregister = R_NO;
  168. function stillValid(p: pai): boolean;
  169. begin
  170. stillValid :=
  171. (p^.typ = ait_instruction) and
  172. (paicpu(p)^.opcode <> a_jmp) and
  173. (ppaiprop(p^.optinfo)^.regs[reg].wstate =
  174. ppaiprop(currentPrev^.optinfo)^.regs[reg].wstate) and
  175. { in case destroyreg is called with doIncState = false }
  176. (ppaiprop(p^.optinfo)^.regs[reg].typ =
  177. ppaiprop(currentPrev^.optinfo)^.regs[reg].typ) and
  178. (reg in (regsNotRead * regsStillValid));
  179. passedJump :=
  180. (p^.typ = ait_instruction) and
  181. (paicpu(p)^.is_jmp);
  182. end;
  183. function findChangedRegister(p: pai): tregister;
  184. var
  185. regCounter: tregister;
  186. begin
  187. for regCounter := succ(current_reg) to R_EDI do
  188. with ppaiprop(p^.optinfo)^.regs[regCounter] do
  189. if ((startmod <>
  190. ppaiprop(currentPrev^.optinfo)^.regs[regCounter].startmod) or
  191. (nrOfMods <>
  192. ppaiprop(currentPrev^.optinfo)^.regs[regCounter].nrOfMods)) and
  193. (ppaiprop(p^.optinfo)^.regs[regCounter].typ in
  194. [con_ref,con_noRemoveRef]) then
  195. begin
  196. findChangedRegister := regCounter;
  197. current_reg := regCounter;
  198. exit;
  199. end;
  200. current_reg := R_NO;
  201. findChangedRegister := R_NO;
  202. end;
  203. var
  204. hp, prevFound: pai;
  205. tmpResult, regCounter: tregister;
  206. begin
  207. if not(current_reg in [R_NO,R_EDI]) then
  208. begin
  209. tmpResult := findChangedRegister(currentPrev);
  210. if tmpResult <> R_NO then
  211. begin
  212. getPrevSequence := tmpResult;
  213. exit;
  214. end;
  215. end;
  216. getPrevSequence := R_NO;
  217. passedJump := passedJump or
  218. ((currentPrev^.typ = ait_instruction) and
  219. (paicpu(currentPrev)^.is_jmp));
  220. if (passedJump and not(reg in (usableregs+[R_EDI]))) or
  221. not getLastInstruction(currentPrev,hp) then
  222. exit;
  223. prevFound := currentPrev;
  224. tmpResult := R_NO;
  225. while (tmpResult = R_NO) and
  226. stillValid(hp) and
  227. not(modifiesConflictingMemLocation(prevFound,reg,
  228. ppaiprop(p^.optinfo)^.regs,regsStillValid)) do
  229. begin
  230. { only update the regsread for the instructions we already passed }
  231. if not(ppaiprop(prevFound^.optinfo)^.canBeRemoved) then
  232. for regCounter := R_EAX to R_EDI do
  233. if regReadByInstruction(regCounter,prevFound) then
  234. exclude(regsNotRead,regCounter);
  235. { in case getPreviousInstruction fails and sets hp to nil in the }
  236. { next iteration }
  237. prevFound := hp;
  238. if not(ppaiprop(hp^.optinfo)^.canBeRemoved) then
  239. tmpResult := findChangedRegister(hp);
  240. if { do not load the self pointer or a regvar before a (conditional) }
  241. { jump with a new value, since if the jump is taken, the old value }
  242. { is (probably) still necessary }
  243. (passedJump and not(reg in (usableregs+[R_EDI]))) or
  244. not getLastInstruction(hp,hp) then
  245. break;
  246. end;
  247. getPrevSequence := tmpResult;
  248. if tmpResult <> R_NO then
  249. newPrev := prevFound;
  250. end;
  251. function isSimpleMemLoc(const ref: treference): boolean;
  252. begin
  253. isSimpleMemLoc :=
  254. (ref.index = R_NO) and
  255. (not(ref.base in (usableregs+[R_EDI])) or
  256. (assigned(ref.symbol) and
  257. (ref.base = R_NO) and
  258. (ref.index = R_NO)));
  259. end;
  260. {checks whether the current instruction sequence (starting with p) and the
  261. one between StartMod and EndMod of Reg are the same. If so, the number of
  262. instructions that match is stored in Found and true is returned, otherwise
  263. Found holds the number of instructions between StartMod and EndMod and false
  264. is returned}
  265. Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint;
  266. Var RegInfo: TRegInfo): Boolean;
  267. const
  268. checkingPrevSequences: boolean = false;
  269. var
  270. regsNotRead, regsStillValid: tregset;
  271. function getNextRegToTest(var prev: pai; currentReg: tregister): tregister;
  272. const
  273. passedJump: boolean = false;
  274. begin
  275. if not checkingPrevSequences then
  276. begin
  277. Repeat
  278. Inc(currentReg);
  279. Until (currentReg > R_EDI) or
  280. (ppaiprop(prev^.optInfo)^.regs[currentReg].typ
  281. in [con_ref,con_noRemoveRef]);
  282. if currentReg > R_EDI then
  283. begin
  284. if isSimpleMemLoc(paicpu(p)^.oper[0].ref^) then
  285. begin
  286. checkingPrevSequences := true;
  287. passedJump := false;
  288. end
  289. else
  290. getNextRegToTest := R_NO;
  291. end
  292. else getNextRegToTest := currentReg;
  293. end;
  294. if checkingPrevSequences then
  295. getNextRegToTest :=
  296. getPrevSequence(p,reg,prev,prev,passedJump,regsNotRead,RegsStillValid);
  297. end;
  298. Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai;
  299. {Cnt,} OldNrOfMods: Longint;
  300. startRegInfo, OrgRegInfo, HighRegInfo: TRegInfo;
  301. HighFound, OrgRegFound: Byte;
  302. RegCounter, regCounter2: TRegister;
  303. OrgRegResult: Boolean;
  304. TmpResult: Boolean;
  305. {TmpState: Byte;}
  306. Begin {CheckSequence}
  307. Reg := Reg32(Reg);
  308. TmpResult := False;
  309. FillChar(OrgRegInfo, SizeOf(OrgRegInfo), 0);
  310. FillChar(startRegInfo, sizeof(startRegInfo), 0);
  311. OrgRegFound := 0;
  312. HighFound := 0;
  313. OrgRegResult := False;
  314. with startRegInfo do
  315. begin
  316. newRegsEncountered := [procinfo^.FramePointer, stack_pointer];
  317. new2OldReg[procinfo^.FramePointer] := procinfo^.FramePointer;
  318. new2OldReg[stack_pointer] := stack_pointer;
  319. oldRegsEncountered := newRegsEncountered;
  320. end;
  321. checkingPrevSequences := false;
  322. regsNotRead := [R_EAX,R_EBX,R_ECX,R_EDX,R_ESP,R_EBP,R_EDI,R_ESI];
  323. regsStillValid := regsNotRead;
  324. GetLastInstruction(p, prev);
  325. regCounter := getNextRegToTest(prev,R_NO);
  326. While (RegCounter <> R_NO) Do
  327. Begin
  328. regInfo := startRegInfo;
  329. Found := 0;
  330. hp2 := PPaiProp(prev^.OptInfo)^.Regs[RegCounter].StartMod;
  331. If (prev <> PPaiProp(prev^.OptInfo)^.Regs[RegCounter].StartMod)
  332. Then OldNrOfMods := PPaiProp(prev^.OptInfo)^.Regs[RegCounter].NrOfMods
  333. Else OldNrOfMods := 1;
  334. hp3 := p;
  335. While (Found <> OldNrOfMods) And
  336. { old new }
  337. InstructionsEquivalent(hp2, hp3, RegInfo) Do
  338. Begin
  339. if (hp3^.typ = ait_instruction) and
  340. ((paicpu(hp3)^.opcode = A_MOV) or
  341. (paicpu(hp3)^.opcode = A_MOVZX) or
  342. (paicpu(hp3)^.opcode = A_MOVSX)) and
  343. (paicpu(hp3)^.oper[0].typ in
  344. [top_const,top_ref,top_symbol]) and
  345. (paicpu(hp3)^.oper[1].typ = top_reg) and
  346. not(regInRef(reg32(paicpu(hp3)^.oper[1].reg),
  347. paicpu(hp3)^.oper[0].ref^)) then
  348. regInfo.lastReload
  349. [reg32(paicpu(hp3)^.oper[1].reg)] := hp3;
  350. GetNextInstruction(hp2, hp2);
  351. GetNextInstruction(hp3, hp3);
  352. Inc(Found)
  353. End;
  354. for regCounter2 := R_EAX to R_EDI do
  355. if (regInfo.new2OldReg[regCounter2] <> R_NO) and
  356. (regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and
  357. not regLoadedWithNewValue(regCounter2,false,hp3) then
  358. include(regInfo.regsStillUsedAfterSeq,regCounter2);
  359. if checkingPrevSequences then
  360. for regCounter2 := R_EAX to R_EDI do
  361. if not(regInfo.new2OldReg[regCounter2] in [R_NO,regCounter2]) and
  362. (not(regCounter2 in (regsNotRead * regsStillValid)) or
  363. not(regInfo.new2OldReg[regCounter2] in regsStillValid)) then
  364. begin
  365. found := 0;
  366. break;
  367. end;
  368. If (Found <> OldNrOfMods) or
  369. { the following is to avoid problems with rangecheck code (see testcse2) }
  370. (assigned(hp3) and
  371. ((reg in regInfo.regsLoadedForRef) and
  372. (reg in PPaiProp(hp3^.optInfo)^.usedRegs) and
  373. not regLoadedWithNewValue(reg,false,hp3))) then
  374. Begin
  375. TmpResult := False;
  376. If (found > 0) then
  377. {this is correct because we only need to turn off the CanBeRemoved flag
  378. when an instruction has already been processed by CheckSequence
  379. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  380. If it has already been processed by CheckSequence and flagged to be
  381. removed, it means that it has been checked against a previous sequence
  382. and that it was equal (otherwise CheckSequence would have returned false
  383. and the instruction wouldn't have been removed). If this "If found > 0"
  384. check is left out, incorrect optimizations are performed.}
  385. Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
  386. End
  387. Else TmpResult := True;
  388. If TmpResult And
  389. (Found > HighFound)
  390. Then
  391. Begin
  392. highPrev := prev;
  393. HighFound := Found;
  394. HighRegInfo := RegInfo;
  395. End;
  396. If (RegCounter = Reg) Then
  397. Begin
  398. orgPrev := prev;
  399. OrgRegFound := Found;
  400. OrgRegResult := TmpResult;
  401. OrgRegInfo := RegInfo
  402. End;
  403. regCounter := getNextRegToTest(prev,regCounter);
  404. End;
  405. If (HighFound > 0) And
  406. (Not(OrgRegResult) Or
  407. (HighFound > OrgRegFound))
  408. Then
  409. Begin
  410. {$ifndef fpc}
  411. TmpResult := True;
  412. {$else fpc}
  413. CheckSequence := True;
  414. {$endif fpc}
  415. prev := highPrev;
  416. RegInfo := HighRegInfo;
  417. Found := HighFound
  418. End
  419. Else
  420. Begin
  421. {$ifndef fpc}
  422. TmpResult := OrgRegResult;
  423. {$else fpc}
  424. CheckSequence := OrgRegResult;
  425. {$endif fpc}
  426. prev := orgPrev;
  427. Found := OrgRegFound;
  428. RegInfo := OrgRegInfo;
  429. End;
  430. {$ifndef fpc}
  431. CheckSequence := TmpResult;
  432. {$endif fpc}
  433. End; {CheckSequence}
  434. Procedure SetAlignReg(p: Pai);
  435. Const alignSearch = 12;
  436. var regsUsable: TRegSet;
  437. prevInstrCount, nextInstrCount: Longint;
  438. prevState, nextWState,nextRState: Array[R_EAX..R_EDI] of byte;
  439. regCounter, lastRemoved: TRegister;
  440. prev, next: Pai;
  441. {$ifdef alignregdebug}
  442. temp: Pai;
  443. {$endif alignregdebug}
  444. begin
  445. regsUsable := [R_EAX,R_ECX,R_EDX,R_EBX,{R_ESP,R_EBP,}R_ESI,R_EDI];
  446. for regCounter := R_EAX to R_EDI do
  447. begin
  448. prevState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  449. nextWState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  450. nextRState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].rState;
  451. end;
  452. getLastInstruction(p,prev);
  453. getNextInstruction(p,next);
  454. lastRemoved := pai_align(p)^.reg;
  455. nextInstrCount := 0;
  456. prevInstrCount := 0;
  457. while ((assigned(prev) and
  458. assigned(prev^.optInfo) and
  459. (prevInstrCount < alignSearch)) or
  460. (assigned(next) and
  461. assigned(next^.optInfo) and
  462. (nextInstrCount < alignSearch))) And
  463. (regsUsable <> []) do
  464. begin
  465. {$ifdef alignregdebug}
  466. if assigned(prev) then
  467. begin
  468. temp := new(pai_asm_comment,init(strpnew('got here')));
  469. temp^.next := prev^.next;
  470. temp^.previous := prev;
  471. prev^.next := temp;
  472. if assigned(temp^.next) then
  473. temp^.next^.previous := temp;
  474. end;
  475. {$endif alignregdebug}
  476. if assigned(prev) and assigned(prev^.optinfo) and
  477. (prevInstrCount < alignSearch) then
  478. begin
  479. if (prev^.typ = ait_instruction) And
  480. (insProp[PaiCpu(prev)^.opcode].ch[1] <> Ch_ALL) and
  481. (PaiCpu(prev)^.opcode <> A_JMP) then
  482. begin
  483. inc(prevInstrCount);
  484. for regCounter := R_EAX to R_EDI do
  485. begin
  486. if (regCounter in regsUsable) And
  487. (PPaiProp(prev^.optInfo)^.Regs[regCounter].wState <>
  488. prevState[regCounter]) then
  489. begin
  490. lastRemoved := regCounter;
  491. exclude(regsUsable,regCounter);
  492. {$ifdef alignregdebug}
  493. temp := new(pai_asm_comment,init(strpnew(
  494. att_reg2str[regCounter]+' removed')));
  495. temp^.next := prev^.next;
  496. temp^.previous := prev;
  497. prev^.next := temp;
  498. if assigned(temp^.next) then
  499. temp^.next^.previous := temp;
  500. if regsUsable = [] then
  501. begin
  502. temp := new(pai_asm_comment,init(strpnew(
  503. 'regsUsable empty here')));
  504. temp^.next := prev^.next;
  505. temp^.previous := prev;
  506. prev^.next := temp;
  507. if assigned(temp^.next) then
  508. temp^.next^.previous := temp;
  509. end;
  510. {$endif alignregdebug}
  511. end;
  512. prevState[regCounter] :=
  513. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState;
  514. end;
  515. getLastInstruction(prev,prev);
  516. end
  517. else
  518. If GetLastInstruction(prev,prev) and
  519. assigned(prev^.optinfo) then
  520. for regCounter := R_EAX to R_EDI do
  521. prevState[regCounter] :=
  522. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState
  523. end;
  524. if assigned(next) and assigned(next^.optInfo) and
  525. (nextInstrCount < alignSearch) then
  526. begin
  527. if (next^.typ = ait_instruction) and
  528. (insProp[PaiCpu(next)^.opcode].ch[1] <> Ch_ALL) and
  529. (PaiCpu(next)^.opcode <> A_JMP) then
  530. begin
  531. inc(nextInstrCount);
  532. for regCounter := R_EAX to R_EDI do
  533. begin
  534. if (regCounter in regsUsable) And
  535. ((PPaiProp(next^.optInfo)^.Regs[regCounter].wState <>
  536. nextWState[regCounter]) or
  537. (PPaiProp(next^.optInfo)^.Regs[regCounter].rState <>
  538. nextRState[regCounter])) Then
  539. begin
  540. lastRemoved := regCounter;
  541. exclude(regsUsable,regCounter);
  542. {$ifdef alignregdebug}
  543. temp := new(pai_asm_comment,init(strpnew(
  544. att_reg2str[regCounter]+' removed')));
  545. temp^.next := next^.next;
  546. temp^.previous := next;
  547. next^.next := temp;
  548. if assigned(temp^.next) then
  549. temp^.next^.previous := temp;
  550. if regsUsable = [] then
  551. begin
  552. temp := new(pai_asm_comment,init(strpnew(
  553. 'regsUsable empty here')));
  554. temp^.next := next^.next;
  555. temp^.previous := next;
  556. next^.next := temp;
  557. if assigned(temp^.next) then
  558. temp^.next^.previous := temp;
  559. end;
  560. {$endif alignregdebug}
  561. end;
  562. nextWState[regCounter] :=
  563. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  564. nextRState[regCounter] :=
  565. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  566. end
  567. end
  568. else
  569. for regCounter := R_EAX to R_EDI do
  570. begin
  571. nextWState[regCounter] :=
  572. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  573. nextRState[regCounter] :=
  574. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  575. end;
  576. getNextInstruction(next,next);
  577. end;
  578. end;
  579. if regsUsable <> [] then
  580. for regCounter := R_EAX to R_EDI do
  581. if regCounter in regsUsable then
  582. begin
  583. lastRemoved := regCounter;
  584. break
  585. end;
  586. {$ifdef alignregdebug}
  587. next := new(pai_asm_comment,init(strpnew(att_reg2str[lastRemoved]+
  588. ' chosen as alignment register')));
  589. next^.next := p^.next;
  590. next^.previous := p;
  591. p^.next := next;
  592. if assigned(next^.next) then
  593. next^.next^.previous := next;
  594. {$endif alignregdebug}
  595. pai_align(p)^.reg := lastRemoved;
  596. End;
  597. Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p, endP: pai);
  598. var
  599. {$ifdef replaceregdebug}
  600. hp: pai;
  601. l: longint;
  602. {$endif replaceregdebug}
  603. tmpState: byte;
  604. begin
  605. {$ifdef replaceregdebug}
  606. l := random(1000);
  607. hp := new(pai_asm_comment,init(strpnew(
  608. 'restored '+att_reg2str[reg]+' with data from here... '+tostr(l))));
  609. hp^.next := p;
  610. hp^.previous := p^.previous;
  611. p^.previous := hp;
  612. if assigned(hp^.previous) then
  613. hp^.previous^.next := hp;
  614. {$endif replaceregdebug}
  615. { PPaiProp(p^.optInfo)^.Regs[reg] := c;}
  616. While (p <> endP) Do
  617. Begin
  618. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  619. getNextInstruction(p,p);
  620. end;
  621. tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
  622. repeat
  623. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  624. until not getNextInstruction(p,p) or
  625. (PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
  626. {$ifdef replaceregdebug}
  627. if assigned(p) then
  628. begin
  629. hp := new(pai_asm_comment,init(strpnew(
  630. 'restored '+att_reg2str[reg]+' till here... '+tostr(l))));
  631. hp^.next := p;
  632. hp^.previous := p^.previous;
  633. p^.previous := hp;
  634. if assigned(hp^.previous) then
  635. hp^.previous^.next := hp;
  636. end;
  637. {$endif replaceregdebug}
  638. end;
  639. function FindRegDealloc(reg: tregister; p: pai): boolean;
  640. { assumes reg is a 32bit register }
  641. var
  642. hp: pai;
  643. first: boolean;
  644. begin
  645. findregdealloc := false;
  646. first := true;
  647. while assigned(p^.previous) and
  648. ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
  649. ((Pai(p^.previous)^.typ = ait_label) and
  650. labelCanBeSkipped(pai_label(p^.previous)))) do
  651. begin
  652. p := pai(p^.previous);
  653. if (p^.typ = ait_regalloc) and
  654. (pairegalloc(p)^.reg = reg) then
  655. if not(pairegalloc(p)^.allocation) then
  656. if first then
  657. begin
  658. findregdealloc := true;
  659. break;
  660. end
  661. else
  662. begin
  663. findRegDealloc :=
  664. getNextInstruction(p,hp) and
  665. regLoadedWithNewValue(reg,false,hp);
  666. break
  667. end
  668. else
  669. first := false;
  670. end
  671. end;
  672. Procedure ClearRegContentsFrom(reg: TRegister; p, endP: pai);
  673. { first clears the contents of reg from p till endP. Then the contents are }
  674. { cleared until the first instruction that changes reg }
  675. var
  676. {$ifdef replaceregdebug}
  677. hp: pai;
  678. l: longint;
  679. {$endif replaceregdebug}
  680. oldStartmod: pai;
  681. begin
  682. {$ifdef replaceregdebug}
  683. l := random(1000);
  684. hp := new(pai_asm_comment,init(strpnew(
  685. 'cleared '+att_reg2str[reg]+' from here... '+tostr(l))));
  686. hp^.next := p;
  687. hp^.previous := p^.previous;
  688. p^.previous := hp;
  689. if assigned(hp^.previous) then
  690. hp^.previous^.next := hp;
  691. {$endif replaceregdebug}
  692. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  693. While (p <> endP) Do
  694. Begin
  695. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  696. getNextInstruction(p,p);
  697. end;
  698. oldStartmod := PPaiProp(p^.optInfo)^.Regs[reg].startmod;
  699. repeat
  700. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  701. until not getNextInstruction(p,p) or
  702. (PPaiProp(p^.optInfo)^.Regs[reg].startmod <> oldStartmod);
  703. {$ifdef replaceregdebug}
  704. if assigned(p) then
  705. begin
  706. hp := new(pai_asm_comment,init(strpnew(
  707. 'cleared '+att_reg2str[reg]+' till here... '+tostr(l))));
  708. hp^.next := p;
  709. hp^.previous := p^.previous;
  710. p^.previous := hp;
  711. if assigned(hp^.previous) then
  712. hp^.previous^.next := hp;
  713. end;
  714. {$endif replaceregdebug}
  715. end;
  716. function NoHardCodedRegs(p: paicpu; orgReg, newReg: tRegister): boolean;
  717. var chCount: byte;
  718. begin
  719. case p^.opcode of
  720. A_IMUL: noHardCodedRegs := p^.ops <> 1;
  721. A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
  722. (p^.oper[0].typ <> top_reg) or
  723. ((orgReg <> R_ECX) and (newReg <> R_ECX));
  724. else
  725. begin
  726. NoHardCodedRegs := true;
  727. with InsProp[p^.opcode] do
  728. for chCount := 1 to MaxCh do
  729. if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
  730. begin
  731. NoHardCodedRegs := false;
  732. break
  733. end;
  734. end;
  735. end;
  736. end;
  737. function ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister): boolean;
  738. begin
  739. changeReg := true;
  740. if reg = newReg then
  741. reg := orgReg
  742. else if reg = regtoreg8(newReg) then
  743. reg := regtoreg8(orgReg)
  744. else if reg = regtoreg16(newReg) then
  745. reg := regtoreg16(orgReg)
  746. else changeReg := false;
  747. end;
  748. function changeOp(var o: toper; orgReg, newReg: tregister): boolean;
  749. begin
  750. case o.typ of
  751. top_reg: changeOp := changeReg(o.reg,orgReg,newReg);
  752. top_ref:
  753. begin
  754. changeOp :=
  755. changeReg(o.ref^.base,orgReg,newReg) or
  756. changeReg(o.ref^.index,orgReg,newReg);
  757. end;
  758. end;
  759. end;
  760. procedure updateStates(orgReg,newReg: tregister; hp: pai; writeStateToo: boolean);
  761. var
  762. prev: pai;
  763. newOrgRegRState, newOrgRegWState: byte;
  764. begin
  765. if getLastInstruction(hp,prev) then
  766. with ppaiprop(prev^.optinfo)^ do
  767. begin
  768. newOrgRegRState := regs[orgReg].rState +
  769. ppaiprop(hp^.optinfo)^.regs[newReg].rState - regs[newReg].rstate;
  770. if writeStateToo then
  771. newOrgRegWState := regs[orgReg].wState +
  772. ppaiprop(hp^.optinfo)^.regs[newReg].wState - regs[newReg].wstate;
  773. end
  774. else
  775. with ppaiprop(hp^.optinfo)^.regs[newReg] do
  776. begin
  777. newOrgRegRState := rState;
  778. if writeStateToo then
  779. newOrgRegWState := wState;
  780. end;
  781. with ppaiprop(hp^.optinfo)^.regs[orgReg] do
  782. begin
  783. rState := newOrgRegRState;
  784. if writeStateToo then
  785. wState := newOrgRegwState;
  786. end;
  787. end;
  788. function doReplaceReg(orgReg,newReg: tregister; hp: paicpu): boolean;
  789. var
  790. opCount: byte;
  791. tmpResult: boolean;
  792. begin
  793. for opCount := 0 to 2 do
  794. tmpResult :=
  795. changeOp(hp^.oper[opCount],orgReg,newReg) or tmpResult;
  796. doReplaceReg := tmpResult;
  797. end;
  798. function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
  799. { oldreg and newreg must be 32bit components }
  800. var opCount: byte;
  801. begin
  802. RegSizesOK := true;
  803. { if only one of them is a general purpose register ... }
  804. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  805. begin
  806. for opCount := 0 to 2 do
  807. if (p^.oper[opCount].typ = top_reg) and
  808. (p^.oper[opCount].reg in [R_AL..R_DH]) then
  809. begin
  810. RegSizesOK := false;
  811. break
  812. end
  813. end;
  814. end;
  815. function doReplaceReadReg(orgReg,newReg: tregister; p: paicpu): boolean;
  816. var opCount: byte;
  817. begin
  818. doReplaceReadReg := false;
  819. { handle special case }
  820. case p^.opcode of
  821. A_IMUL:
  822. begin
  823. case p^.ops of
  824. 1: internalerror(1301001);
  825. 2,3:
  826. begin
  827. if changeOp(p^.oper[0],orgReg,newReg) then
  828. begin
  829. { updateStates(orgReg,newReg,p,false);}
  830. doReplaceReadReg := true;
  831. end;
  832. if p^.ops = 3 then
  833. if changeOp(p^.oper[1],orgReg,newReg) then
  834. begin
  835. { updateStates(orgReg,newReg,p,false);}
  836. doReplaceReadReg := true;
  837. end;
  838. end;
  839. end;
  840. end;
  841. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  842. else
  843. begin
  844. for opCount := 0 to 2 do
  845. if p^.oper[opCount].typ = top_ref then
  846. if changeOp(p^.oper[opCount],orgReg,newReg) then
  847. begin
  848. { updateStates(orgReg,newReg,p,false);}
  849. doReplaceReadReg := true;
  850. end;
  851. for opCount := 1 to MaxCh do
  852. case InsProp[p^.opcode].Ch[opCount] of
  853. Ch_ROp1:
  854. if p^.oper[0].typ = top_reg then
  855. if changeReg(p^.oper[0].reg,orgReg,newReg) then
  856. begin
  857. { updateStates(orgReg,newReg,p,false);}
  858. doReplaceReadReg := true;
  859. end;
  860. Ch_ROp2:
  861. if p^.oper[1].typ = top_reg then
  862. if changeReg(p^.oper[1].reg,orgReg,newReg) then
  863. begin
  864. { updateStates(orgReg,newReg,p,false);}
  865. doReplaceReadReg := true;
  866. end;
  867. Ch_ROp3:
  868. if p^.oper[2].typ = top_reg then
  869. if changeReg(p^.oper[2].reg,orgReg,newReg) then
  870. begin
  871. { updateStates(orgReg,newReg,p,false);}
  872. doReplaceReadReg := true;
  873. end;
  874. end;
  875. end;
  876. end;
  877. end;
  878. procedure updateState(reg: tregister; p: pai);
  879. { this procedure updates the read and write states of the instructions }
  880. { coming after p. It's called when the read/write state of p has been }
  881. { changed and this change has to be propagated to the following }
  882. { instructions as well }
  883. var
  884. newRState, newWState: byte;
  885. prevRState, prevWState: byte;
  886. doRState, doWState: boolean;
  887. begin
  888. { get the new read/write states from p }
  889. with ppaiprop(p^.optinfo)^.regs[reg] do
  890. begin
  891. newRState := rState;
  892. newWState := wState;
  893. end;
  894. if not GetNextInstruction(p,p) then
  895. exit;
  896. { get the old read/write states from the next instruction, to know }
  897. { when we can stop updating }
  898. with ppaiprop(p^.optinfo)^.regs[reg] do
  899. begin
  900. prevRState := rState;
  901. prevWState := wState;
  902. end;
  903. { adjust the states if this next instruction reads/writes the register }
  904. if regReadByInstruction(reg,p) then
  905. incState(newRState,1);
  906. if regModifiedByInstruction(reg,p) then
  907. incState(newWState,1);
  908. { do we still have to update the read and/or write states? }
  909. doRState := true;
  910. doWState := true;
  911. repeat
  912. { update the states }
  913. with ppaiprop(p^.optinfo)^.regs[reg] do
  914. begin
  915. if doRState then
  916. rState := newRState;
  917. if doWState then
  918. wState := newWState;
  919. end;
  920. if not getNextInstruction(p,p) then
  921. break;
  922. with ppaiprop(p^.optinfo)^.regs[reg] do
  923. begin
  924. { stop updating the read state if it changes }
  925. doRState :=
  926. doRState and (rState = prevRState);
  927. { if, by accident, this changed state is the same as the one }
  928. { we've been using, change it to a value that's definitely }
  929. { different from the previous and next state }
  930. if not doRState and
  931. (rState = newRState) then
  932. begin
  933. incState(newRState,1);
  934. prevRState := rState;
  935. doRState := true;
  936. end;
  937. { ditto for the write state }
  938. doWState :=
  939. doWState and (WState = prevWState);
  940. if not doWState and
  941. (wState = newWState) then
  942. begin
  943. incState(newWState,1);
  944. prevWState := wState;
  945. doWState := true;
  946. end;
  947. end;
  948. { stop when we don't have to update either state anymore }
  949. until not(doRState or doWState);
  950. end;
  951. function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
  952. const c: TContent; orgRegCanBeModified: Boolean;
  953. var returnEndP: pai): Boolean;
  954. { Tries to replace orgreg with newreg in all instructions coming after p }
  955. { until orgreg gets loaded with a new value. Returns true if successful, }
  956. { false otherwise. If successful, the contents of newReg are set to c, }
  957. { which should hold the contents of newReg before the current sequence }
  958. { started }
  959. { if the function returns true, returnEndP holds the last instruction }
  960. { where newReg was replaced by orgReg }
  961. var endP, hp: Pai;
  962. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead,
  963. stateChanged, readStateChanged: Boolean;
  964. function storeBack(p1: pai): boolean;
  965. { returns true if p1 contains an instruction that stores the contents }
  966. { of newReg back to orgReg }
  967. begin
  968. storeBack :=
  969. (p1^.typ = ait_instruction) and
  970. (paicpu(p1)^.opcode = A_MOV) and
  971. (paicpu(p1)^.oper[0].typ = top_reg) and
  972. (paicpu(p1)^.oper[0].reg = newReg) and
  973. (paicpu(p1)^.oper[1].typ = top_reg) and
  974. (paicpu(p1)^.oper[1].reg = orgReg);
  975. end;
  976. begin
  977. ReplaceReg := false;
  978. tmpResult := true;
  979. sequenceEnd := false;
  980. newRegModified := false;
  981. orgRegRead := false;
  982. removeLast := false;
  983. endP := p;
  984. while tmpResult and not sequenceEnd do
  985. begin
  986. tmpResult :=
  987. getNextInstruction(endP,endP) and
  988. (endP^.typ = ait_instruction);
  989. if tmpresult and not assigned(endP^.optInfo) then
  990. begin
  991. { hp := new(pai_asm_comment,init(strpnew('next no optinfo')));
  992. hp^.next := endp;
  993. hp^.previous := endp^.previous;
  994. endp^.previous := hp;
  995. if assigned(hp^.previous) then
  996. hp^.previous^.next := hp;}
  997. exit;
  998. end;
  999. If tmpResult and
  1000. { don't take into account instructions that will be removed }
  1001. Not (PPaiProp(endP^.optInfo)^.canBeRemoved) then
  1002. begin
  1003. { if the newReg gets stored back to the oldReg, we can change }
  1004. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  1005. { %oldReg" to "<operations on %oldReg>" }
  1006. removeLast := storeBack(endP);
  1007. sequenceEnd :=
  1008. { no support for (i)div, mul and imul with hardcoded operands }
  1009. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  1010. { if newReg gets loaded with a new value, we can stop }
  1011. { replacing newReg with oldReg here (possibly keeping }
  1012. { the original contents of oldReg so we still know them }
  1013. { afterwards) }
  1014. RegLoadedWithNewValue(newReg,true,paicpu(endP)) or
  1015. { we can also stop if we reached the end of the use of }
  1016. { newReg's current contents }
  1017. (GetNextInstruction(endp,hp) and
  1018. FindRegDealloc(newReg,hp)));
  1019. { to be able to remove the first and last instruction of }
  1020. { movl %reg1, %reg2 }
  1021. { <operations on %reg2> (replacing reg2 with reg1 here) }
  1022. { movl %reg2, %reg1 }
  1023. { %reg2 must not be use afterwards (it can be as the }
  1024. { result of a peepholeoptimization) }
  1025. removeLast := removeLast and sequenceEnd;
  1026. newRegModified :=
  1027. newRegModified or
  1028. (not(regLoadedWithNewValue(newReg,true,paicpu(endP))) and
  1029. RegModifiedByInstruction(newReg,endP));
  1030. orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
  1031. sequenceEnd := SequenceEnd and
  1032. (removeLast or
  1033. { since newReg will be replaced by orgReg, we can't allow that newReg }
  1034. { gets modified if orgReg is still read afterwards (since after }
  1035. { replacing, this would mean that orgReg first gets modified and then }
  1036. { gets read in the assumption it still contains the unmodified value) }
  1037. not(newRegModified and orgRegRead)) (* and
  1038. { since newReg will be replaced by orgReg, we can't allow that newReg }
  1039. { gets modified if orgRegCanBeModified = false }
  1040. { this now gets checked after the loop (JM) }
  1041. (orgRegCanBeModified or not(newRegModified)) *);
  1042. tmpResult :=
  1043. not(removeLast) and
  1044. not(newRegModified and orgRegRead) and
  1045. (* (orgRegCanBeModified or not(newRegModified)) and *)
  1046. (endP^.typ = ait_instruction) and
  1047. not(paicpu(endP)^.is_jmp) and
  1048. NoHardCodedRegs(paicpu(endP),orgReg,newReg) and
  1049. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  1050. not RegModifiedByInstruction(orgReg,endP);
  1051. end;
  1052. end;
  1053. sequenceEnd := sequenceEnd and
  1054. (removeLast or
  1055. (orgRegCanBeModified or not(newRegModified))) and
  1056. (not(assigned(endp)) or
  1057. not(endp^.typ = ait_instruction) or
  1058. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  1059. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  1060. not(newRegModified and
  1061. (orgReg in PPaiProp(endP^.optInfo)^.usedRegs) and
  1062. not(RegLoadedWithNewValue(orgReg,true,paicpu(endP))))));
  1063. if SequenceEnd then
  1064. begin
  1065. {$ifdef replaceregdebug}
  1066. hp := new(pai_asm_comment,init(strpnew(
  1067. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  1068. ' from here...')));
  1069. hp^.next := p;
  1070. hp^.previous := p^.previous;
  1071. p^.previous := hp;
  1072. if assigned(hp^.previous) then
  1073. hp^.previous^.next := hp;
  1074. hp := new(pai_asm_comment,init(strpnew(
  1075. 'replaced '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  1076. ' till here')));
  1077. hp^.next := endp^.next;
  1078. hp^.previous := endp;
  1079. endp^.next := hp;
  1080. if assigned(hp^.next) then
  1081. hp^.next^.previous := hp;
  1082. {$endif replaceregdebug}
  1083. replaceReg := true;
  1084. returnEndP := endP;
  1085. getNextInstruction(p,hp);
  1086. stateChanged := false;
  1087. while hp <> endP do
  1088. begin
  1089. if {not(PPaiProp(hp^.optInfo)^.canBeRemoved) and }
  1090. (hp^.typ = ait_instruction) then
  1091. stateChanged :=
  1092. doReplaceReg(orgReg,newReg,paicpu(hp)) or stateChanged;
  1093. if stateChanged then
  1094. updateStates(orgReg,newReg,hp,true);
  1095. getNextInstruction(hp,hp)
  1096. end;
  1097. if assigned(endp) and (endp^.typ = ait_instruction) then
  1098. readStateChanged :=
  1099. DoReplaceReadReg(orgReg,newReg,paicpu(endP));
  1100. if stateChanged or readStateChanged then
  1101. updateStates(orgReg,newReg,endP,stateChanged);
  1102. if stateChanged or readStateChanged then
  1103. updateState(orgReg,endP);
  1104. { the replacing stops either at the moment that }
  1105. { a) the newreg gets loaded with a new value (one not depending on the }
  1106. { current value of newreg) }
  1107. { b) newreg is completely replaced in this sequence and it's current value }
  1108. { isn't used anymore }
  1109. { In case b, the newreg was completely replaced by oldreg, so it's contents }
  1110. { are unchanged compared the start of this sequence, so restore them }
  1111. If removeLast or
  1112. RegLoadedWithNewValue(newReg,true,endP) then
  1113. GetLastInstruction(endP,hp)
  1114. else hp := endP;
  1115. if removeLast or
  1116. (p <> endp) or
  1117. not RegLoadedWithNewValue(newReg,true,endP) then
  1118. RestoreRegContentsTo(newReg,c,p,hp);
  1119. { In both case a and b, it is possible that the new register was modified }
  1120. { (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
  1121. { oldreg's contents have been changed. To take this into account, we simply }
  1122. { set the contents of orgreg to "unknown" after this sequence }
  1123. if newRegModified then
  1124. ClearRegContentsFrom(orgReg,p,hp);
  1125. if removeLast then
  1126. ppaiprop(endP^.optinfo)^.canBeRemoved := true;
  1127. allocRegBetween(asml,orgReg,p,endP);
  1128. end
  1129. {$ifdef replaceregdebug}
  1130. else
  1131. begin
  1132. hp := new(pai_asm_comment,init(strpnew(
  1133. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  1134. ' from here...')));
  1135. hp^.previous := p^.previous;
  1136. hp^.next := p;
  1137. p^.previous := hp;
  1138. if assigned(hp^.previous) then
  1139. hp^.previous^.next := hp;
  1140. hp := new(pai_asm_comment,init(strpnew(
  1141. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  1142. ' failed here')));
  1143. hp^.next := endp^.next;
  1144. hp^.previous := endp;
  1145. endp^.next := hp;
  1146. if assigned(hp^.next) then
  1147. hp^.next^.previous := hp;
  1148. end;
  1149. {$endif replaceregdebug}
  1150. End;
  1151. Function FindRegWithConst(p: Pai; size: topsize; l: longint; Var Res: TRegister): Boolean;
  1152. {Finds a register which contains the constant l}
  1153. Var Counter: TRegister;
  1154. {$ifdef testing}
  1155. hp: pai;
  1156. {$endif testing}
  1157. tmpresult: boolean;
  1158. Begin
  1159. Counter := R_NO;
  1160. repeat
  1161. inc(counter);
  1162. tmpresult := (ppaiprop(p^.optInfo)^.regs[counter].typ in
  1163. [con_const,con_noRemoveConst]) and
  1164. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.opsize = size) and
  1165. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].typ = top_const) and
  1166. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
  1167. {$ifdef testing}
  1168. if (ppaiprop(p^.optInfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  1169. begin
  1170. hp := new(pai_asm_comment,init(strpnew(
  1171. 'checking const load of '+tostr(l)+' here...')));
  1172. hp^.next := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod;
  1173. hp^.previous := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous;
  1174. PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous := hp;
  1175. if assigned(hp^.previous) then
  1176. hp^.previous^.next := hp;
  1177. end;
  1178. {$endif testing}
  1179. until tmpresult or (Counter = R_EDI);
  1180. res := counter;
  1181. FindRegWithConst := tmpResult;
  1182. End;
  1183. procedure removePrevNotUsedLoad(p: pai; reg: tRegister; check: boolean);
  1184. { If check = true, it means the procedure has to check whether it isn't }
  1185. { possible that the contents are still used after p (used when removing }
  1186. { instructions because of a "call"), otherwise this is not necessary }
  1187. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  1188. { value of %eax isn't used anymore later on) }
  1189. var
  1190. hp1: pai;
  1191. begin
  1192. if getLastInstruction(p,hp1) then
  1193. with ppaiprop(hp1^.optInfo)^.regs[reg] do
  1194. if (typ in [con_ref,con_invalid]) and
  1195. (nrOfMods = 1) and
  1196. (rState = ppaiprop(startmod^.optInfo)^.regs[reg].rState) and
  1197. (not(check) or
  1198. (not(regInInstruction(reg,p)) and
  1199. (not(reg in usableregs) and
  1200. (startmod^.typ = ait_instruction) and
  1201. ((paicpu(startmod)^.opcode = A_MOV) or
  1202. (paicpu(startmod)^.opcode = A_MOVZX) or
  1203. (paicpu(startmod)^.opcode = A_MOVSX)) and
  1204. (paicpu(startmod)^.oper[0].typ = top_ref) and
  1205. (paicpu(startmod)^.oper[0].ref^.base = stack_pointer)) or
  1206. not(reg in ppaiprop(hp1^.optInfo)^.usedRegs) or
  1207. findRegDealloc(reg,p))) then
  1208. ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
  1209. end;
  1210. Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
  1211. {marks the instructions that can be removed by RemoveInstructs. They're not
  1212. removed immediately because sometimes an instruction needs to be checked in
  1213. two different sequences}
  1214. var cnt, cnt2, cnt3: longint;
  1215. p, hp1, hp2, prevSeq, prevSeq_next: Pai;
  1216. hp3, hp4: pai;
  1217. hp5 : pai;
  1218. RegInfo: TRegInfo;
  1219. RegCounter: TRegister;
  1220. Begin
  1221. p := First;
  1222. SkipHead(p);
  1223. First := p;
  1224. While (p <> Last) Do
  1225. Begin
  1226. Case p^.typ Of
  1227. ait_align:
  1228. if not(pai_align(p)^.use_op) then
  1229. SetAlignReg(p);
  1230. ait_instruction:
  1231. Begin
  1232. Case Paicpu(p)^.opcode Of
  1233. A_CALL:
  1234. for regCounter := R_EAX to R_EBX do
  1235. removePrevNotUsedLoad(p,regCounter,true);
  1236. A_CLD: If GetLastInstruction(p, hp1) And
  1237. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
  1238. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  1239. A_MOV, A_MOVZX, A_MOVSX:
  1240. Begin
  1241. Case Paicpu(p)^.oper[0].typ Of
  1242. Top_Ref:
  1243. Begin {destination is always a register in this case}
  1244. With PPaiProp(p^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)] Do
  1245. Begin
  1246. If (p = StartMod) And
  1247. GetLastInstruction (p, hp1) And
  1248. (hp1^.typ <> ait_marker) Then
  1249. {so we don't try to check a sequence when p is the first instruction of the block}
  1250. begin
  1251. {$ifdef csdebug}
  1252. hp5 := new(pai_asm_comment,init(strpnew(
  1253. 'cse checking '+att_reg2str[Reg32(Paicpu(p)^.oper[1].reg)])));
  1254. insertLLItem(asml,p,p^.next,hp5);
  1255. {$endif csdebug}
  1256. If CheckSequence(p,prevSeq,Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
  1257. (Cnt > 0) Then
  1258. Begin
  1259. hp1 := nil;
  1260. { although it's perfectly ok to remove an instruction which doesn't contain }
  1261. { the register that we've just checked (CheckSequence takes care of that), }
  1262. { the sequence containing this other register should also be completely }
  1263. { checked and removed, otherwise we may get situations like this: }
  1264. { }
  1265. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  1266. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  1267. { movl 8(%edx), %edx movl 8(%edx), %edx }
  1268. { movl (%eax), eax movl (%eax), eax }
  1269. { cmpl %eax, %edx cmpl %eax, %edx }
  1270. { jnz l123 getting converted to jnz l123 }
  1271. { movl 12(%ebp), %edx movl 4(%eax), eax }
  1272. { movl 16(%ebp), %eax }
  1273. { movl 8(%edx), %edx }
  1274. { movl 4(%eax), eax }
  1275. hp2 := p;
  1276. Cnt2 := 1;
  1277. While Cnt2 <= Cnt Do
  1278. Begin
  1279. If Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p)) then
  1280. begin
  1281. if ((p^.typ = ait_instruction) And
  1282. ((paicpu(p)^.OpCode = A_MOV) or
  1283. (paicpu(p)^.opcode = A_MOVZX) or
  1284. (paicpu(p)^.opcode = A_MOVSX)) And
  1285. (paicpu(p)^.Oper[0].typ in
  1286. [top_const,top_ref,top_symbol])) and
  1287. (paicpu(p)^.oper[1].typ = top_reg) then
  1288. begin
  1289. regCounter := reg32(paicpu(p)^.oper[1].reg);
  1290. if (regCounter in reginfo.regsStillUsedAfterSeq) then
  1291. begin
  1292. if (hp1 = nil) then
  1293. hp1 := reginfo.lastReload[regCounter];
  1294. end
  1295. {$ifndef noremove}
  1296. else
  1297. begin
  1298. hp5 := p;
  1299. for cnt3 := ppaiprop(p^.optinfo)^.regs[regCounter].nrofmods downto 1 do
  1300. begin
  1301. if regModifiedByInstruction(regCounter,hp5) then
  1302. PPaiProp(hp5^.OptInfo)^.CanBeRemoved := True;
  1303. getNextInstruction(hp5,hp5);
  1304. end;
  1305. end
  1306. {$endif noremove}
  1307. end
  1308. end
  1309. {$ifndef noremove}
  1310. else
  1311. PPaiProp(p^.OptInfo)^.CanBeRemoved := True
  1312. {$endif noremove}
  1313. ; Inc(Cnt2);
  1314. GetNextInstruction(p, p);
  1315. End;
  1316. {hp4 is used to get the contents of the registers before the sequence}
  1317. GetLastInstruction(hp2, hp4);
  1318. getNextInstruction(prevSeq,prevSeq_next);
  1319. {$IfDef CSDebug}
  1320. For RegCounter := R_EAX To R_EDI Do
  1321. If (RegCounter in RegInfo.RegsLoadedForRef) Then
  1322. Begin
  1323. hp5 := new(pai_asm_comment,init(strpnew('New: '+att_reg2str[RegCounter]+', Old: '+
  1324. att_reg2str[RegInfo.New2OldReg[RegCounter]])));
  1325. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
  1326. End;
  1327. {$EndIf CSDebug}
  1328. { If some registers were different in the old and the new sequence, move }
  1329. { the contents of those old registers to the new ones }
  1330. For RegCounter := R_EAX To R_EDI Do
  1331. If Not(RegCounter in [R_ESP,procinfo^.framepointer]) And
  1332. (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
  1333. Begin
  1334. AllocRegBetween(AsmL,RegInfo.New2OldReg[RegCounter],
  1335. PPaiProp(prevSeq^.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,prevSeq_next);
  1336. if hp4 <> prevSeq then
  1337. begin
  1338. if assigned(reginfo.lastReload[regCounter]) then
  1339. getLastInstruction(reginfo.lastReload[regCounter],hp3)
  1340. else hp3 := hp4;
  1341. if prevSeq <> hp3 then
  1342. clearRegContentsFrom(regCounter,prevSeq_next,
  1343. hp3);
  1344. allocRegBetween(asmL,regCounter,prevSeq,hp3);
  1345. end;
  1346. If Not(RegCounter In RegInfo.RegsLoadedForRef) And
  1347. {old reg new reg}
  1348. (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
  1349. Begin
  1350. getLastInstruction(p,hp3);
  1351. If (hp4 <> prevSeq) or
  1352. not(regCounter in usableRegs + [R_EDI,R_ESI]) or
  1353. not ReplaceReg(asmL,RegInfo.New2OldReg[RegCounter],
  1354. regCounter,hp3,
  1355. PPaiProp(PrevSeq^.optInfo)^.Regs[regCounter],true,hp5) then
  1356. begin
  1357. hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
  1358. InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
  1359. hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
  1360. {old reg new reg}
  1361. RegInfo.New2OldReg[RegCounter], RegCounter));
  1362. InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
  1363. hp3 := New(Pai_Marker,Init(NoPropInfoStart));
  1364. InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
  1365. { adjusts states in previous instruction so that it will }
  1366. { definitely be different from the previous or next state }
  1367. incstate(ppaiprop(prevSeq_next^.optinfo)^.
  1368. regs[RegInfo.New2OldReg[RegCounter]].rstate,20);
  1369. incstate(ppaiprop(prevSeq_next^.optinfo)^.
  1370. regs[regCounter].wstate,20);
  1371. updateState(RegInfo.New2OldReg[RegCounter],
  1372. prevSeq_next);
  1373. end
  1374. End
  1375. Else
  1376. { imagine the following code: }
  1377. { normal wrong optimized }
  1378. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  1379. { movl (%eax), %eax movl (%eax), %eax }
  1380. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  1381. { jne l1 jne l1 }
  1382. { movl 8(%ebp), %eax }
  1383. { movl (%eax), %edi movl %eax, %edi }
  1384. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  1385. { movl 8(%ebp), %eax }
  1386. { pushl 70(%eax) pushl 70(%eax) }
  1387. { }
  1388. { The error is that at the moment that the last instruction is executed, }
  1389. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  1390. { registers that are completely removed from a sequence (= registers in }
  1391. { RegLoadedForRef, have to be changed to their contents from before the }
  1392. { sequence. }
  1393. If RegCounter in RegInfo.RegsLoadedForRef Then
  1394. Begin
  1395. hp3 := hp2;
  1396. { cnt still holds the number of instructions }
  1397. { of the sequence, so go to the end of it }
  1398. for cnt2 := 1 to pred(cnt) Do
  1399. getNextInstruction(hp3,hp3);
  1400. { hp4 = instruction prior to start of sequence }
  1401. restoreRegContentsTo(regCounter,
  1402. PPaiProp(hp4^.OptInfo)^.Regs[RegCounter],
  1403. hp2,hp3);
  1404. End;
  1405. End;
  1406. If hp1 <> nil Then
  1407. p := hp1;
  1408. Continue;
  1409. End
  1410. Else
  1411. If (PPaiProp(p^.OptInfo)^.
  1412. regs[reg32(paicpu(p)^.oper[1].reg)].typ
  1413. in [con_ref,con_noRemoveRef]) and
  1414. (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
  1415. if (cnt > 0) then
  1416. begin
  1417. hp2 := p;
  1418. Cnt2 := 1;
  1419. While Cnt2 <= Cnt Do
  1420. Begin
  1421. If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Then
  1422. PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
  1423. Inc(Cnt2);
  1424. GetNextInstruction(p, p);
  1425. End;
  1426. Continue;
  1427. End
  1428. else
  1429. begin
  1430. { Fix for web bug 972 }
  1431. regCounter := Reg32(Paicpu(p)^.oper[1].reg);
  1432. cnt := PPaiProp(p^.optInfo)^.Regs[regCounter].nrOfMods;
  1433. hp3 := p;
  1434. for cnt2 := 1 to cnt do
  1435. if not(regModifiedByInstruction(regCounter,hp3) and
  1436. not(PPaiProp(hp3^.optInfo)^.canBeRemoved)) then
  1437. getNextInstruction(hp3,hp3)
  1438. else
  1439. break;
  1440. getLastInstruction(p,hp4);
  1441. RestoreRegContentsTo(regCounter,
  1442. PPaiProp(hp4^.optInfo)^.Regs[regCounter],
  1443. p,hp3);
  1444. end;
  1445. End;
  1446. End;
  1447. if not ppaiprop(p^.optinfo)^.canBeRemoved and
  1448. not regInRef(reg32(paicpu(p)^.oper[1].reg),
  1449. paicpu(p)^.oper[0].ref^) then
  1450. removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
  1451. End;
  1452. top_Reg:
  1453. { try to replace the new reg with the old reg }
  1454. if not(PPaiProp(p^.optInfo)^.canBeRemoved) and
  1455. { only remove if we're not storing something in a regvar }
  1456. (paicpu(p)^.oper[1].reg in (usableregs+[R_EDI])) and
  1457. (paicpu(p)^.opcode = A_MOV) and
  1458. getLastInstruction(p,hp4) then
  1459. begin
  1460. case paicpu(p)^.oper[1].typ of
  1461. top_Reg:
  1462. { we only have to start replacing from the instruction after the mov, }
  1463. { but replacereg only starts with getnextinstruction(p,p) }
  1464. if ReplaceReg(asmL,paicpu(p)^.oper[0].reg,
  1465. paicpu(p)^.oper[1].reg,p,
  1466. PPaiProp(hp4^.optInfo)^.Regs[paicpu(p)^.oper[1].reg],false,hp1) then
  1467. begin
  1468. PPaiProp(p^.optInfo)^.canBeRemoved := true;
  1469. allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
  1470. PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
  1471. hp1);
  1472. end
  1473. else
  1474. if reg32(paicpu(p)^.oper[0].reg) <> reg32(paicpu(p)^.oper[1].reg) then
  1475. removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
  1476. end
  1477. end;
  1478. top_symbol,Top_Const:
  1479. Begin
  1480. Case Paicpu(p)^.oper[1].typ Of
  1481. Top_Reg:
  1482. Begin
  1483. regCounter := Reg32(Paicpu(p)^.oper[1].reg);
  1484. If GetLastInstruction(p, hp1) Then
  1485. With PPaiProp(hp1^.OptInfo)^.Regs[regCounter] Do
  1486. if (typ in [con_const,con_noRemoveConst]) and
  1487. (paicpu(startMod)^.opsize >= paicpu(p)^.opsize) and
  1488. opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
  1489. begin
  1490. PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
  1491. allocRegBetween(asmL,regCounter,startMod,p);
  1492. end
  1493. else
  1494. removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
  1495. End;
  1496. Top_Ref:
  1497. if (paicpu(p)^.oper[0].typ = top_const) and
  1498. getLastInstruction(p,hp1) and
  1499. findRegWithConst(hp1,paicpu(p)^.opsize,paicpu(p)^.oper[0].val,regCounter) then
  1500. begin
  1501. paicpu(p)^.loadreg(0,regCounter);
  1502. allocRegBetween(AsmL,reg32(regCounter),
  1503. PPaiProp(hp1^.optinfo)^.regs[regCounter].startMod,p);
  1504. end;
  1505. End;
  1506. End;
  1507. End;
  1508. End;
  1509. A_STD: If GetLastInstruction(p, hp1) And
  1510. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
  1511. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  1512. End
  1513. End;
  1514. End;
  1515. GetNextInstruction(p, p);
  1516. End;
  1517. End;
  1518. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  1519. { Removes the marked instructions and disposes the PPaiProps of the other }
  1520. { instructions }
  1521. Var p, hp1: Pai;
  1522. begin
  1523. p := First;
  1524. While (p <> Last) Do
  1525. Begin
  1526. If (p^.typ = ait_marker) and
  1527. (pai_marker(p)^.kind in [noPropInfoStart,noPropInfoEnd]) then
  1528. begin
  1529. hp1 := pai(p^.next);
  1530. asmL^.remove(p);
  1531. dispose(p,done);
  1532. p := hp1
  1533. end
  1534. else
  1535. {$ifndef noinstremove}
  1536. if assigned(p^.optInfo) and
  1537. PPaiProp(p^.optInfo)^.canBeRemoved then
  1538. begin
  1539. hp1 := pai(p^.next);
  1540. AsmL^.Remove(p);
  1541. Dispose(p, Done);
  1542. p := hp1;
  1543. End
  1544. Else
  1545. {$endif noinstremove}
  1546. Begin
  1547. p^.OptInfo := nil;
  1548. p := pai(p^.next);;
  1549. End;
  1550. End;
  1551. FreeMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4))
  1552. End;
  1553. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  1554. Begin
  1555. DoCSE(AsmL, First, Last);
  1556. RemoveInstructs(AsmL, First, Last);
  1557. End;
  1558. End.
  1559. {
  1560. $Log$
  1561. Revision 1.14 2000-09-30 13:07:23 jonas
  1562. * fixed support for -Or with new features of CSE
  1563. Revision 1.13 2000/09/29 23:14:45 jonas
  1564. * search much further back for CSE sequences (non-conflicting stores are
  1565. now passed)
  1566. * remove more unnecessary loads of registers (especially the self pointer)
  1567. Revision 1.12 2000/09/26 11:49:41 jonas
  1568. * writes to register variables and to the self pointer now also count as
  1569. memore writes
  1570. Revision 1.11 2000/09/25 09:50:29 jonas
  1571. - removed TP conditional code
  1572. Revision 1.10 2000/09/24 15:06:14 peter
  1573. * use defines.inc
  1574. Revision 1.9 2000/09/22 15:01:59 jonas
  1575. * fixed some bugs in the previous improvements: in some cases, esi was
  1576. still being replaced before a conditional jump (the code that
  1577. detected conditional jumps sometimes skipped over them)
  1578. Revision 1.8 2000/09/20 15:00:58 jonas
  1579. + much improved CSE: the CSE now searches further back for sequences it
  1580. can reuse. After I've also implemented register renaming, the effect
  1581. should be even better (afaik web bug 1088 will then even be optimized
  1582. properly). I don't know about the slow down factor this adds. Maybe
  1583. a new optimization level should be introduced?
  1584. Revision 1.7 2000/08/25 19:40:45 jonas
  1585. * refined previous fix a bit, some instructions weren't being removed
  1586. while they could (merged from fixes branch)
  1587. * made checksequence a bit faster
  1588. Revision 1.6 2000/08/23 12:55:10 jonas
  1589. * fix for web bug 1112 and a bit of clean up in csopt386 (merged from
  1590. fixes branch)
  1591. Revision 1.5 2000/08/04 20:08:03 jonas
  1592. * improved detection of range of instructions which use a register
  1593. (merged from fixes branch)
  1594. Revision 1.4 2000/07/21 15:19:54 jonas
  1595. * daopt386: changes to getnextinstruction/getlastinstruction so they
  1596. ignore labels who have is_addr set
  1597. + daopt386/csopt386: remove loads of registers which are overwritten
  1598. before their contents are used (especially usefull for removing superfluous
  1599. maybe_loadesi outputs and push/pops transformed by below optimization
  1600. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  1601. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  1602. currently because I don't know whether it's safe to do this under Win32/
  1603. Linux (because of problems we had when using esp as frame pointer on
  1604. those os'es)
  1605. Revision 1.3 2000/07/14 05:11:48 michael
  1606. + Patch to 1.1
  1607. Revision 1.2 2000/07/13 11:32:39 michael
  1608. + removed logs
  1609. }