csopt386.pas 46 KB

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