csopt386.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Jonas Maebe
  4. This unit contains the common subexpression elimination procedure.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit CSOpt386;
  19. {$ifdef newOptimizations}
  20. {$define foropt}
  21. {$define replacereg}
  22. {$define arithopt}
  23. {$define foldarithops}
  24. {$endif newOptimizations}
  25. Interface
  26. Uses aasm;
  27. {Procedure CSOpt386(First, Last: Pai);}
  28. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  29. Implementation
  30. Uses
  31. CObjects, verbose, hcodegen, globals,cpubase,cpuasm,DAOpt386, tgeni386;
  32. {
  33. Function PaiInSequence(P: Pai; Const Seq: TContent): Boolean;
  34. Var P1: Pai;
  35. Counter: Byte;
  36. TmpResult: Boolean;
  37. Begin
  38. TmpResult := False;
  39. P1 := Seq.StartMod;
  40. Counter := 1;
  41. While Not(TmpResult) And
  42. (Counter <= Seq.NrOfMods) Do
  43. Begin
  44. If (P = P1) Then TmpResult := True;
  45. Inc(Counter);
  46. p1 := Pai(p1^.Next);
  47. End;
  48. PaiInSequence := TmpResult;
  49. End;
  50. }
  51. Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint; Var RegInfo: TRegInfo): Boolean;
  52. {checks whether the current instruction sequence (starting with p) and the
  53. one between StartMod and EndMod of Reg are the same. If so, the number of
  54. instructions that match is stored in Found and true is returned, otherwise
  55. Found holds the number of instructions between StartMod and EndMod and false
  56. is returned}
  57. Var hp2, hp3{, EndMod}: Pai;
  58. PrevNonRemovablePai: Pai;
  59. Cnt, OldNrOfMods: Longint;
  60. OrgRegInfo, HighRegInfo: TRegInfo;
  61. HighFound, OrgRegFound: Byte;
  62. RegCounter: TRegister;
  63. OrgRegResult: Boolean;
  64. TmpResult: Boolean;
  65. TmpState: Byte;
  66. Begin {CheckSequence}
  67. Reg := Reg32(Reg);
  68. TmpResult := False;
  69. FillChar(OrgRegInfo, SizeOf(OrgRegInfo), 0);
  70. OrgRegFound := 0;
  71. HighFound := 0;
  72. OrgRegResult := False;
  73. RegCounter := R_EAX;
  74. GetLastInstruction(p, PrevNonRemovablePai);
  75. While (RegCounter <= R_EDI) And
  76. (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ <> Con_Ref) Do
  77. Inc(RegCounter);
  78. While (RegCounter <= R_EDI) Do
  79. Begin
  80. FillChar(RegInfo, SizeOf(RegInfo), 0);
  81. RegInfo.NewRegsEncountered := [procinfo^.FramePointer, R_ESP];
  82. RegInfo.OldRegsEncountered := RegInfo.NewRegsEncountered;
  83. RegInfo.New2OldReg[procinfo^.FramePointer] := procinfo^.FramePointer;
  84. RegInfo.New2OldReg[R_ESP] := R_ESP;
  85. Found := 0;
  86. hp2 := PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].StartMod;
  87. If (PrevNonRemovablePai <> PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].StartMod)
  88. Then OldNrOfMods := PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].NrOfMods
  89. Else OldNrOfMods := 1;
  90. hp3 := p;
  91. While (Found <> OldNrOfMods) And
  92. { old new }
  93. InstructionsEquivalent(hp2, hp3, RegInfo) Do
  94. Begin
  95. GetNextInstruction(hp2, hp2);
  96. GetNextInstruction(hp3, hp3);
  97. Inc(Found)
  98. End;
  99. If (Found <> OldNrOfMods) or
  100. { the following is to avoid problems with rangecheck code (see testcse2) }
  101. (assigned(hp3) and
  102. ((reg in regInfo.regsLoadedForRef) and
  103. (reg in PPaiProp(hp3^.optInfo)^.usedRegs) and
  104. not regLoadedWithNewValue(reg,false,hp3))) then
  105. Begin
  106. TmpResult := False;
  107. If (found > 0) then
  108. {this is correct because we only need to turn off the CanBeRemoved flag
  109. when an instruction has already been processed by CheckSequence
  110. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  111. If it has already been processed by CheckSequence and flagged to be
  112. removed, it means that it has been checked against a previous sequence
  113. and that it was equal (otherwise CheckSequence would have returned false
  114. and the instruction wouldn't have been removed). If this "If found > 0"
  115. check is left out, incorrect optimizations are performed.}
  116. Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
  117. End
  118. Else TmpResult := True;
  119. If TmpResult And
  120. (Found > HighFound)
  121. Then
  122. Begin
  123. HighFound := Found;
  124. HighRegInfo := RegInfo;
  125. End;
  126. If (RegCounter = Reg) Then
  127. Begin
  128. OrgRegFound := Found;
  129. OrgRegResult := TmpResult;
  130. OrgRegInfo := RegInfo
  131. End;
  132. Repeat
  133. Inc(RegCounter);
  134. Until (RegCounter > R_EDI) or
  135. ((PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ = Con_Ref) {And
  136. ((Regcounter = Reg) Or
  137. Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
  138. );
  139. End;
  140. If (HighFound > 0) And
  141. (Not(OrgRegResult) Or
  142. (HighFound > OrgRegFound))
  143. Then
  144. Begin
  145. {$ifndef fpc}
  146. TmpResult := True;
  147. {$else fpc}
  148. CheckSequence := True;
  149. {$endif fpc}
  150. RegInfo := HighRegInfo;
  151. Found := HighFound
  152. End
  153. Else
  154. Begin
  155. {$ifndef fpc}
  156. TmpResult := OrgRegResult;
  157. {$else fpc}
  158. CheckSequence := OrgRegResult;
  159. {$endif fpc}
  160. Found := OrgRegFound;
  161. RegInfo := OrgRegInfo;
  162. End;
  163. { sometimes, registers in RegsLoadedForRef (which normally aren't/shouldn't }
  164. { be used anymore after the sequence, are still used nevertheless (when }
  165. { range checking is on for instance, because this is not "normal" generated }
  166. { code, but more or less manually inserted) }
  167. (*
  168. {$ifndef fpc}
  169. If TmpResult Then
  170. {$else fpc}
  171. If CheckSequence And (Found > 0) Then
  172. {$endif fpc}
  173. For RegCounter := R_EAX to R_EDI Do
  174. If (RegCounter in RegInfo.RegsLoadedForRef) And
  175. (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
  176. Begin
  177. OldNrOfMods := PPaiProp(PrevNonRemovablePai^.OptInfo)^.
  178. Regs[RegInfo.New2OldReg[RegCounter]].NrOfMods;
  179. hp2 := p;
  180. For Cnt := 1 to Pred(OldNrOfMods) Do
  181. GetNextInstruction(hp2, hp2);
  182. { hp2 now containts the last instruction of the sequence }
  183. { get the writestate at this point of the register in TmpState }
  184. TmpState := PPaiProp(hp2^.OptInfo)^.Regs[RegCounter].WState;
  185. { now, even though reg is in RegsLoadedForRef, sometimes it's still used }
  186. { afterwards. It is not if either it is not in usedregs anymore after the }
  187. { sequence, or if it is loaded with a new value right after the sequence }
  188. If GetNextInstruction(hp2, hp2) and
  189. (TmpState = PPaiProp(hp2^.OptInfo)^.Regs[RegCounter].WState) And
  190. (RegCounter in PPaiProp(hp2^.OptInfo)^.UsedRegs) Then
  191. { it is still used, so remove it from RegsLoadedForRef }
  192. Begin
  193. {$ifdef regrefdebug}
  194. hp3 := new(pai_asm_comment,init(strpnew(att_reg2str[regcounter]+
  195. ' removed from regsloadedforref')));
  196. hp3^.fileinfo := hp2^.fileinfo;
  197. hp3^.next := hp2^.next;
  198. hp3^.previous := hp2;
  199. hp2^.next := hp3;
  200. If assigned(hp3^.next) then
  201. Pai(hp3^.next)^.previous := hp3;
  202. {$endif regrefdebug}
  203. Exclude(RegInfo.RegsLoadedForRef,RegCounter);
  204. End;
  205. End;
  206. *)
  207. {$ifndef fpc}
  208. CheckSequence := TmpResult;
  209. {$endif fpc}
  210. End; {CheckSequence}
  211. Procedure SetAlignReg(p: Pai);
  212. Const alignSearch = 12;
  213. var regsUsable: TRegSet;
  214. prevInstrCount, nextInstrCount: Longint;
  215. prevState, nextWState,nextRState: Array[R_EAX..R_EDI] of byte;
  216. regCounter, lastRemoved: TRegister;
  217. prev, next: Pai;
  218. {$ifdef alignregdebug}
  219. temp: Pai;
  220. {$endif alignregdebug}
  221. begin
  222. regsUsable := [R_EAX,R_ECX,R_EDX,R_EBX,{R_ESP,R_EBP,}R_ESI,R_EDI];
  223. for regCounter := R_EAX to R_EDI do
  224. begin
  225. prevState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  226. nextWState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  227. nextRState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].rState;
  228. end;
  229. getLastInstruction(p,prev);
  230. getNextInstruction(p,next);
  231. lastRemoved := pai_align(p)^.reg;
  232. nextInstrCount := 0;
  233. prevInstrCount := 0;
  234. while ((assigned(prev) and
  235. assigned(prev^.optInfo) and
  236. (prevInstrCount < alignSearch)) or
  237. (assigned(next) and
  238. assigned(next^.optInfo) and
  239. (nextInstrCount < alignSearch))) And
  240. (regsUsable <> []) do
  241. begin
  242. {$ifdef alignregdebug}
  243. if assigned(prev) then
  244. begin
  245. temp := new(pai_asm_comment,init(strpnew('got here')));
  246. temp^.next := prev^.next;
  247. temp^.previous := prev;
  248. prev^.next := temp;
  249. if assigned(temp^.next) then
  250. temp^.next^.previous := temp;
  251. end;
  252. {$endif alignregdebug}
  253. if assigned(prev) and assigned(prev^.optinfo) and
  254. (prevInstrCount < alignSearch) then
  255. begin
  256. if (prev^.typ = ait_instruction) And
  257. (insProp[PaiCpu(prev)^.opcode].ch[1] <> Ch_ALL) and
  258. (PaiCpu(prev)^.opcode <> A_JMP) then
  259. begin
  260. inc(prevInstrCount);
  261. for regCounter := R_EAX to R_EDI do
  262. begin
  263. if (regCounter in regsUsable) And
  264. (PPaiProp(prev^.optInfo)^.Regs[regCounter].wState <>
  265. prevState[regCounter]) then
  266. begin
  267. lastRemoved := regCounter;
  268. exclude(regsUsable,regCounter);
  269. {$ifdef alignregdebug}
  270. temp := new(pai_asm_comment,init(strpnew(
  271. att_reg2str[regCounter]+' removed')));
  272. temp^.next := prev^.next;
  273. temp^.previous := prev;
  274. prev^.next := temp;
  275. if assigned(temp^.next) then
  276. temp^.next^.previous := temp;
  277. if regsUsable = [] then
  278. begin
  279. temp := new(pai_asm_comment,init(strpnew(
  280. 'regsUsable empty here')));
  281. temp^.next := prev^.next;
  282. temp^.previous := prev;
  283. prev^.next := temp;
  284. if assigned(temp^.next) then
  285. temp^.next^.previous := temp;
  286. end;
  287. {$endif alignregdebug}
  288. end;
  289. prevState[regCounter] :=
  290. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState;
  291. end;
  292. getLastInstruction(prev,prev);
  293. end
  294. else
  295. If GetLastInstruction(prev,prev) and
  296. assigned(prev^.optinfo) then
  297. for regCounter := R_EAX to R_EDI do
  298. prevState[regCounter] :=
  299. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState
  300. end;
  301. if assigned(next) and assigned(next^.optInfo) and
  302. (nextInstrCount < alignSearch) then
  303. begin
  304. if (next^.typ = ait_instruction) and
  305. (insProp[PaiCpu(next)^.opcode].ch[1] <> Ch_ALL) and
  306. (PaiCpu(next)^.opcode <> A_JMP) then
  307. begin
  308. inc(nextInstrCount);
  309. for regCounter := R_EAX to R_EDI do
  310. begin
  311. if (regCounter in regsUsable) And
  312. ((PPaiProp(next^.optInfo)^.Regs[regCounter].wState <>
  313. nextWState[regCounter]) or
  314. (PPaiProp(next^.optInfo)^.Regs[regCounter].rState <>
  315. nextRState[regCounter])) Then
  316. begin
  317. lastRemoved := regCounter;
  318. exclude(regsUsable,regCounter);
  319. {$ifdef alignregdebug}
  320. temp := new(pai_asm_comment,init(strpnew(
  321. att_reg2str[regCounter]+' removed')));
  322. temp^.next := next^.next;
  323. temp^.previous := next;
  324. next^.next := temp;
  325. if assigned(temp^.next) then
  326. temp^.next^.previous := temp;
  327. if regsUsable = [] then
  328. begin
  329. temp := new(pai_asm_comment,init(strpnew(
  330. 'regsUsable empty here')));
  331. temp^.next := next^.next;
  332. temp^.previous := next;
  333. next^.next := temp;
  334. if assigned(temp^.next) then
  335. temp^.next^.previous := temp;
  336. end;
  337. {$endif alignregdebug}
  338. end;
  339. nextWState[regCounter] :=
  340. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  341. nextRState[regCounter] :=
  342. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  343. end
  344. end
  345. else
  346. for regCounter := R_EAX to R_EDI do
  347. begin
  348. nextWState[regCounter] :=
  349. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  350. nextRState[regCounter] :=
  351. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  352. end;
  353. getNextInstruction(next,next);
  354. end;
  355. end;
  356. if regsUsable <> [] then
  357. for regCounter := R_EAX to R_EDI do
  358. if regCounter in regsUsable then
  359. begin
  360. lastRemoved := regCounter;
  361. break
  362. end;
  363. {$ifdef alignregdebug}
  364. next := new(pai_asm_comment,init(strpnew(att_reg2str[lastRemoved]+
  365. ' chosen as alignment register')));
  366. next^.next := p^.next;
  367. next^.previous := p;
  368. p^.next := next;
  369. if assigned(next^.next) then
  370. next^.next^.previous := next;
  371. {$endif alignregdebug}
  372. pai_align(p)^.reg := lastRemoved;
  373. End;
  374. {$ifdef replacereg}
  375. function FindRegDealloc(reg: tregister; p: pai): boolean;
  376. { assumes reg is a 32bit register }
  377. begin
  378. findregdealloc := false;
  379. while assigned(p^.previous) and
  380. ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
  381. ((Pai(p^.previous)^.typ = ait_label) and
  382. not(Pai_Label(p^.previous)^.l^.is_used))) do
  383. begin
  384. p := pai(p^.previous);
  385. if (p^.typ = ait_regalloc) and
  386. (pairegalloc(p)^.reg = reg) then
  387. begin
  388. findregdealloc := not(pairegalloc(p)^.allocation);
  389. break;
  390. end;
  391. end
  392. end;
  393. Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p, endP: pai);
  394. var
  395. {$ifdef replaceregdebug}
  396. hp: pai;
  397. {$endif replaceregdebug}
  398. tmpState: byte;
  399. begin
  400. {$ifdef replaceregdebug}
  401. hp := new(pai_asm_comment,init(strpnew(
  402. 'restored '+att_reg2str[reg]+' with data from here...')));
  403. hp^.next := p;
  404. hp^.previous := p^.previous;
  405. p^.previous := hp;
  406. if assigned(hp^.previous) then
  407. hp^.previous^.next := hp;
  408. {$endif replaceregdebug}
  409. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  410. While (p <> endP) Do
  411. Begin
  412. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  413. getNextInstruction(p,p);
  414. end;
  415. tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
  416. repeat
  417. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  418. until not getNextInstruction(p,p) or
  419. (PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
  420. {$ifdef replaceregdebug}
  421. if assigned(p) then
  422. begin
  423. hp := new(pai_asm_comment,init(strpnew(
  424. 'restored '+att_reg2str[reg]+' till here...')));
  425. hp^.next := p;
  426. hp^.previous := p^.previous;
  427. p^.previous := hp;
  428. if assigned(hp^.previous) then
  429. hp^.previous^.next := hp;
  430. end;
  431. {$endif replaceregdebug}
  432. end;
  433. Procedure ClearRegContentsFrom(reg: TRegister; p, endP: pai);
  434. { first clears the contents of reg from p till endP. Then the contents are }
  435. { cleared until the first instruction that changes reg }
  436. var
  437. {$ifdef replaceregdebug}
  438. hp: pai;
  439. {$endif replaceregdebug}
  440. tmpState: byte;
  441. begin
  442. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  443. While (p <> endP) Do
  444. Begin
  445. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  446. getNextInstruction(p,p);
  447. end;
  448. tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
  449. repeat
  450. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  451. until not getNextInstruction(p,p) or
  452. (PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
  453. {$ifdef replaceregdebug}
  454. if assigned(p) then
  455. begin
  456. hp := new(pai_asm_comment,init(strpnew(
  457. 'cleared '+att_reg2str[reg]+' till here...')));
  458. hp^.next := p;
  459. hp^.previous := p^.previous;
  460. p^.previous := hp;
  461. if assigned(hp^.previous) then
  462. hp^.previous^.next := hp;
  463. end;
  464. {$endif replaceregdebug}
  465. end;
  466. function NoHardCodedRegs(p: paicpu; orgReg, newReg: tRegister): boolean;
  467. var chCount: byte;
  468. begin
  469. case p^.opcode of
  470. A_IMUL: noHardCodedRegs := p^.ops <> 1;
  471. A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
  472. (p^.oper[0].typ <> top_reg) or
  473. ((orgReg <> R_ECX) and (newReg <> R_ECX));
  474. else
  475. begin
  476. NoHardCodedRegs := true;
  477. with InsProp[p^.opcode] do
  478. for chCount := 1 to MaxCh do
  479. if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
  480. begin
  481. NoHardCodedRegs := false;
  482. break
  483. end;
  484. end;
  485. end;
  486. end;
  487. Procedure ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister);
  488. begin
  489. if reg = newReg then
  490. reg := orgReg
  491. else if reg = regtoreg8(newReg) then
  492. reg := regtoreg8(orgReg)
  493. else if reg = regtoreg16(newReg) then
  494. reg := regtoreg16(orgReg);
  495. end;
  496. procedure changeOp(var o: toper; orgReg, newReg: tregister);
  497. begin
  498. case o.typ of
  499. top_reg: changeReg(o.reg,orgReg,newReg);
  500. top_ref:
  501. begin
  502. changeReg(o.ref^.base,orgReg,newReg);
  503. changeReg(o.ref^.index,orgReg,newReg);
  504. end;
  505. end;
  506. end;
  507. Procedure DoReplaceReg(orgReg,newReg: tregister; hp: paicpu);
  508. var opCount: byte;
  509. begin
  510. for opCount := 0 to 2 do
  511. changeOp(hp^.oper[opCount],orgReg,newReg)
  512. end;
  513. function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
  514. { oldreg and newreg must be 32bit components }
  515. var opCount: byte;
  516. begin
  517. RegSizesOK := true;
  518. { if only one of them is a general purpose register ... }
  519. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  520. begin
  521. for opCount := 0 to 2 do
  522. if (p^.oper[opCount].typ = top_reg) and
  523. (p^.oper[opCount].reg in [R_AL..R_DH]) then
  524. begin
  525. RegSizesOK := false;
  526. break
  527. end
  528. end;
  529. end;
  530. procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
  531. var opCount: byte;
  532. begin
  533. { handle special case }
  534. case p^.opcode of
  535. A_IMUL:
  536. begin
  537. case p^.ops of
  538. 1: internalerror(1301001);
  539. 2,3:
  540. begin
  541. changeOp(p^.oper[0],orgReg,newReg);
  542. if p^.ops = 3 then
  543. changeOp(p^.oper[1],orgReg,newReg);
  544. end;
  545. end;
  546. end;
  547. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  548. else
  549. begin
  550. for opCount := 0 to 2 do
  551. if p^.oper[opCount].typ = top_ref then
  552. changeOp(p^.oper[opCount],orgReg,newReg);
  553. for opCount := 1 to MaxCh do
  554. case InsProp[p^.opcode].Ch[opCount] of
  555. Ch_ROp1:
  556. if p^.oper[0].typ = top_reg then
  557. ChangeReg(p^.oper[0].reg,orgReg,newReg);
  558. Ch_ROp2:
  559. if p^.oper[1].typ = top_reg then
  560. ChangeReg(p^.oper[1].reg,orgReg,newReg);
  561. Ch_ROp3:
  562. if p^.oper[2].typ = top_reg then
  563. ChangeReg(p^.oper[2].reg,orgReg,newReg);
  564. end;
  565. end;
  566. end;
  567. end;
  568. function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
  569. const c: TContent; orgRegCanBeModified: Boolean;
  570. var returnEndP: pai): Boolean;
  571. { Tries to replace orgreg with newreg in all instructions coming after p }
  572. { until orgreg gets loaded with a new value. Returns true if successful, }
  573. { false otherwise. If successful, the contents of newReg are set to c, }
  574. { which should hold the contents of newReg before the current sequence }
  575. { started }
  576. { if the function returns true, returnEndP holds the last instruction }
  577. { where newReg was replaced by orgReg }
  578. var endP, hp: Pai;
  579. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: Boolean;
  580. function storeBack(p1: pai): boolean;
  581. { returns true if p1 contains an instruction that stores the contents }
  582. { of newReg back to orgReg }
  583. begin
  584. storeBack :=
  585. (p1^.typ = ait_instruction) and
  586. (paicpu(p1)^.opcode = A_MOV) and
  587. (paicpu(p1)^.oper[0].typ = top_reg) and
  588. (paicpu(p1)^.oper[0].reg = newReg) and
  589. (paicpu(p1)^.oper[1].typ = top_reg) and
  590. (paicpu(p1)^.oper[1].reg = orgReg);
  591. end;
  592. begin
  593. ReplaceReg := false;
  594. tmpResult := true;
  595. sequenceEnd := false;
  596. newRegModified := false;
  597. orgRegRead := false;
  598. removeLast := false;
  599. endP := p;
  600. while tmpResult and not sequenceEnd do
  601. begin
  602. tmpResult :=
  603. getNextInstruction(endP,endP) and
  604. (endP^.typ = ait_instruction);
  605. if tmpresult and not assigned(endP^.optInfo) then
  606. begin
  607. { hp := new(pai_asm_comment,init(strpnew('next no optinfo')));
  608. hp^.next := endp;
  609. hp^.previous := endp^.previous;
  610. endp^.previous := hp;
  611. if assigned(hp^.previous) then
  612. hp^.previous^.next := hp;}
  613. exit;
  614. end;
  615. If tmpResult and
  616. { don't take into account instructions that will be removed }
  617. Not (PPaiProp(endP^.optInfo)^.canBeRemoved) then
  618. begin
  619. { if the newReg gets stored back to the oldReg, we can change }
  620. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  621. { %oldReg" to "<operations on %oldReg>" }
  622. removeLast := storeBack(endP);
  623. sequenceEnd :=
  624. { no support for (i)div, mul and imul with hardcoded operands }
  625. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  626. { if newReg gets loaded with a new value, we can stop }
  627. { replacing newReg with oldReg here (possibly keeping }
  628. { the original contents of oldReg so we still know them }
  629. { afterwards) }
  630. RegLoadedWithNewValue(newReg,true,paicpu(endP)) or
  631. { we can also stop if we reached the end of the use of }
  632. { newReg's current contents }
  633. (GetNextInstruction(endp,hp) and
  634. FindRegDealloc(newReg,hp)));
  635. { to be able to remove the first and last instruction of }
  636. { movl %reg1, %reg2 }
  637. { <operations on %reg2> (replacing reg2 with reg1 here) }
  638. { movl %reg2, %reg1 }
  639. { %reg2 must not be use afterwards (it can be as the }
  640. { result of a peepholeoptimization) }
  641. removeLast := removeLast and sequenceEnd;
  642. newRegModified :=
  643. newRegModified or
  644. (not(regLoadedWithNewValue(newReg,true,paicpu(endP))) and
  645. RegModifiedByInstruction(newReg,endP));
  646. orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
  647. sequenceEnd := SequenceEnd and
  648. (removeLast or
  649. { since newReg will be replaced by orgReg, we can't allow that newReg }
  650. { gets modified if orgReg is still read afterwards (since after }
  651. { replacing, this would mean that orgReg first gets modified and then }
  652. { gets read in the assumption it still contains the unmodified value) }
  653. not(newRegModified and orgRegRead)) (* and
  654. { since newReg will be replaced by orgReg, we can't allow that newReg }
  655. { gets modified if orgRegCanBeModified = false }
  656. (orgRegCanBeModified or not(newRegModified)) *);
  657. tmpResult :=
  658. not(removeLast) and
  659. not(newRegModified and orgRegRead) and
  660. (* (orgRegCanBeModified or not(newRegModified)) and *)
  661. (endP^.typ = ait_instruction) and
  662. not(paicpu(endP)^.is_jmp) and
  663. NoHardCodedRegs(paicpu(endP),orgReg,newReg) and
  664. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  665. not RegModifiedByInstruction(orgReg,endP);
  666. end;
  667. end;
  668. sequenceEnd := sequenceEnd and
  669. (removeLast or
  670. (orgRegCanBeModified or not(newRegModified))) and
  671. (not(assigned(endp)) or
  672. not(endp^.typ = ait_instruction) or
  673. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  674. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  675. not(newRegModified and
  676. (orgReg in PPaiProp(endP^.optInfo)^.usedRegs) and
  677. not(RegLoadedWithNewValue(orgReg,true,paicpu(endP))))));
  678. if SequenceEnd then
  679. begin
  680. {$ifdef replaceregdebug}
  681. hp := new(pai_asm_comment,init(strpnew(
  682. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  683. ' from here...')));
  684. hp^.next := p;
  685. hp^.previous := p^.previous;
  686. p^.previous := hp;
  687. if assigned(hp^.previous) then
  688. hp^.previous^.next := hp;
  689. hp := new(pai_asm_comment,init(strpnew(
  690. 'replaced '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  691. ' till here')));
  692. hp^.next := endp^.next;
  693. hp^.previous := endp;
  694. endp^.next := hp;
  695. if assigned(hp^.next) then
  696. hp^.next^.previous := hp;
  697. {$endif replaceregdebug}
  698. replaceReg := true;
  699. returnEndP := endP;
  700. getNextInstruction(p,hp);
  701. while hp <> endP do
  702. begin
  703. if not(PPaiProp(hp^.optInfo)^.canBeRemoved) and
  704. (hp^.typ = ait_instruction) then
  705. DoReplaceReg(orgReg,newReg,paicpu(hp));
  706. GetNextInstruction(hp,hp)
  707. end;
  708. if assigned(endp) and (endp^.typ = ait_instruction) then
  709. DoReplaceReadReg(orgReg,newReg,paicpu(endP));
  710. { the replacing stops either at the moment that }
  711. { a) the newreg gets loaded with a new value (one not depending on the }
  712. { current value of newreg) }
  713. { b) newreg is completely replaced in this sequence and it's current value }
  714. { isn't used anymore }
  715. { In case b, the newreg was completely replaced by oldreg, so it's contents }
  716. { are unchanged compared the start of this sequence, so restore them }
  717. If removeLast or
  718. RegLoadedWithNewValue(newReg,true,endP) then
  719. GetLastInstruction(endP,hp)
  720. else hp := endP;
  721. if removeLast or
  722. (p <> endp) or
  723. not RegLoadedWithNewValue(newReg,true,endP) then
  724. RestoreRegContentsTo(newReg, c ,p, hp);
  725. { In both case a and b, it is possible that the new register was modified }
  726. { (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
  727. { oldreg's contents have been changed. To take this into account, we simply }
  728. { set the contents of orgreg to "unknown" after this sequence }
  729. if newRegModified then
  730. ClearRegContentsFrom(orgReg,p,hp);
  731. if removeLast then
  732. ppaiprop(endP^.optinfo)^.canBeRemoved := true;
  733. allocRegBetween(asml,orgReg,p,endP);
  734. end
  735. {$ifdef replaceregdebug}
  736. else
  737. begin
  738. hp := new(pai_asm_comment,init(strpnew(
  739. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  740. ' from here...')));
  741. hp^.previous := p^.previous;
  742. hp^.next := p;
  743. p^.previous := hp;
  744. if assigned(hp^.previous) then
  745. hp^.previous^.next := hp;
  746. hp := new(pai_asm_comment,init(strpnew(
  747. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  748. ' failed here')));
  749. hp^.next := endp^.next;
  750. hp^.previous := endp;
  751. endp^.next := hp;
  752. if assigned(hp^.next) then
  753. hp^.next^.previous := hp;
  754. end;
  755. {$endif replaceregdebug}
  756. End;
  757. {$endif replacereg}
  758. {$ifdef arithopt}
  759. Function FindRegWithConst(p: Pai; size: topsize; l: longint; Var Res: TRegister): Boolean;
  760. {Finds a register which contains the constant l}
  761. Var Counter: TRegister;
  762. {$ifdef testing}
  763. hp: pai;
  764. {$endif testing}
  765. tmpresult: boolean;
  766. Begin
  767. Counter := R_NO;
  768. repeat
  769. inc(counter);
  770. tmpresult := (PPaiProp(p^.OptInfo)^.Regs[Counter].Typ = Con_Const) and
  771. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.opsize = size) and
  772. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].typ = top_const) and
  773. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
  774. {$ifdef testing}
  775. if (PPaiProp(p^.OptInfo)^.Regs[Counter].Typ = Con_Const) then
  776. begin
  777. hp := new(pai_asm_comment,init(strpnew(
  778. 'checking const load of '+tostr(l)+' here...')));
  779. hp^.next := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod;
  780. hp^.previous := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous;
  781. PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous := hp;
  782. if assigned(hp^.previous) then
  783. hp^.previous^.next := hp;
  784. end;
  785. {$endif testing}
  786. until tmpresult or (Counter = R_EDI);
  787. res := counter;
  788. FindRegWithConst := tmpResult;
  789. End;
  790. {$endif arithopt}
  791. Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
  792. {marks the instructions that can be removed by RemoveInstructs. They're not
  793. removed immediately because sometimes an instruction needs to be checked in
  794. two different sequences}
  795. Var Cnt, Cnt2, Cnt3: Longint;
  796. p, hp1, hp2: Pai;
  797. hp3, hp4: pai;
  798. {$ifdef replacereg}
  799. hp5 : pai;
  800. {$else}
  801. {$ifdef csdebug}
  802. hp5 : pai;
  803. {$endif}
  804. {$endif}
  805. RegInfo: TRegInfo;
  806. RegCounter: TRegister;
  807. TmpState: Byte;
  808. Begin
  809. p := First;
  810. SkipHead(p);
  811. First := p;
  812. While (p <> Last) Do
  813. Begin
  814. Case p^.typ Of
  815. ait_align:
  816. if not(pai_align(p)^.use_op) then
  817. SetAlignReg(p);
  818. ait_instruction:
  819. Begin
  820. Case Paicpu(p)^.opcode Of
  821. A_CLD: If GetLastInstruction(p, hp1) And
  822. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
  823. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  824. A_MOV, A_MOVZX, A_MOVSX:
  825. Begin
  826. Case Paicpu(p)^.oper[0].typ Of
  827. Top_Ref:
  828. Begin {destination is always a register in this case}
  829. With PPaiProp(p^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)] Do
  830. Begin
  831. If (p = StartMod) And
  832. GetLastInstruction (p, hp1) And
  833. (hp1^.typ <> ait_marker) Then
  834. {so we don't try to check a sequence when p is the first instruction of the block}
  835. begin
  836. {$ifdef csdebug}
  837. hp5 := new(pai_asm_comment,init(strpnew(
  838. 'cse checking '+att_reg2str[Reg32(Paicpu(p)^.oper[1].reg)])));
  839. insertLLItem(asml,p,p^.next,hp5);
  840. {$endif csdebug}
  841. If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
  842. (Cnt > 0) Then
  843. Begin
  844. hp1 := nil;
  845. { although it's perfectly ok to remove an instruction which doesn't contain }
  846. { the register that we've just checked (CheckSequence takes care of that), }
  847. { the sequence containing this other register should also be completely }
  848. { checked and removed, otherwise we may get situations like this: }
  849. { }
  850. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  851. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  852. { movl 8(%edx), %edx movl 8(%edx), %edx }
  853. { movl (%eax), eax movl (%eax), eax }
  854. { cmpl %eax, %edx cmpl %eax, %edx }
  855. { jnz l123 getting converted to jnz l123 }
  856. { movl 12(%ebp), %edx movl 4(%eax), eax }
  857. { movl 16(%ebp), %eax }
  858. { movl 8(%edx), %edx }
  859. { movl 4(%eax), eax }
  860. hp2 := p;
  861. Cnt2 := 1;
  862. While Cnt2 <= Cnt Do
  863. Begin
  864. If (hp1 = nil) And
  865. Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p)) And
  866. ((p^.typ = ait_instruction) And
  867. ((paicpu(p)^.OpCode = A_MOV) or
  868. (paicpu(p)^.opcode = A_MOVZX) or
  869. (paicpu(p)^.opcode = A_MOVSX)) And
  870. (paicpu(p)^.Oper[0].typ = top_ref)) Then
  871. if (PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
  872. <= (Cnt - Cnt2 + 1)) and
  873. (Reg32(paicpu(p)^.Oper[1].reg) in regInfo.regsLoadedForRef) then
  874. begin
  875. hp3 := p;
  876. for Cnt3 := PPaiProp(p^.OptInfo)^.Regs[Reg32(paicpu(p)^.Oper[1].reg)].NrOfMods
  877. downto 1 do
  878. begin
  879. {$ifndef noremove}
  880. if regInInstruction(paicpu(p)^.Oper[1].reg,hp3) then
  881. PPaiProp(hp3^.OptInfo)^.CanBeRemoved := True;
  882. {$endif noremove}
  883. getNextInstruction(hp3,hp3);
  884. end
  885. end
  886. else hp1 := p;
  887. {$ifndef noremove}
  888. if regInInstruction(Paicpu(hp2)^.oper[1].reg,p) then
  889. PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
  890. {$endif noremove}
  891. Inc(Cnt2);
  892. GetNextInstruction(p, p);
  893. End;
  894. hp3 := New(Pai_Marker,Init(NoPropInfoStart));
  895. InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
  896. {hp4 is used to get the contents of the registers before the sequence}
  897. GetLastInstruction(hp2, hp4);
  898. {$IfDef CSDebug}
  899. For RegCounter := R_EAX To R_EDI Do
  900. If (RegCounter in RegInfo.RegsLoadedForRef) Then
  901. Begin
  902. hp5 := new(pai_asm_comment,init(strpnew('New: '+att_reg2str[RegCounter]+', Old: '+
  903. att_reg2str[RegInfo.New2OldReg[RegCounter]])));
  904. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
  905. End;
  906. {$EndIf CSDebug}
  907. { If some registers were different in the old and the new sequence, move }
  908. { the contents of those old registers to the new ones }
  909. For RegCounter := R_EAX To R_EDI Do
  910. If Not(RegCounter in [R_ESP,procinfo^.framepointer]) And
  911. (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
  912. Begin
  913. AllocRegBetween(AsmL,RegInfo.New2OldReg[RegCounter],
  914. PPaiProp(hp4^.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,hp2);
  915. If Not(RegCounter In RegInfo.RegsLoadedForRef) And
  916. {old reg new reg}
  917. (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
  918. Begin
  919. {$ifdef replacereg}
  920. getLastInstruction(p,hp3);
  921. If not(regCounter in usableRegs + [R_EDI,R_ESI]) or
  922. not ReplaceReg(asmL,RegInfo.New2OldReg[RegCounter],
  923. regCounter,hp3,
  924. PPaiProp(hp4^.optInfo)^.Regs[regCounter],true,hp5) then
  925. begin
  926. {$endif replacereg}
  927. hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
  928. {old reg new reg}
  929. RegInfo.New2OldReg[RegCounter], RegCounter));
  930. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
  931. {$ifdef replacereg}
  932. end
  933. {$endif replacereg}
  934. End
  935. Else
  936. { imagine the following code: }
  937. { normal wrong optimized }
  938. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  939. { movl (%eax), %eax movl (%eax), %eax }
  940. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  941. { jne l1 jne l1 }
  942. { movl 8(%ebp), %eax }
  943. { movl (%eax), %edi movl %eax, %edi }
  944. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  945. { movl 8(%ebp), %eax }
  946. { pushl 70(%eax) pushl 70(%eax) }
  947. { }
  948. { The error is that at the moment that the last instruction is executed, }
  949. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  950. { registers that are completely removed from a sequence (= registers in }
  951. { RegLoadedForRef, have to be changed to their contents from before the }
  952. { sequence. }
  953. If RegCounter in RegInfo.RegsLoadedForRef Then
  954. Begin
  955. {load Cnt2 with the total number of instructions of this sequence}
  956. Cnt2 := PPaiProp(hp4^.OptInfo)^.
  957. Regs[RegInfo.New2OldReg[RegCounter]].NrOfMods;
  958. hp3 := hp2;
  959. For Cnt := 1 to Pred(Cnt2) Do
  960. GetNextInstruction(hp3, hp3);
  961. TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
  962. GetNextInstruction(hp3, hp3);
  963. {$ifdef csdebug}
  964. Writeln('Cnt2: ',Cnt2);
  965. hp5 := new(pai_asm_comment,init(strpnew('starting here...')));
  966. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
  967. {$endif csdebug}
  968. hp3 := hp2;
  969. {first change the contents of the register inside the sequence}
  970. For Cnt := 1 to Cnt2 Do
  971. Begin
  972. {save the WState of the last pai object of the sequence for later use}
  973. TmpState := PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState;
  974. {$ifdef csdebug}
  975. hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '
  976. +tostr(tmpstate))));
  977. InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
  978. {$endif csdebug}
  979. PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
  980. PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
  981. GetNextInstruction(hp3, hp3);
  982. End;
  983. {here, hp3 = p = Pai object right after the sequence, TmpState = WState of
  984. RegCounter at the last Pai object of the sequence}
  985. GetLastInstruction(hp3, hp3);
  986. While GetNextInstruction(hp3, hp3) And
  987. (PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState
  988. = TmpState) Do
  989. {$ifdef csdebug}
  990. begin
  991. hp5 := new(pai_asm_comment,init(strpnew('WState for '+att_reg2str[Regcounter]+': '+
  992. tostr(PPaiProp(hp3^.OptInfo)^.Regs[RegCounter].WState))));
  993. InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
  994. {$endif csdebug}
  995. PPaiProp(hp3^.OptInfo)^.Regs[RegCounter] :=
  996. PPaiProp(hp4^.OptInfo)^.Regs[RegCounter];
  997. {$ifdef csdebug}
  998. end;
  999. {$endif csdebug}
  1000. {$ifdef csdebug}
  1001. hp5 := new(pai_asm_comment,init(strpnew('stopping here...')));
  1002. InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
  1003. {$endif csdebug}
  1004. End;
  1005. End;
  1006. hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
  1007. InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
  1008. If hp1 <> nil Then
  1009. p := hp1;
  1010. Continue;
  1011. End
  1012. Else
  1013. If (Cnt > 0) And
  1014. (PPaiProp(p^.OptInfo)^.
  1015. Regs[Reg32(Paicpu(p)^.oper[1].reg)].Typ = Con_Ref) And
  1016. (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
  1017. Begin
  1018. hp2 := p;
  1019. Cnt2 := 1;
  1020. While Cnt2 <= Cnt Do
  1021. Begin
  1022. If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Then
  1023. PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
  1024. Inc(Cnt2);
  1025. GetNextInstruction(p, p);
  1026. End;
  1027. Continue;
  1028. End;
  1029. End;
  1030. End;
  1031. End;
  1032. {$ifdef replacereg}
  1033. top_Reg:
  1034. { try to replace the new reg with the old reg }
  1035. if not(PPaiProp(p^.optInfo)^.canBeRemoved) and
  1036. { only remove if we're not storing something in a regvar }
  1037. (paicpu(p)^.oper[1].reg in (usableregs+[R_EDI])) and
  1038. (paicpu(p)^.opcode = A_MOV) and
  1039. getLastInstruction(p,hp4) then
  1040. begin
  1041. case paicpu(p)^.oper[1].typ of
  1042. top_Reg:
  1043. { we only have to start replacing from the instruction after the mov, }
  1044. { but replacereg only starts with getnextinstruction(p,p) }
  1045. if ReplaceReg(asmL,paicpu(p)^.oper[0].reg,
  1046. paicpu(p)^.oper[1].reg,p,
  1047. PPaiProp(hp4^.optInfo)^.Regs[paicpu(p)^.oper[1].reg],false,hp1) then
  1048. begin
  1049. PPaiProp(p^.optInfo)^.canBeRemoved := true;
  1050. allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
  1051. PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
  1052. hp1);
  1053. end;
  1054. end
  1055. end;
  1056. {$endif replacereg}
  1057. top_symbol,Top_Const:
  1058. Begin
  1059. Case Paicpu(p)^.oper[1].typ Of
  1060. Top_Reg:
  1061. Begin
  1062. regCounter := Reg32(Paicpu(p)^.oper[1].reg);
  1063. If GetLastInstruction(p, hp1) Then
  1064. With PPaiProp(hp1^.OptInfo)^.Regs[regCounter] Do
  1065. If (Typ = Con_Const) And
  1066. (paicpu(startMod)^.opsize >= paicpu(p)^.opsize) and
  1067. opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
  1068. begin
  1069. PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
  1070. allocRegBetween(asmL,regCounter,startMod,p);
  1071. end;
  1072. End;
  1073. {$ifdef arithopt}
  1074. Top_Ref:
  1075. if (paicpu(p)^.oper[0].typ = top_const) and
  1076. getLastInstruction(p,hp1) and
  1077. findRegWithConst(hp1,paicpu(p)^.opsize,paicpu(p)^.oper[0].val,regCounter) then
  1078. begin
  1079. paicpu(p)^.loadreg(0,regCounter);
  1080. allocRegBetween(AsmL,reg32(regCounter),
  1081. PPaiProp(hp1^.optinfo)^.regs[regCounter].startMod,p);
  1082. end;
  1083. {$endif arithopt}
  1084. End;
  1085. End;
  1086. End;
  1087. End;
  1088. A_STD: If GetLastInstruction(p, hp1) And
  1089. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
  1090. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  1091. End
  1092. End;
  1093. End;
  1094. GetNextInstruction(p, p);
  1095. End;
  1096. End;
  1097. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  1098. { Removes the marked instructions and disposes the PPaiProps of the other }
  1099. { instructions }
  1100. Var p, hp1: Pai;
  1101. begin
  1102. p := First;
  1103. While (p <> Last) Do
  1104. Begin
  1105. If (p^.typ = ait_marker) and
  1106. (pai_marker(p)^.kind in [noPropInfoStart,noPropInfoEnd]) then
  1107. begin
  1108. hp1 := pai(p^.next);
  1109. asmL^.remove(p);
  1110. dispose(p,done);
  1111. p := hp1
  1112. end
  1113. else
  1114. {$ifndef noinstremove}
  1115. if assigned(p^.optInfo) and
  1116. PPaiProp(p^.optInfo)^.canBeRemoved then
  1117. begin
  1118. {$IfDef TP}
  1119. Dispose(PPaiProp(p^.OptInfo));
  1120. {$EndIf}
  1121. hp1 := pai(p^.next);
  1122. AsmL^.Remove(p);
  1123. Dispose(p, Done);
  1124. p := hp1;
  1125. End
  1126. Else
  1127. {$endif noinstremove}
  1128. Begin
  1129. {$IfDef TP}
  1130. if assigned(p^.optInfo) then
  1131. Dispose(PPaiProp(p^.OptInfo));
  1132. {$EndIf TP}
  1133. p^.OptInfo := nil;
  1134. p := pai(p^.next);;
  1135. End;
  1136. End;
  1137. {$IfNDef TP}
  1138. FreeMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4))
  1139. {$EndIf TP}
  1140. End;
  1141. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  1142. Begin
  1143. DoCSE(AsmL, First, Last);
  1144. RemoveInstructs(AsmL, First, Last);
  1145. End;
  1146. End.
  1147. {
  1148. $Log$
  1149. Revision 1.58 2000-04-29 16:57:44 jonas
  1150. * fixed incompatibility with range chcking code, -O2 and higher
  1151. now work correctly together with -Cr
  1152. Revision 1.57 2000/04/10 12:45:57 jonas
  1153. * fixed a serious bug in the CSE which (I think) only showed with
  1154. -dnewoptimizations when using multi-dimensional arrays with
  1155. elements of a size different from 1, 2 or 4 (especially strings).
  1156. * made the DFA/CSE more robust (much less dependent on specifics of the
  1157. code generator)
  1158. Revision 1.56 2000/03/25 19:05:47 jonas
  1159. * fixed some things for -Or. Make cycle now works with -OG2p3r if
  1160. you use -Aas. There still a bug in popt386.pas that causes a
  1161. problem with the binary writer, but I haven't found it yet
  1162. Revision 1.55 2000/03/24 15:54:49 jonas
  1163. * fix for -dnewoptimizations and -Or (never remove stores to regvars)
  1164. but make cycle with -OG2p3r still fails :(
  1165. Revision 1.54 2000/02/24 18:41:38 peter
  1166. * removed warnings/notes
  1167. Revision 1.53 2000/02/19 13:50:29 jonas
  1168. * fixed bug in -dnewoptizations (showed itself only if -Or was
  1169. used as well I think)
  1170. Revision 1.52 2000/02/17 07:46:49 jonas
  1171. * -dreplacereg no logner tries to optimize "movl %reg1,%reg1" (which are
  1172. always marked as CanBeRemoved)
  1173. + some comments in -dreplacereg code
  1174. * small fix which could cause crash when optimizer is compiler with -dTP
  1175. Revision 1.51 2000/02/12 19:28:56 jonas
  1176. * fix for imul optimization in popt386 (exclude top_ref as first
  1177. argument)
  1178. * in csopt386: change "mov reg1,reg2; <several operations on reg2>;
  1179. mov reg2,reg1" to "<several operations on reg1>" (-dnewopt...)
  1180. Revision 1.50 2000/02/12 14:10:14 jonas
  1181. + change "mov reg1,reg2;imul x,reg2" to "imul x,reg1,reg2" in popt386
  1182. (-dnewoptimizations)
  1183. * shl(d) and shr(d) are considered to have a hardcoded register if
  1184. they use cl as shift count (since you can't replace them with
  1185. another register) in csopt386 (also for -dnewoptimizations)
  1186. Revision 1.49 2000/02/12 10:54:18 jonas
  1187. * fixed edi allocation in allocRegBetween
  1188. * fixed bug I introduced yesterday, added comment to prevent it from
  1189. happening again in the future
  1190. Revision 1.48 2000/02/11 23:50:03 jonas
  1191. * fixed crashing bug under Dos with -dnewoptimizations (found it,
  1192. John!). Don't understand why it didn't crash under Linux :(
  1193. Revision 1.47 2000/02/10 16:04:43 jonas
  1194. * fixed stupid typo!
  1195. Revision 1.46 2000/02/10 15:07:41 jonas
  1196. * fixed small bug introduced with my previous fix
  1197. Revision 1.45 2000/02/10 14:57:13 jonas
  1198. * fixed bug due to lack of support for top_symbol operands
  1199. Revision 1.44 2000/02/09 13:22:51 peter
  1200. * log truncated
  1201. Revision 1.43 2000/02/04 13:52:17 jonas
  1202. * better support for regvars (still needs a move of the call to the optimize
  1203. procedure to a place where resetusableregisters is not yet called to work)
  1204. * small regallocation fixes for -dnewoptimizations
  1205. Revision 1.42 2000/01/28 15:15:31 jonas
  1206. * moved skipinstr from daopt386 to aasm
  1207. * fixed crashing bug with -dreplacereg in csopt386.pas
  1208. Revision 1.41 2000/01/23 11:11:37 michael
  1209. + Fixes from Jonas.
  1210. Revision 1.40 2000/01/22 16:10:06 jonas
  1211. + all code generator generated "mov reg1,reg2" instructions are now
  1212. attempted to be removed using the replacereg code
  1213. (-dnewoptimizations)
  1214. * small fixes to -dreplacereg code
  1215. Revision 1.39 2000/01/13 13:07:05 jonas
  1216. * released -dalignreg
  1217. * some small fixes to -dnewOptimizations helper procedures
  1218. Revision 1.38 2000/01/07 01:14:23 peter
  1219. * updated copyright to 2000
  1220. Revision 1.37 2000/01/03 17:11:17 jonas
  1221. * fixed bug with -dreplacereg
  1222. Revision 1.36 1999/12/05 16:48:43 jonas
  1223. * CSE of constant loading in regs works properly again
  1224. + if a constant is stored into memory using "mov const, ref" and
  1225. there is a reg that contains this const, it is changed into
  1226. "mov reg, ref"
  1227. Revision 1.35 1999/12/02 11:26:41 peter
  1228. * newoptimizations define added
  1229. Revision 1.34 1999/11/21 13:09:41 jonas
  1230. * fixed some missed optimizations because 8bit regs were not always
  1231. taken into account
  1232. Revision 1.33 1999/11/20 11:37:03 jonas
  1233. * make cycle works with -dreplacereg (register renaming)! I have not
  1234. tested it yet together with -darithopt, but I don't expect problems
  1235. Revision 1.32 1999/11/14 11:26:53 jonas
  1236. + basic register renaming (not yet working completely, between
  1237. -dreplacereg/-dreplaceregdebug)
  1238. Revision 1.31 1999/11/06 16:21:57 jonas
  1239. + search optimial register to use in alignment code (compile with
  1240. -dalignreg, -dalignregdebug to see chosen register in
  1241. assembler code). Still needs support in ag386bin.
  1242. Revision 1.30 1999/11/06 14:34:20 peter
  1243. * truncated log to 20 revs
  1244. Revision 1.29 1999/11/05 16:01:46 jonas
  1245. + first implementation of choosing least used register for alignment code
  1246. (not yet working, between ifdef alignreg)
  1247. Revision 1.28 1999/10/11 11:11:31 jonas
  1248. * fixed bug which sometimes caused a crash when optimizing blocks of code with
  1249. assembler blocks (didn't notice before because of lack of zero page protection
  1250. under Win9x :( )
  1251. Revision 1.27 1999/10/01 13:51:40 jonas
  1252. * CSE now updates the RegAlloc's
  1253. Revision 1.26 1999/09/30 14:43:13 jonas
  1254. * fixed small efficiency which caused some missed optimizations (saves 1
  1255. assembler instruction on the whole compiler/RTL source tree! :)
  1256. Revision 1.25 1999/09/27 23:44:50 peter
  1257. * procinfo is now a pointer
  1258. * support for result setting in sub procedure
  1259. Revision 1.24 1999/08/25 11:59:58 jonas
  1260. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  1261. }