csopt386.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  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. Interface
  21. Uses aasm;
  22. {Procedure CSOpt386(First, Last: Pai);}
  23. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  24. Implementation
  25. Uses
  26. CObjects, verbose, hcodegen, globals,cpubase,cpuasm,DAOpt386, tgeni386;
  27. {
  28. Function PaiInSequence(P: Pai; Const Seq: TContent): Boolean;
  29. Var P1: Pai;
  30. Counter: Byte;
  31. TmpResult: Boolean;
  32. Begin
  33. TmpResult := False;
  34. P1 := Seq.StartMod;
  35. Counter := 1;
  36. While Not(TmpResult) And
  37. (Counter <= Seq.NrOfMods) Do
  38. Begin
  39. If (P = P1) Then TmpResult := True;
  40. Inc(Counter);
  41. p1 := Pai(p1^.Next);
  42. End;
  43. PaiInSequence := TmpResult;
  44. End;
  45. }
  46. Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint; Var RegInfo: TRegInfo): Boolean;
  47. {checks whether the current instruction sequence (starting with p) and the
  48. one between StartMod and EndMod of Reg are the same. If so, the number of
  49. instructions that match is stored in Found and true is returned, otherwise
  50. Found holds the number of instructions between StartMod and EndMod and false
  51. is returned}
  52. Var hp2, hp3{, EndMod}: Pai;
  53. PrevNonRemovablePai: Pai;
  54. {Cnt,} OldNrOfMods: Longint;
  55. startRegInfo, OrgRegInfo, HighRegInfo: TRegInfo;
  56. HighFound, OrgRegFound: Byte;
  57. RegCounter, regCounter2: TRegister;
  58. OrgRegResult: Boolean;
  59. TmpResult: Boolean;
  60. {TmpState: Byte;}
  61. Begin {CheckSequence}
  62. Reg := Reg32(Reg);
  63. TmpResult := False;
  64. FillChar(OrgRegInfo, SizeOf(OrgRegInfo), 0);
  65. FillChar(startRegInfo, sizeof(startRegInfo), 0);
  66. OrgRegFound := 0;
  67. HighFound := 0;
  68. OrgRegResult := False;
  69. with startRegInfo do
  70. begin
  71. newRegsEncountered := [procinfo^.FramePointer, stack_pointer];
  72. new2OldReg[procinfo^.FramePointer] := procinfo^.FramePointer;
  73. new2OldReg[stack_pointer] := stack_pointer;
  74. oldRegsEncountered := newRegsEncountered;
  75. end;
  76. RegCounter := R_EAX;
  77. GetLastInstruction(p, PrevNonRemovablePai);
  78. While (RegCounter <= R_EDI) And
  79. not(ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ in
  80. [con_ref,con_noRemoveRef]) do
  81. Inc(RegCounter);
  82. While (RegCounter <= R_EDI) Do
  83. Begin
  84. regInfo := startRegInfo;
  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. if (hp3^.typ = ait_instruction) and
  96. ((paicpu(hp3)^.opcode = A_MOV) or
  97. (paicpu(hp3)^.opcode = A_MOVZX) or
  98. (paicpu(hp3)^.opcode = A_MOVSX)) and
  99. (paicpu(hp3)^.oper[0].typ in
  100. [top_const,top_ref,top_symbol]) and
  101. (paicpu(hp3)^.oper[1].typ = top_reg) then
  102. regInfo.lastReload
  103. [reg32(paicpu(hp3)^.oper[1].reg)] := hp3;
  104. GetNextInstruction(hp2, hp2);
  105. GetNextInstruction(hp3, hp3);
  106. Inc(Found)
  107. End;
  108. for regCounter2 := R_EAX to R_EDX do
  109. if (regInfo.new2OldReg[regCounter2] <> R_NO) and
  110. (reg in PPaiProp(hp3^.optInfo)^.usedRegs) and
  111. not regLoadedWithNewValue(reg,false,hp3) then
  112. include(regInfo.regsStillUsedAfterSeq,regCounter);
  113. If (Found <> OldNrOfMods) or
  114. { the following is to avoid problems with rangecheck code (see testcse2) }
  115. (assigned(hp3) and
  116. ((reg in regInfo.regsLoadedForRef) and
  117. (reg in PPaiProp(hp3^.optInfo)^.usedRegs) and
  118. not regLoadedWithNewValue(reg,false,hp3))) then
  119. Begin
  120. TmpResult := False;
  121. If (found > 0) then
  122. {this is correct because we only need to turn off the CanBeRemoved flag
  123. when an instruction has already been processed by CheckSequence
  124. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  125. If it has already been processed by CheckSequence and flagged to be
  126. removed, it means that it has been checked against a previous sequence
  127. and that it was equal (otherwise CheckSequence would have returned false
  128. and the instruction wouldn't have been removed). If this "If found > 0"
  129. check is left out, incorrect optimizations are performed.}
  130. Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
  131. End
  132. Else TmpResult := True;
  133. If TmpResult And
  134. (Found > HighFound)
  135. Then
  136. Begin
  137. HighFound := Found;
  138. HighRegInfo := RegInfo;
  139. End;
  140. If (RegCounter = Reg) Then
  141. Begin
  142. OrgRegFound := Found;
  143. OrgRegResult := TmpResult;
  144. OrgRegInfo := RegInfo
  145. End;
  146. Repeat
  147. Inc(RegCounter);
  148. Until (RegCounter > R_EDI) or
  149. ((ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ
  150. in [con_ref,con_noRemoveRef]) {And
  151. ((Regcounter = Reg) Or
  152. Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
  153. );
  154. End;
  155. If (HighFound > 0) And
  156. (Not(OrgRegResult) Or
  157. (HighFound > OrgRegFound))
  158. Then
  159. Begin
  160. {$ifndef fpc}
  161. TmpResult := True;
  162. {$else fpc}
  163. CheckSequence := True;
  164. {$endif fpc}
  165. RegInfo := HighRegInfo;
  166. Found := HighFound
  167. End
  168. Else
  169. Begin
  170. {$ifndef fpc}
  171. TmpResult := OrgRegResult;
  172. {$else fpc}
  173. CheckSequence := OrgRegResult;
  174. {$endif fpc}
  175. Found := OrgRegFound;
  176. RegInfo := OrgRegInfo;
  177. End;
  178. {$ifndef fpc}
  179. CheckSequence := TmpResult;
  180. {$endif fpc}
  181. End; {CheckSequence}
  182. Procedure SetAlignReg(p: Pai);
  183. Const alignSearch = 12;
  184. var regsUsable: TRegSet;
  185. prevInstrCount, nextInstrCount: Longint;
  186. prevState, nextWState,nextRState: Array[R_EAX..R_EDI] of byte;
  187. regCounter, lastRemoved: TRegister;
  188. prev, next: Pai;
  189. {$ifdef alignregdebug}
  190. temp: Pai;
  191. {$endif alignregdebug}
  192. begin
  193. regsUsable := [R_EAX,R_ECX,R_EDX,R_EBX,{R_ESP,R_EBP,}R_ESI,R_EDI];
  194. for regCounter := R_EAX to R_EDI do
  195. begin
  196. prevState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  197. nextWState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].wState;
  198. nextRState[regCounter] := PPaiProp(p^.optInfo)^.Regs[regCounter].rState;
  199. end;
  200. getLastInstruction(p,prev);
  201. getNextInstruction(p,next);
  202. lastRemoved := pai_align(p)^.reg;
  203. nextInstrCount := 0;
  204. prevInstrCount := 0;
  205. while ((assigned(prev) and
  206. assigned(prev^.optInfo) and
  207. (prevInstrCount < alignSearch)) or
  208. (assigned(next) and
  209. assigned(next^.optInfo) and
  210. (nextInstrCount < alignSearch))) And
  211. (regsUsable <> []) do
  212. begin
  213. {$ifdef alignregdebug}
  214. if assigned(prev) then
  215. begin
  216. temp := new(pai_asm_comment,init(strpnew('got here')));
  217. temp^.next := prev^.next;
  218. temp^.previous := prev;
  219. prev^.next := temp;
  220. if assigned(temp^.next) then
  221. temp^.next^.previous := temp;
  222. end;
  223. {$endif alignregdebug}
  224. if assigned(prev) and assigned(prev^.optinfo) and
  225. (prevInstrCount < alignSearch) then
  226. begin
  227. if (prev^.typ = ait_instruction) And
  228. (insProp[PaiCpu(prev)^.opcode].ch[1] <> Ch_ALL) and
  229. (PaiCpu(prev)^.opcode <> A_JMP) then
  230. begin
  231. inc(prevInstrCount);
  232. for regCounter := R_EAX to R_EDI do
  233. begin
  234. if (regCounter in regsUsable) And
  235. (PPaiProp(prev^.optInfo)^.Regs[regCounter].wState <>
  236. prevState[regCounter]) then
  237. begin
  238. lastRemoved := regCounter;
  239. exclude(regsUsable,regCounter);
  240. {$ifdef alignregdebug}
  241. temp := new(pai_asm_comment,init(strpnew(
  242. att_reg2str[regCounter]+' removed')));
  243. temp^.next := prev^.next;
  244. temp^.previous := prev;
  245. prev^.next := temp;
  246. if assigned(temp^.next) then
  247. temp^.next^.previous := temp;
  248. if regsUsable = [] then
  249. begin
  250. temp := new(pai_asm_comment,init(strpnew(
  251. 'regsUsable empty here')));
  252. temp^.next := prev^.next;
  253. temp^.previous := prev;
  254. prev^.next := temp;
  255. if assigned(temp^.next) then
  256. temp^.next^.previous := temp;
  257. end;
  258. {$endif alignregdebug}
  259. end;
  260. prevState[regCounter] :=
  261. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState;
  262. end;
  263. getLastInstruction(prev,prev);
  264. end
  265. else
  266. If GetLastInstruction(prev,prev) and
  267. assigned(prev^.optinfo) then
  268. for regCounter := R_EAX to R_EDI do
  269. prevState[regCounter] :=
  270. PPaiProp(prev^.optInfo)^.Regs[regCounter].wState
  271. end;
  272. if assigned(next) and assigned(next^.optInfo) and
  273. (nextInstrCount < alignSearch) then
  274. begin
  275. if (next^.typ = ait_instruction) and
  276. (insProp[PaiCpu(next)^.opcode].ch[1] <> Ch_ALL) and
  277. (PaiCpu(next)^.opcode <> A_JMP) then
  278. begin
  279. inc(nextInstrCount);
  280. for regCounter := R_EAX to R_EDI do
  281. begin
  282. if (regCounter in regsUsable) And
  283. ((PPaiProp(next^.optInfo)^.Regs[regCounter].wState <>
  284. nextWState[regCounter]) or
  285. (PPaiProp(next^.optInfo)^.Regs[regCounter].rState <>
  286. nextRState[regCounter])) Then
  287. begin
  288. lastRemoved := regCounter;
  289. exclude(regsUsable,regCounter);
  290. {$ifdef alignregdebug}
  291. temp := new(pai_asm_comment,init(strpnew(
  292. att_reg2str[regCounter]+' removed')));
  293. temp^.next := next^.next;
  294. temp^.previous := next;
  295. next^.next := temp;
  296. if assigned(temp^.next) then
  297. temp^.next^.previous := temp;
  298. if regsUsable = [] then
  299. begin
  300. temp := new(pai_asm_comment,init(strpnew(
  301. 'regsUsable empty here')));
  302. temp^.next := next^.next;
  303. temp^.previous := next;
  304. next^.next := temp;
  305. if assigned(temp^.next) then
  306. temp^.next^.previous := temp;
  307. end;
  308. {$endif alignregdebug}
  309. end;
  310. nextWState[regCounter] :=
  311. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  312. nextRState[regCounter] :=
  313. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  314. end
  315. end
  316. else
  317. for regCounter := R_EAX to R_EDI do
  318. begin
  319. nextWState[regCounter] :=
  320. PPaiProp(next^.optInfo)^.Regs[regCounter].wState;
  321. nextRState[regCounter] :=
  322. PPaiProp(next^.optInfo)^.Regs[regCounter].rState;
  323. end;
  324. getNextInstruction(next,next);
  325. end;
  326. end;
  327. if regsUsable <> [] then
  328. for regCounter := R_EAX to R_EDI do
  329. if regCounter in regsUsable then
  330. begin
  331. lastRemoved := regCounter;
  332. break
  333. end;
  334. {$ifdef alignregdebug}
  335. next := new(pai_asm_comment,init(strpnew(att_reg2str[lastRemoved]+
  336. ' chosen as alignment register')));
  337. next^.next := p^.next;
  338. next^.previous := p;
  339. p^.next := next;
  340. if assigned(next^.next) then
  341. next^.next^.previous := next;
  342. {$endif alignregdebug}
  343. pai_align(p)^.reg := lastRemoved;
  344. End;
  345. Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p, endP: pai);
  346. var
  347. {$ifdef replaceregdebug}
  348. hp: pai;
  349. {$endif replaceregdebug}
  350. tmpState: byte;
  351. begin
  352. {$ifdef replaceregdebug}
  353. hp := new(pai_asm_comment,init(strpnew(
  354. 'restored '+att_reg2str[reg]+' with data from here...')));
  355. hp^.next := p;
  356. hp^.previous := p^.previous;
  357. p^.previous := hp;
  358. if assigned(hp^.previous) then
  359. hp^.previous^.next := hp;
  360. {$endif replaceregdebug}
  361. { PPaiProp(p^.optInfo)^.Regs[reg] := c;}
  362. While (p <> endP) Do
  363. Begin
  364. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  365. getNextInstruction(p,p);
  366. end;
  367. tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
  368. repeat
  369. PPaiProp(p^.optInfo)^.Regs[reg] := c;
  370. until not getNextInstruction(p,p) or
  371. (PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
  372. {$ifdef replaceregdebug}
  373. if assigned(p) then
  374. begin
  375. hp := new(pai_asm_comment,init(strpnew(
  376. 'restored '+att_reg2str[reg]+' till here...')));
  377. hp^.next := p;
  378. hp^.previous := p^.previous;
  379. p^.previous := hp;
  380. if assigned(hp^.previous) then
  381. hp^.previous^.next := hp;
  382. end;
  383. {$endif replaceregdebug}
  384. end;
  385. function FindRegDealloc(reg: tregister; p: pai): boolean;
  386. { assumes reg is a 32bit register }
  387. var
  388. hp: pai;
  389. first: boolean;
  390. begin
  391. findregdealloc := false;
  392. first := true;
  393. while assigned(p^.previous) and
  394. ((Pai(p^.previous)^.typ in (skipinstr+[ait_align])) or
  395. ((Pai(p^.previous)^.typ = ait_label) and
  396. labelCanBeSkipped(pai_label(p^.previous)))) do
  397. begin
  398. p := pai(p^.previous);
  399. if (p^.typ = ait_regalloc) and
  400. (pairegalloc(p)^.reg = reg) then
  401. if not(pairegalloc(p)^.allocation) then
  402. if first then
  403. begin
  404. findregdealloc := true;
  405. break;
  406. end
  407. else
  408. begin
  409. findRegDealloc :=
  410. getNextInstruction(p,hp) and
  411. regLoadedWithNewValue(reg,false,hp);
  412. break
  413. end
  414. else
  415. first := false;
  416. end
  417. end;
  418. Procedure ClearRegContentsFrom(reg: TRegister; p, endP: pai);
  419. { first clears the contents of reg from p till endP. Then the contents are }
  420. { cleared until the first instruction that changes reg }
  421. var
  422. {$ifdef replaceregdebug}
  423. hp: pai;
  424. {$endif replaceregdebug}
  425. tmpState: byte;
  426. begin
  427. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  428. While (p <> endP) Do
  429. Begin
  430. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  431. getNextInstruction(p,p);
  432. end;
  433. tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
  434. repeat
  435. PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
  436. until not getNextInstruction(p,p) or
  437. (PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
  438. {$ifdef replaceregdebug}
  439. if assigned(p) then
  440. begin
  441. hp := new(pai_asm_comment,init(strpnew(
  442. 'cleared '+att_reg2str[reg]+' till here...')));
  443. hp^.next := p;
  444. hp^.previous := p^.previous;
  445. p^.previous := hp;
  446. if assigned(hp^.previous) then
  447. hp^.previous^.next := hp;
  448. end;
  449. {$endif replaceregdebug}
  450. end;
  451. function NoHardCodedRegs(p: paicpu; orgReg, newReg: tRegister): boolean;
  452. var chCount: byte;
  453. begin
  454. case p^.opcode of
  455. A_IMUL: noHardCodedRegs := p^.ops <> 1;
  456. A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
  457. (p^.oper[0].typ <> top_reg) or
  458. ((orgReg <> R_ECX) and (newReg <> R_ECX));
  459. else
  460. begin
  461. NoHardCodedRegs := true;
  462. with InsProp[p^.opcode] do
  463. for chCount := 1 to MaxCh do
  464. if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
  465. begin
  466. NoHardCodedRegs := false;
  467. break
  468. end;
  469. end;
  470. end;
  471. end;
  472. Procedure ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister);
  473. begin
  474. if reg = newReg then
  475. reg := orgReg
  476. else if reg = regtoreg8(newReg) then
  477. reg := regtoreg8(orgReg)
  478. else if reg = regtoreg16(newReg) then
  479. reg := regtoreg16(orgReg);
  480. end;
  481. procedure changeOp(var o: toper; orgReg, newReg: tregister);
  482. begin
  483. case o.typ of
  484. top_reg: changeReg(o.reg,orgReg,newReg);
  485. top_ref:
  486. begin
  487. changeReg(o.ref^.base,orgReg,newReg);
  488. changeReg(o.ref^.index,orgReg,newReg);
  489. end;
  490. end;
  491. end;
  492. Procedure DoReplaceReg(orgReg,newReg: tregister; hp: paicpu);
  493. var opCount: byte;
  494. begin
  495. for opCount := 0 to 2 do
  496. changeOp(hp^.oper[opCount],orgReg,newReg)
  497. end;
  498. function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
  499. { oldreg and newreg must be 32bit components }
  500. var opCount: byte;
  501. begin
  502. RegSizesOK := true;
  503. { if only one of them is a general purpose register ... }
  504. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  505. begin
  506. for opCount := 0 to 2 do
  507. if (p^.oper[opCount].typ = top_reg) and
  508. (p^.oper[opCount].reg in [R_AL..R_DH]) then
  509. begin
  510. RegSizesOK := false;
  511. break
  512. end
  513. end;
  514. end;
  515. procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
  516. var opCount: byte;
  517. begin
  518. { handle special case }
  519. case p^.opcode of
  520. A_IMUL:
  521. begin
  522. case p^.ops of
  523. 1: internalerror(1301001);
  524. 2,3:
  525. begin
  526. changeOp(p^.oper[0],orgReg,newReg);
  527. if p^.ops = 3 then
  528. changeOp(p^.oper[1],orgReg,newReg);
  529. end;
  530. end;
  531. end;
  532. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  533. else
  534. begin
  535. for opCount := 0 to 2 do
  536. if p^.oper[opCount].typ = top_ref then
  537. changeOp(p^.oper[opCount],orgReg,newReg);
  538. for opCount := 1 to MaxCh do
  539. case InsProp[p^.opcode].Ch[opCount] of
  540. Ch_ROp1:
  541. if p^.oper[0].typ = top_reg then
  542. ChangeReg(p^.oper[0].reg,orgReg,newReg);
  543. Ch_ROp2:
  544. if p^.oper[1].typ = top_reg then
  545. ChangeReg(p^.oper[1].reg,orgReg,newReg);
  546. Ch_ROp3:
  547. if p^.oper[2].typ = top_reg then
  548. ChangeReg(p^.oper[2].reg,orgReg,newReg);
  549. end;
  550. end;
  551. end;
  552. end;
  553. function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
  554. const c: TContent; orgRegCanBeModified: Boolean;
  555. var returnEndP: pai): Boolean;
  556. { Tries to replace orgreg with newreg in all instructions coming after p }
  557. { until orgreg gets loaded with a new value. Returns true if successful, }
  558. { false otherwise. If successful, the contents of newReg are set to c, }
  559. { which should hold the contents of newReg before the current sequence }
  560. { started }
  561. { if the function returns true, returnEndP holds the last instruction }
  562. { where newReg was replaced by orgReg }
  563. var endP, hp: Pai;
  564. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: Boolean;
  565. function storeBack(p1: pai): boolean;
  566. { returns true if p1 contains an instruction that stores the contents }
  567. { of newReg back to orgReg }
  568. begin
  569. storeBack :=
  570. (p1^.typ = ait_instruction) and
  571. (paicpu(p1)^.opcode = A_MOV) and
  572. (paicpu(p1)^.oper[0].typ = top_reg) and
  573. (paicpu(p1)^.oper[0].reg = newReg) and
  574. (paicpu(p1)^.oper[1].typ = top_reg) and
  575. (paicpu(p1)^.oper[1].reg = orgReg);
  576. end;
  577. begin
  578. ReplaceReg := false;
  579. tmpResult := true;
  580. sequenceEnd := false;
  581. newRegModified := false;
  582. orgRegRead := false;
  583. removeLast := false;
  584. endP := p;
  585. while tmpResult and not sequenceEnd do
  586. begin
  587. tmpResult :=
  588. getNextInstruction(endP,endP) and
  589. (endP^.typ = ait_instruction);
  590. if tmpresult and not assigned(endP^.optInfo) then
  591. begin
  592. { hp := new(pai_asm_comment,init(strpnew('next no optinfo')));
  593. hp^.next := endp;
  594. hp^.previous := endp^.previous;
  595. endp^.previous := hp;
  596. if assigned(hp^.previous) then
  597. hp^.previous^.next := hp;}
  598. exit;
  599. end;
  600. If tmpResult and
  601. { don't take into account instructions that will be removed }
  602. Not (PPaiProp(endP^.optInfo)^.canBeRemoved) then
  603. begin
  604. { if the newReg gets stored back to the oldReg, we can change }
  605. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  606. { %oldReg" to "<operations on %oldReg>" }
  607. removeLast := storeBack(endP);
  608. sequenceEnd :=
  609. { no support for (i)div, mul and imul with hardcoded operands }
  610. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  611. { if newReg gets loaded with a new value, we can stop }
  612. { replacing newReg with oldReg here (possibly keeping }
  613. { the original contents of oldReg so we still know them }
  614. { afterwards) }
  615. RegLoadedWithNewValue(newReg,true,paicpu(endP)) or
  616. { we can also stop if we reached the end of the use of }
  617. { newReg's current contents }
  618. (GetNextInstruction(endp,hp) and
  619. FindRegDealloc(newReg,hp)));
  620. { to be able to remove the first and last instruction of }
  621. { movl %reg1, %reg2 }
  622. { <operations on %reg2> (replacing reg2 with reg1 here) }
  623. { movl %reg2, %reg1 }
  624. { %reg2 must not be use afterwards (it can be as the }
  625. { result of a peepholeoptimization) }
  626. removeLast := removeLast and sequenceEnd;
  627. newRegModified :=
  628. newRegModified or
  629. (not(regLoadedWithNewValue(newReg,true,paicpu(endP))) and
  630. RegModifiedByInstruction(newReg,endP));
  631. orgRegRead := newRegModified and RegReadByInstruction(orgReg,endP);
  632. sequenceEnd := SequenceEnd and
  633. (removeLast or
  634. { since newReg will be replaced by orgReg, we can't allow that newReg }
  635. { gets modified if orgReg is still read afterwards (since after }
  636. { replacing, this would mean that orgReg first gets modified and then }
  637. { gets read in the assumption it still contains the unmodified value) }
  638. not(newRegModified and orgRegRead)) (* and
  639. { since newReg will be replaced by orgReg, we can't allow that newReg }
  640. { gets modified if orgRegCanBeModified = false }
  641. (orgRegCanBeModified or not(newRegModified)) *);
  642. tmpResult :=
  643. not(removeLast) and
  644. not(newRegModified and orgRegRead) and
  645. (* (orgRegCanBeModified or not(newRegModified)) and *)
  646. (endP^.typ = ait_instruction) and
  647. not(paicpu(endP)^.is_jmp) and
  648. NoHardCodedRegs(paicpu(endP),orgReg,newReg) and
  649. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  650. not RegModifiedByInstruction(orgReg,endP);
  651. end;
  652. end;
  653. sequenceEnd := sequenceEnd and
  654. (removeLast or
  655. (orgRegCanBeModified or not(newRegModified))) and
  656. (not(assigned(endp)) or
  657. not(endp^.typ = ait_instruction) or
  658. (noHardCodedRegs(paicpu(endP),orgReg,newReg) and
  659. RegSizesOk(orgReg,newReg,paicpu(endP)) and
  660. not(newRegModified and
  661. (orgReg in PPaiProp(endP^.optInfo)^.usedRegs) and
  662. not(RegLoadedWithNewValue(orgReg,true,paicpu(endP))))));
  663. if SequenceEnd then
  664. begin
  665. {$ifdef replaceregdebug}
  666. hp := new(pai_asm_comment,init(strpnew(
  667. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  668. ' from here...')));
  669. hp^.next := p;
  670. hp^.previous := p^.previous;
  671. p^.previous := hp;
  672. if assigned(hp^.previous) then
  673. hp^.previous^.next := hp;
  674. hp := new(pai_asm_comment,init(strpnew(
  675. 'replaced '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  676. ' till here')));
  677. hp^.next := endp^.next;
  678. hp^.previous := endp;
  679. endp^.next := hp;
  680. if assigned(hp^.next) then
  681. hp^.next^.previous := hp;
  682. {$endif replaceregdebug}
  683. replaceReg := true;
  684. returnEndP := endP;
  685. getNextInstruction(p,hp);
  686. while hp <> endP do
  687. begin
  688. if not(PPaiProp(hp^.optInfo)^.canBeRemoved) and
  689. (hp^.typ = ait_instruction) then
  690. DoReplaceReg(orgReg,newReg,paicpu(hp));
  691. GetNextInstruction(hp,hp)
  692. end;
  693. if assigned(endp) and (endp^.typ = ait_instruction) then
  694. DoReplaceReadReg(orgReg,newReg,paicpu(endP));
  695. { the replacing stops either at the moment that }
  696. { a) the newreg gets loaded with a new value (one not depending on the }
  697. { current value of newreg) }
  698. { b) newreg is completely replaced in this sequence and it's current value }
  699. { isn't used anymore }
  700. { In case b, the newreg was completely replaced by oldreg, so it's contents }
  701. { are unchanged compared the start of this sequence, so restore them }
  702. If removeLast or
  703. RegLoadedWithNewValue(newReg,true,endP) then
  704. GetLastInstruction(endP,hp)
  705. else hp := endP;
  706. if removeLast or
  707. (p <> endp) or
  708. not RegLoadedWithNewValue(newReg,true,endP) then
  709. RestoreRegContentsTo(newReg, c ,p, hp);
  710. { In both case a and b, it is possible that the new register was modified }
  711. { (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
  712. { oldreg's contents have been changed. To take this into account, we simply }
  713. { set the contents of orgreg to "unknown" after this sequence }
  714. if newRegModified then
  715. ClearRegContentsFrom(orgReg,p,hp);
  716. if removeLast then
  717. ppaiprop(endP^.optinfo)^.canBeRemoved := true;
  718. allocRegBetween(asml,orgReg,p,endP);
  719. end
  720. {$ifdef replaceregdebug}
  721. else
  722. begin
  723. hp := new(pai_asm_comment,init(strpnew(
  724. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  725. ' from here...')));
  726. hp^.previous := p^.previous;
  727. hp^.next := p;
  728. p^.previous := hp;
  729. if assigned(hp^.previous) then
  730. hp^.previous^.next := hp;
  731. hp := new(pai_asm_comment,init(strpnew(
  732. 'replacing '+att_reg2str[newreg]+' with '+att_reg2str[orgreg]+
  733. ' failed here')));
  734. hp^.next := endp^.next;
  735. hp^.previous := endp;
  736. endp^.next := hp;
  737. if assigned(hp^.next) then
  738. hp^.next^.previous := hp;
  739. end;
  740. {$endif replaceregdebug}
  741. End;
  742. Function FindRegWithConst(p: Pai; size: topsize; l: longint; Var Res: TRegister): Boolean;
  743. {Finds a register which contains the constant l}
  744. Var Counter: TRegister;
  745. {$ifdef testing}
  746. hp: pai;
  747. {$endif testing}
  748. tmpresult: boolean;
  749. Begin
  750. Counter := R_NO;
  751. repeat
  752. inc(counter);
  753. tmpresult := (ppaiprop(p^.optInfo)^.regs[counter].typ in
  754. [con_const,con_noRemoveConst]) and
  755. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.opsize = size) and
  756. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].typ = top_const) and
  757. (paicpu(PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod)^.oper[0].val = l);
  758. {$ifdef testing}
  759. if (ppaiprop(p^.optInfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  760. begin
  761. hp := new(pai_asm_comment,init(strpnew(
  762. 'checking const load of '+tostr(l)+' here...')));
  763. hp^.next := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod;
  764. hp^.previous := PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous;
  765. PPaiProp(p^.OptInfo)^.Regs[Counter].StartMod^.previous := hp;
  766. if assigned(hp^.previous) then
  767. hp^.previous^.next := hp;
  768. end;
  769. {$endif testing}
  770. until tmpresult or (Counter = R_EDI);
  771. res := counter;
  772. FindRegWithConst := tmpResult;
  773. End;
  774. procedure removePrevNotUsedLoad(p: pai; reg: tRegister; check: boolean);
  775. { If check = true, it means the procedure has to check whether it isn't }
  776. { possible that the contents are still used after p (used when removing }
  777. { instructions because of a "call"), otherwise this is not necessary }
  778. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  779. { value of %eax isn't used anymore later on) }
  780. var
  781. hp1: pai;
  782. begin
  783. if getLastInstruction(p,hp1) then
  784. with ppaiprop(hp1^.optInfo)^.regs[reg] do
  785. if (typ in [con_ref,con_invalid]) and
  786. (nrOfMods = 1) and
  787. (rState = ppaiprop(startmod^.optInfo)^.regs[reg].rState) and
  788. (not(check) or
  789. (not(regInInstruction(reg,p)) and
  790. (not(reg in usableregs) and
  791. (startmod^.typ = ait_instruction) and
  792. ((paicpu(startmod)^.opcode = A_MOV) or
  793. (paicpu(startmod)^.opcode = A_MOVZX) or
  794. (paicpu(startmod)^.opcode = A_MOVSX)) and
  795. (paicpu(startmod)^.oper[0].typ = top_ref) and
  796. (paicpu(startmod)^.oper[0].ref^.base = stack_pointer)) or
  797. not(reg in ppaiprop(hp1^.optInfo)^.usedRegs) or
  798. findRegDealloc(reg,p))) then
  799. ppaiprop(startMod^.optInfo)^.canBeRemoved := true;
  800. end;
  801. Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
  802. {marks the instructions that can be removed by RemoveInstructs. They're not
  803. removed immediately because sometimes an instruction needs to be checked in
  804. two different sequences}
  805. var cnt, cnt2, cnt3: longint;
  806. p, hp1, hp2: Pai;
  807. hp3, hp4: pai;
  808. hp5 : pai;
  809. RegInfo: TRegInfo;
  810. RegCounter: TRegister;
  811. Begin
  812. p := First;
  813. SkipHead(p);
  814. First := p;
  815. While (p <> Last) Do
  816. Begin
  817. Case p^.typ Of
  818. ait_align:
  819. if not(pai_align(p)^.use_op) then
  820. SetAlignReg(p);
  821. ait_instruction:
  822. Begin
  823. Case Paicpu(p)^.opcode Of
  824. A_CALL:
  825. for regCounter := R_EAX to R_EBX do
  826. removePrevNotUsedLoad(p,regCounter,true);
  827. A_CLD: If GetLastInstruction(p, hp1) And
  828. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
  829. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  830. A_MOV, A_MOVZX, A_MOVSX:
  831. Begin
  832. Case Paicpu(p)^.oper[0].typ Of
  833. Top_Ref:
  834. Begin {destination is always a register in this case}
  835. With PPaiProp(p^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)] Do
  836. Begin
  837. If (p = StartMod) And
  838. GetLastInstruction (p, hp1) And
  839. (hp1^.typ <> ait_marker) Then
  840. {so we don't try to check a sequence when p is the first instruction of the block}
  841. begin
  842. {$ifdef csdebug}
  843. hp5 := new(pai_asm_comment,init(strpnew(
  844. 'cse checking '+att_reg2str[Reg32(Paicpu(p)^.oper[1].reg)])));
  845. insertLLItem(asml,p,p^.next,hp5);
  846. {$endif csdebug}
  847. If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
  848. (Cnt > 0) Then
  849. Begin
  850. hp1 := nil;
  851. { although it's perfectly ok to remove an instruction which doesn't contain }
  852. { the register that we've just checked (CheckSequence takes care of that), }
  853. { the sequence containing this other register should also be completely }
  854. { checked and removed, otherwise we may get situations like this: }
  855. { }
  856. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  857. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  858. { movl 8(%edx), %edx movl 8(%edx), %edx }
  859. { movl (%eax), eax movl (%eax), eax }
  860. { cmpl %eax, %edx cmpl %eax, %edx }
  861. { jnz l123 getting converted to jnz l123 }
  862. { movl 12(%ebp), %edx movl 4(%eax), eax }
  863. { movl 16(%ebp), %eax }
  864. { movl 8(%edx), %edx }
  865. { movl 4(%eax), eax }
  866. hp2 := p;
  867. Cnt2 := 1;
  868. While Cnt2 <= Cnt Do
  869. Begin
  870. If Not(RegInInstruction(Paicpu(hp2)^.oper[1].reg, p)) then
  871. begin
  872. if ((p^.typ = ait_instruction) And
  873. ((paicpu(p)^.OpCode = A_MOV) or
  874. (paicpu(p)^.opcode = A_MOVZX) or
  875. (paicpu(p)^.opcode = A_MOVSX)) And
  876. (paicpu(p)^.Oper[0].typ in
  877. [top_const,top_ref,top_symbol])) and
  878. (paicpu(p)^.oper[1].typ = top_reg) then
  879. begin
  880. regCounter := reg32(paicpu(p)^.oper[1].reg);
  881. if (regCounter in reginfo.regsStillUsedAfterSeq) then
  882. begin
  883. if (hp1 = nil) then
  884. hp1 := reginfo.lastReload[regCounter];
  885. end
  886. {$ifndef noremove}
  887. else
  888. begin
  889. hp5 := p;
  890. for cnt3 := ppaiprop(p^.optinfo)^.regs[regCounter].nrofmods downto 1 do
  891. begin
  892. if regModifiedByInstruction(regCounter,hp5) then
  893. PPaiProp(hp5^.OptInfo)^.CanBeRemoved := True;
  894. getNextInstruction(hp5,hp5);
  895. end;
  896. {$endif noremove} end
  897. end
  898. end
  899. {$ifndef noremove}
  900. else
  901. PPaiProp(p^.OptInfo)^.CanBeRemoved := True
  902. {$endif noremove}
  903. ; Inc(Cnt2);
  904. GetNextInstruction(p, p);
  905. End;
  906. hp3 := New(Pai_Marker,Init(NoPropInfoStart));
  907. InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
  908. {hp4 is used to get the contents of the registers before the sequence}
  909. GetLastInstruction(hp2, hp4);
  910. {$IfDef CSDebug}
  911. For RegCounter := R_EAX To R_EDI Do
  912. If (RegCounter in RegInfo.RegsLoadedForRef) Then
  913. Begin
  914. hp5 := new(pai_asm_comment,init(strpnew('New: '+att_reg2str[RegCounter]+', Old: '+
  915. att_reg2str[RegInfo.New2OldReg[RegCounter]])));
  916. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp5);
  917. End;
  918. {$EndIf CSDebug}
  919. { If some registers were different in the old and the new sequence, move }
  920. { the contents of those old registers to the new ones }
  921. For RegCounter := R_EAX To R_EDI Do
  922. If Not(RegCounter in [R_ESP,procinfo^.framepointer]) And
  923. (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
  924. Begin
  925. AllocRegBetween(AsmL,RegInfo.New2OldReg[RegCounter],
  926. PPaiProp(hp4^.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,hp2);
  927. If Not(RegCounter In RegInfo.RegsLoadedForRef) And
  928. {old reg new reg}
  929. (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
  930. Begin
  931. getLastInstruction(p,hp3);
  932. If not(regCounter in usableRegs + [R_EDI,R_ESI]) or
  933. not ReplaceReg(asmL,RegInfo.New2OldReg[RegCounter],
  934. regCounter,hp3,
  935. PPaiProp(hp4^.optInfo)^.Regs[regCounter],true,hp5) then
  936. begin
  937. hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
  938. {old reg new reg}
  939. RegInfo.New2OldReg[RegCounter], RegCounter));
  940. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
  941. end
  942. End
  943. Else
  944. { imagine the following code: }
  945. { normal wrong optimized }
  946. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  947. { movl (%eax), %eax movl (%eax), %eax }
  948. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  949. { jne l1 jne l1 }
  950. { movl 8(%ebp), %eax }
  951. { movl (%eax), %edi movl %eax, %edi }
  952. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  953. { movl 8(%ebp), %eax }
  954. { pushl 70(%eax) pushl 70(%eax) }
  955. { }
  956. { The error is that at the moment that the last instruction is executed, }
  957. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  958. { registers that are completely removed from a sequence (= registers in }
  959. { RegLoadedForRef, have to be changed to their contents from before the }
  960. { sequence. }
  961. If RegCounter in RegInfo.RegsLoadedForRef Then
  962. Begin
  963. hp3 := hp2;
  964. { cnt still holds the number of instructions }
  965. { of the sequence, so go to the end of it }
  966. for cnt2 := 1 to pred(cnt) Do
  967. getNextInstruction(hp3,hp3);
  968. { hp4 = instruction prior to start of sequence }
  969. restoreRegContentsTo(regCounter,
  970. PPaiProp(hp4^.OptInfo)^.Regs[RegCounter],
  971. hp2,hp3);
  972. End;
  973. End;
  974. hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
  975. InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
  976. If hp1 <> nil Then
  977. p := hp1;
  978. Continue;
  979. End
  980. Else
  981. If (PPaiProp(p^.OptInfo)^.
  982. regs[reg32(paicpu(p)^.oper[1].reg)].typ
  983. in [con_ref,con_noRemoveRef]) and
  984. (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
  985. if (cnt > 0) then
  986. begin
  987. hp2 := p;
  988. Cnt2 := 1;
  989. While Cnt2 <= Cnt Do
  990. Begin
  991. If RegInInstruction(Paicpu(hp2)^.oper[1].reg, p) Then
  992. PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
  993. Inc(Cnt2);
  994. GetNextInstruction(p, p);
  995. End;
  996. Continue;
  997. End
  998. else
  999. begin
  1000. { Fix for web bug 972 }
  1001. regCounter := Reg32(Paicpu(p)^.oper[1].reg);
  1002. cnt := PPaiProp(p^.optInfo)^.Regs[regCounter].nrOfMods;
  1003. hp3 := p;
  1004. for cnt2 := 1 to cnt do
  1005. if not(regModifiedByInstruction(regCounter,hp3) and
  1006. not(PPaiProp(hp3^.optInfo)^.canBeRemoved)) then
  1007. getNextInstruction(hp3,hp3)
  1008. else
  1009. break;
  1010. getLastInstruction(p,hp4);
  1011. RestoreRegContentsTo(regCounter,
  1012. PPaiProp(hp4^.optInfo)^.Regs[regCounter],
  1013. p,hp3);
  1014. end;
  1015. End;
  1016. End;
  1017. if not ppaiprop(p^.optinfo)^.canBeRemoved and
  1018. not regInRef(reg32(paicpu(p)^.oper[1].reg),
  1019. paicpu(p)^.oper[0].ref^) then
  1020. removePrevNotUsedLoad(p,reg32(paicpu(p)^.oper[1].reg),false);
  1021. End;
  1022. top_Reg:
  1023. { try to replace the new reg with the old reg }
  1024. if not(PPaiProp(p^.optInfo)^.canBeRemoved) and
  1025. { only remove if we're not storing something in a regvar }
  1026. (paicpu(p)^.oper[1].reg in (usableregs+[R_EDI])) and
  1027. (paicpu(p)^.opcode = A_MOV) and
  1028. getLastInstruction(p,hp4) then
  1029. begin
  1030. case paicpu(p)^.oper[1].typ of
  1031. top_Reg:
  1032. { we only have to start replacing from the instruction after the mov, }
  1033. { but replacereg only starts with getnextinstruction(p,p) }
  1034. if ReplaceReg(asmL,paicpu(p)^.oper[0].reg,
  1035. paicpu(p)^.oper[1].reg,p,
  1036. PPaiProp(hp4^.optInfo)^.Regs[paicpu(p)^.oper[1].reg],false,hp1) then
  1037. begin
  1038. PPaiProp(p^.optInfo)^.canBeRemoved := true;
  1039. allocRegBetween(asmL,paicpu(p)^.oper[0].reg,
  1040. PPaiProp(p^.optInfo)^.regs[paicpu(p)^.oper[0].reg].startMod,
  1041. hp1);
  1042. end;
  1043. end
  1044. end;
  1045. top_symbol,Top_Const:
  1046. Begin
  1047. Case Paicpu(p)^.oper[1].typ Of
  1048. Top_Reg:
  1049. Begin
  1050. regCounter := Reg32(Paicpu(p)^.oper[1].reg);
  1051. If GetLastInstruction(p, hp1) Then
  1052. With PPaiProp(hp1^.OptInfo)^.Regs[regCounter] Do
  1053. if (typ in [con_const,con_noRemoveConst]) and
  1054. (paicpu(startMod)^.opsize >= paicpu(p)^.opsize) and
  1055. opsequal(paicpu(StartMod)^.oper[0],paicpu(p)^.oper[0]) Then
  1056. begin
  1057. PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
  1058. allocRegBetween(asmL,regCounter,startMod,p);
  1059. end;
  1060. End;
  1061. Top_Ref:
  1062. if (paicpu(p)^.oper[0].typ = top_const) and
  1063. getLastInstruction(p,hp1) and
  1064. findRegWithConst(hp1,paicpu(p)^.opsize,paicpu(p)^.oper[0].val,regCounter) then
  1065. begin
  1066. paicpu(p)^.loadreg(0,regCounter);
  1067. allocRegBetween(AsmL,reg32(regCounter),
  1068. PPaiProp(hp1^.optinfo)^.regs[regCounter].startMod,p);
  1069. end;
  1070. End;
  1071. End;
  1072. End;
  1073. End;
  1074. A_STD: If GetLastInstruction(p, hp1) And
  1075. (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
  1076. PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
  1077. End
  1078. End;
  1079. End;
  1080. GetNextInstruction(p, p);
  1081. End;
  1082. End;
  1083. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  1084. { Removes the marked instructions and disposes the PPaiProps of the other }
  1085. { instructions }
  1086. Var p, hp1: Pai;
  1087. begin
  1088. p := First;
  1089. While (p <> Last) Do
  1090. Begin
  1091. If (p^.typ = ait_marker) and
  1092. (pai_marker(p)^.kind in [noPropInfoStart,noPropInfoEnd]) then
  1093. begin
  1094. hp1 := pai(p^.next);
  1095. asmL^.remove(p);
  1096. dispose(p,done);
  1097. p := hp1
  1098. end
  1099. else
  1100. {$ifndef noinstremove}
  1101. if assigned(p^.optInfo) and
  1102. PPaiProp(p^.optInfo)^.canBeRemoved then
  1103. begin
  1104. {$IfDef TP}
  1105. Dispose(PPaiProp(p^.OptInfo));
  1106. {$EndIf}
  1107. hp1 := pai(p^.next);
  1108. AsmL^.Remove(p);
  1109. Dispose(p, Done);
  1110. p := hp1;
  1111. End
  1112. Else
  1113. {$endif noinstremove}
  1114. Begin
  1115. {$IfDef TP}
  1116. if assigned(p^.optInfo) then
  1117. Dispose(PPaiProp(p^.OptInfo));
  1118. {$EndIf TP}
  1119. p^.OptInfo := nil;
  1120. p := pai(p^.next);;
  1121. End;
  1122. End;
  1123. {$IfNDef TP}
  1124. FreeMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4))
  1125. {$EndIf TP}
  1126. End;
  1127. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  1128. Begin
  1129. DoCSE(AsmL, First, Last);
  1130. RemoveInstructs(AsmL, First, Last);
  1131. End;
  1132. End.
  1133. {
  1134. $Log$
  1135. Revision 1.7 2000-08-25 19:40:45 jonas
  1136. * refined previous fix a bit, some instructions weren't being removed
  1137. while they could (merged from fixes branch)
  1138. * made checksequence a bit faster
  1139. Revision 1.6 2000/08/23 12:55:10 jonas
  1140. * fix for web bug 1112 and a bit of clean up in csopt386 (merged from
  1141. fixes branch)
  1142. Revision 1.5 2000/08/04 20:08:03 jonas
  1143. * improved detection of range of instructions which use a register
  1144. (merged from fixes branch)
  1145. Revision 1.4 2000/07/21 15:19:54 jonas
  1146. * daopt386: changes to getnextinstruction/getlastinstruction so they
  1147. ignore labels who have is_addr set
  1148. + daopt386/csopt386: remove loads of registers which are overwritten
  1149. before their contents are used (especially usefull for removing superfluous
  1150. maybe_loadesi outputs and push/pops transformed by below optimization
  1151. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  1152. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  1153. currently because I don't know whether it's safe to do this under Win32/
  1154. Linux (because of problems we had when using esp as frame pointer on
  1155. those os'es)
  1156. Revision 1.3 2000/07/14 05:11:48 michael
  1157. + Patch to 1.1
  1158. Revision 1.2 2000/07/13 11:32:39 michael
  1159. + removed logs
  1160. }