aoptobj.pas 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. {
  2. Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit contains the processor independent assembler optimizer
  5. object, base for the dataflow analyzer, peepholeoptimizer and
  6. common subexpression elimination objects.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. Unit AoptObj;
  21. {$i fpcdefs.inc}
  22. { general, processor independent objects for use by the assembler optimizer }
  23. Interface
  24. uses
  25. globtype,
  26. aasmbase,aasmcpu,aasmtai,aasmdata,
  27. cclasses,
  28. cgbase,cgutils,
  29. cpubase,
  30. aoptbase,aoptcpub,aoptda;
  31. { ************************************************************************* }
  32. { ********************************* Constants ***************************** }
  33. { ************************************************************************* }
  34. Const
  35. {Possible register content types}
  36. con_Unknown = 0;
  37. con_ref = 1;
  38. con_const = 2;
  39. {***************** Types ****************}
  40. Type
  41. { ************************************************************************* }
  42. { ************************* Some general type definitions ***************** }
  43. { ************************************************************************* }
  44. TRefCompare = Function(const r1, r2: TReference): Boolean;
  45. //!!! FIXME
  46. TRegArray = Array[byte] of tsuperregister;
  47. TRegSet = Set of byte;
  48. { possible actions on an operand: read, write or modify (= read & write) }
  49. TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
  50. { ************************************************************************* }
  51. { * Object to hold information on which regiters are in use and which not * }
  52. { ************************************************************************* }
  53. { TUsedRegs }
  54. TUsedRegs = class
  55. Constructor create(aTyp : TRegisterType);
  56. Constructor create_regset(aTyp : TRegisterType;Const _RegSet: TRegSet);
  57. Destructor Destroy;override;
  58. Procedure Clear;
  59. { update the info with the pairegalloc objects coming after
  60. p }
  61. Procedure Update(p: Tai);
  62. { is Reg currently in use }
  63. Function IsUsed(Reg: TRegister): Boolean;
  64. { get all the currently used registers }
  65. Function GetUsedRegs: TRegSet;
  66. Private
  67. Typ : TRegisterType;
  68. UsedRegs: TRegSet;
  69. End;
  70. { ************************************************************************* }
  71. { ******************* Contents of the integer registers ******************* }
  72. { ************************************************************************* }
  73. { size of the integer that holds the state number of a register. Can be any }
  74. { integer type, so it can be changed to reduce the size of the TContent }
  75. { structure or to improve alignment }
  76. TStateInt = Byte;
  77. TContent = Record
  78. { start and end of block instructions that defines the }
  79. { content of this register. If Typ = con_const, then }
  80. { Longint(StartMod) = value of the constant) }
  81. StartMod: Tai;
  82. { starts at 0, gets increased everytime the register is }
  83. { written to }
  84. WState: TStateInt;
  85. { starts at 0, gets increased everytime the register is read }
  86. { from }
  87. RState: TStateInt;
  88. { how many instructions starting with StarMod does the block }
  89. { consist of }
  90. NrOfMods: Byte;
  91. { the type of the content of the register: unknown, memory }
  92. { (variable) or constant }
  93. Typ: Byte;
  94. End;
  95. //!!! FIXME
  96. TRegContent = Array[byte] Of TContent;
  97. { ************************************************************************** }
  98. { information object with the contents of every register. Every Tai object }
  99. { gets one of these assigned: a pointer to it is stored in the OptInfo field }
  100. { ************************************************************************** }
  101. { TPaiProp }
  102. TPaiProp = class(TAoptBaseCpu)
  103. Regs: TRegContent;
  104. { can this instruction be removed? }
  105. CanBeRemoved: Boolean;
  106. Constructor create; reintroduce;
  107. { checks the whole sequence of which (so regs[which].StartMod and and }
  108. { the next NrOfMods Tai objects) to see whether Reg is used somewhere, }
  109. { without it being loaded with something else first }
  110. Function RegInSequence(Reg, which: TRegister): Boolean;
  111. { destroy the contents of a register, as well as those whose contents }
  112. { are based on those of that register }
  113. Procedure DestroyReg(Reg: TRegister; var InstrSinceLastMod:
  114. TInstrSinceLastMod);
  115. { if the contents of WhichReg (can be R_NO in case of a constant) are }
  116. { written to memory at the location Ref, the contents of the registers }
  117. { that depend on Ref have to be destroyed }
  118. Procedure DestroyRefs(Const Ref: TReference; WhichReg: TRegister; var
  119. InstrSinceLastMod: TInstrSinceLastMod);
  120. { an instruction reads from operand o }
  121. Procedure ReadOp(const o:toper);
  122. { an instruction reads from reference Ref }
  123. Procedure ReadRef(Ref: PReference);
  124. { an instruction reads from register Reg }
  125. Procedure ReadReg(Reg: TRegister);
  126. { an instruction writes/modifies operand o and this has special }
  127. { side-effects or modifies the contents in such a way that we can't }
  128. { simply add this instruction to the sequence of instructions that }
  129. { describe the contents of the operand, so destroy it }
  130. Procedure DestroyOp(const o:Toper; var InstrSinceLastMod:
  131. TInstrSinceLastMod);
  132. { destroy the contents of all registers }
  133. Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
  134. { a register's contents are modified, but not destroyed (the new value
  135. depends on the old one) }
  136. Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
  137. TInstrSinceLastMod);
  138. { an operand's contents are modified, but not destroyed (the new value
  139. depends on the old one) }
  140. Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
  141. TInstrSinceLastMod);
  142. { increase the write state of a register (call every time a register is
  143. written to) }
  144. Procedure IncWState(Reg: TRegister);
  145. { increase the read state of a register (call every time a register is }
  146. { read from) }
  147. Procedure IncRState(Reg: TRegister);
  148. { get the write state of a register }
  149. Function GetWState(Reg: TRegister): TStateInt;
  150. { get the read state of a register }
  151. Function GetRState(Reg: TRegister): TStateInt;
  152. { get the type of contents of a register }
  153. Function GetRegContentType(Reg: TRegister): Byte;
  154. Destructor Done;
  155. Private
  156. Procedure IncState(var s: TStateInt);
  157. { returns whether the reference Ref is used somewhere in the loading }
  158. { sequence Content }
  159. Function RefInSequence(Const Ref: TReference; Content: TContent;
  160. RefsEq: TRefCompare): Boolean;
  161. { returns whether the instruction P reads from and/or writes }
  162. { to Reg }
  163. Function RefInInstruction(Const Ref: TReference; p: Tai;
  164. RefsEq: TRefCompare): Boolean;
  165. { returns whether two references with at least one pointing to an array }
  166. { may point to the same memory location }
  167. End;
  168. { ************************************************************************* }
  169. { ************************ Label information ****************************** }
  170. { ************************************************************************* }
  171. TLabelTableItem = Record
  172. PaiObj: Tai;
  173. End;
  174. TLabelTable = Array[0..2500000] Of TLabelTableItem;
  175. PLabelTable = ^TLabelTable;
  176. PLabelInfo = ^TLabelInfo;
  177. TLabelInfo = Record
  178. { the highest and lowest label number occurring in the current code }
  179. { fragment }
  180. LowLabel, HighLabel: longint;
  181. LabelDif: cardinal;
  182. { table that contains the addresses of the Pai_Label objects associated
  183. with each label number }
  184. LabelTable: PLabelTable;
  185. End;
  186. { ************************************************************************* }
  187. { ********** General optimizer object, used to derive others from ********* }
  188. { ************************************************************************* }
  189. TAllUsedRegs = array[TRegisterType] of TUsedRegs;
  190. { TAOptObj }
  191. TAOptObj = class(TAoptBaseCpu)
  192. { the PAasmOutput list this optimizer instance works on }
  193. AsmL: TAsmList;
  194. { The labelinfo record contains the addresses of the Tai objects }
  195. { that are labels, how many labels there are and the min and max }
  196. { label numbers }
  197. LabelInfo: PLabelInfo;
  198. { Start and end of the block that is currently being optimized }
  199. BlockStart, BlockEnd: Tai;
  200. DFA: TAOptDFA;
  201. UsedRegs: TAllUsedRegs;
  202. { _AsmL is the PAasmOutpout list that has to be optimized, }
  203. { _BlockStart and _BlockEnd the start and the end of the block }
  204. { that has to be optimized and _LabelInfo a pointer to a }
  205. { TLabelInfo record }
  206. Constructor create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
  207. _LabelInfo: PLabelInfo); virtual; reintroduce;
  208. Destructor Destroy;override;
  209. { processor independent methods }
  210. Procedure CreateUsedRegs(var regs: TAllUsedRegs);
  211. Procedure ClearUsedRegs;
  212. Procedure UpdateUsedRegs(p : Tai);
  213. procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai);
  214. Function CopyUsedRegs(var dest : TAllUsedRegs) : boolean;
  215. Procedure ReleaseUsedRegs(const regs : TAllUsedRegs);
  216. Function RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean;
  217. Procedure IncludeRegInUsedRegs(reg : TRegister;var regs : TAllUsedRegs);
  218. Procedure ExcludeRegFromUsedRegs(reg: TRegister;var regs : TAllUsedRegs);
  219. { returns true if the label L is found between hp and the next }
  220. { instruction }
  221. Function FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
  222. { inserts new_one between prev and foll in AsmL }
  223. Procedure InsertLLItem(prev, foll, new_one: TLinkedListItem);
  224. { If P is a Tai object releveant to the optimizer, P is returned
  225. If it is not relevant tot he optimizer, the first object after P
  226. that is relevant is returned }
  227. Function SkipHead(P: Tai): Tai;
  228. { returns true if the operands o1 and o2 are completely equal }
  229. Function OpsEqual(const o1,o2:toper): Boolean;
  230. { Returns true if a ait_alloc object for Reg is found in the block
  231. of Tai's starting with StartPai and ending with the next "real"
  232. instruction }
  233. Function FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
  234. { reg used after p? }
  235. function RegUsedAfterInstruction(reg: Tregister; p: tai; var AllUsedRegs: TAllUsedRegs): Boolean;
  236. { traces sucessive jumps to their final destination and sets it, e.g.
  237. je l1 je l3
  238. <code> <code>
  239. l1: becomes l1:
  240. je l2 je l3
  241. <code> <code>
  242. l2: l2:
  243. jmp l3 jmp l3
  244. the level parameter denotes how deeep we have already followed the jump,
  245. to avoid endless loops with constructs such as "l5: ; jmp l5" }
  246. function GetFinalDestination(hp: taicpu; level: longint): boolean;
  247. function getlabelwithsym(sym: tasmlabel): tai;
  248. { peephole optimizer }
  249. procedure PrePeepHoleOpts;
  250. procedure PeepHoleOptPass1;
  251. procedure PeepHoleOptPass2; virtual;
  252. procedure PostPeepHoleOpts;
  253. { processor dependent methods }
  254. // if it returns true, perform a "continue"
  255. function PeepHoleOptPass1Cpu(var p: tai): boolean; virtual;
  256. function PostPeepHoleOptsCpu(var p: tai): boolean; virtual;
  257. End;
  258. Function ArrayRefsEq(const r1, r2: TReference): Boolean;
  259. { ***************************** Implementation **************************** }
  260. Implementation
  261. uses
  262. globals,
  263. verbose,
  264. procinfo;
  265. { ************************************************************************* }
  266. { ******************************** TUsedRegs ****************************** }
  267. { ************************************************************************* }
  268. Constructor TUsedRegs.create(aTyp : TRegisterType);
  269. Begin
  270. Typ:=aTyp;
  271. UsedRegs := [];
  272. End;
  273. Constructor TUsedRegs.create_regset(aTyp : TRegisterType;Const _RegSet: TRegSet);
  274. Begin
  275. Typ:=aTyp;
  276. UsedRegs := _RegSet;
  277. End;
  278. {
  279. updates UsedRegs with the RegAlloc Information coming after P
  280. }
  281. Procedure TUsedRegs.Update(p: Tai);
  282. Begin
  283. repeat
  284. while assigned(p) and
  285. ((p.typ in (SkipInstr - [ait_RegAlloc])) or
  286. ((p.typ = ait_label) and
  287. labelCanBeSkipped(tai_label(p))) or
  288. ((p.typ = ait_marker) and
  289. (tai_Marker(p).Kind in [mark_AsmBlockEnd,mark_NoLineInfoStart,mark_NoLineInfoEnd]))) do
  290. p := tai(p.next);
  291. while assigned(p) and
  292. (p.typ=ait_RegAlloc) Do
  293. begin
  294. if (getregtype(tai_regalloc(p).reg) = typ) then
  295. begin
  296. case tai_regalloc(p).ratype of
  297. ra_alloc :
  298. Include(UsedRegs, getsupreg(tai_regalloc(p).reg));
  299. ra_dealloc :
  300. Exclude(UsedRegs, getsupreg(tai_regalloc(p).reg));
  301. end;
  302. end;
  303. p := tai(p.next);
  304. end;
  305. until not(assigned(p)) or
  306. (not(p.typ in SkipInstr) and
  307. not((p.typ = ait_label) and
  308. labelCanBeSkipped(tai_label(p))));
  309. End;
  310. Function TUsedRegs.IsUsed(Reg: TRegister): Boolean;
  311. Begin
  312. IsUsed := (getregtype(Reg)=Typ) and (getsupreg(Reg) in UsedRegs);
  313. End;
  314. Function TUsedRegs.GetUsedRegs: TRegSet;
  315. Begin
  316. GetUsedRegs := UsedRegs;
  317. End;
  318. Destructor TUsedRegs.Destroy;
  319. Begin
  320. inherited destroy;
  321. end;
  322. procedure TUsedRegs.Clear;
  323. begin
  324. UsedRegs := [];
  325. end;
  326. { ************************************************************************* }
  327. { **************************** TPaiProp *********************************** }
  328. { ************************************************************************* }
  329. Constructor TPaiProp.Create;
  330. Begin
  331. {!!!!!!
  332. UsedRegs.Init;
  333. CondRegs.init;
  334. }
  335. { DirFlag: TFlagContents; I386 specific}
  336. End;
  337. Function TPaiProp.RegInSequence(Reg, which: TRegister): Boolean;
  338. {
  339. Var p: Tai;
  340. RegsChecked: TRegSet;
  341. content: TContent;
  342. Counter: Byte;
  343. TmpResult: Boolean;
  344. }
  345. begin
  346. Result:=False; { unimplemented }
  347. (*!!!!!!!!!!1
  348. RegsChecked := [];
  349. content := regs[which];
  350. p := content.StartMod;
  351. TmpResult := False;
  352. Counter := 1;
  353. While Not(TmpResult) And
  354. (Counter <= Content.NrOfMods) Do
  355. Begin
  356. If IsLoadMemReg(p) Then
  357. With PInstr(p)^.oper[LoadSrc]^.ref^ Do
  358. If (Base = ProcInfo.FramePointer)
  359. {$ifdef cpurefshaveindexreg}
  360. And (Index = R_NO)
  361. {$endif cpurefshaveindexreg} Then
  362. Begin
  363. RegsChecked := RegsChecked +
  364. [RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg)];
  365. If Reg = RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg) Then
  366. Break;
  367. End
  368. Else
  369. Begin
  370. If (Base = Reg) And
  371. Not(Base In RegsChecked)
  372. Then TmpResult := True;
  373. {$ifdef cpurefshaveindexreg}
  374. If Not(TmpResult) And
  375. (Index = Reg) And
  376. Not(Index In RegsChecked)
  377. Then TmpResult := True;
  378. {$Endif cpurefshaveindexreg}
  379. End
  380. Else TmpResult := RegInInstruction(Reg, p);
  381. Inc(Counter);
  382. GetNextInstruction(p,p)
  383. End;
  384. RegInSequence := TmpResult
  385. *)
  386. End;
  387. Procedure TPaiProp.DestroyReg(Reg: TRegister; var InstrSinceLastMod:
  388. TInstrSinceLastMod);
  389. { Destroys the contents of the register Reg in the PPaiProp p1, as well as }
  390. { the contents of registers are loaded with a memory location based on Reg }
  391. {
  392. Var TmpWState, TmpRState: Byte;
  393. Counter: TRegister;
  394. }
  395. Begin
  396. {!!!!!!!
  397. Reg := RegMaxSize(Reg);
  398. If (Reg in [LoGPReg..HiGPReg]) Then
  399. For Counter := LoGPReg to HiGPReg Do
  400. With Regs[Counter] Do
  401. If (Counter = reg) Or
  402. ((Typ = Con_Ref) And
  403. RegInSequence(Reg, Counter)) Then
  404. Begin
  405. InstrSinceLastMod[Counter] := 0;
  406. IncWState(Counter);
  407. TmpWState := GetWState(Counter);
  408. TmpRState := GetRState(Counter);
  409. FillChar(Regs[Counter], SizeOf(TContent), 0);
  410. WState := TmpWState;
  411. RState := TmpRState
  412. End
  413. }
  414. End;
  415. Function ArrayRefsEq(const r1, r2: TReference): Boolean;
  416. Begin
  417. Result:=False; { unimplemented }
  418. (*!!!!!!!!!!
  419. ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
  420. {$ifdef refsHaveSegmentReg}
  421. (R1.Segment = R2.Segment) And
  422. {$endif}
  423. (R1.Base = R2.Base) And
  424. (R1.Symbol=R2.Symbol);
  425. *)
  426. End;
  427. Procedure TPaiProp.DestroyRefs(Const Ref: TReference; WhichReg: TRegister;
  428. var InstrSinceLastMod: TInstrSinceLastMod);
  429. { destroys all registers which possibly contain a reference to Ref, WhichReg }
  430. { is the register whose contents are being written to memory (if this proc }
  431. { is called because of a "mov?? %reg, (mem)" instruction) }
  432. {
  433. Var RefsEq: TRefCompare;
  434. Counter: TRegister;
  435. }
  436. Begin
  437. (*!!!!!!!!!!!
  438. WhichReg := RegMaxSize(WhichReg);
  439. If (Ref.base = procinfo.FramePointer) or
  440. Assigned(Ref.Symbol) Then
  441. Begin
  442. If
  443. {$ifdef cpurefshaveindexreg}
  444. (Ref.Index = R_NO) And
  445. {$endif cpurefshaveindexreg}
  446. (Not(Assigned(Ref.Symbol)) or
  447. (Ref.base = R_NO)) Then
  448. { local variable which is not an array }
  449. RefsEq := @RefsEqual
  450. Else
  451. { local variable which is an array }
  452. RefsEq := @ArrayRefsEq;
  453. {write something to a parameter, a local or global variable, so
  454. * with uncertain optimizations on:
  455. - destroy the contents of registers whose contents have somewhere a
  456. "mov?? (Ref), %reg". WhichReg (this is the register whose contents
  457. are being written to memory) is not destroyed if it's StartMod is
  458. of that form and NrOfMods = 1 (so if it holds ref, but is not a
  459. pointer or value based on Ref)
  460. * with uncertain optimizations off:
  461. - also destroy registers that contain any pointer}
  462. For Counter := LoGPReg to HiGPReg Do
  463. With Regs[Counter] Do
  464. Begin
  465. If (typ = Con_Ref) And
  466. ((Not(cs_opt_size in current_settings.optimizerswitches) And
  467. (NrOfMods <> 1)
  468. ) Or
  469. (RefInSequence(Ref,Regs[Counter], RefsEq) And
  470. ((Counter <> WhichReg) Or
  471. ((NrOfMods <> 1) And
  472. {StarMod is always of the type ait_instruction}
  473. (PInstr(StartMod)^.oper[0].typ = top_ref) And
  474. RefsEq(PInstr(StartMod)^.oper[0].ref^, Ref)
  475. )
  476. )
  477. )
  478. )
  479. Then
  480. DestroyReg(Counter, InstrSinceLastMod)
  481. End
  482. End
  483. Else
  484. {write something to a pointer location, so
  485. * with uncertain optimzations on:
  486. - do not destroy registers which contain a local/global variable or a
  487. parameter, except if DestroyRefs is called because of a "movsl"
  488. * with uncertain optimzations off:
  489. - destroy every register which contains a memory location
  490. }
  491. For Counter := LoGPReg to HiGPReg Do
  492. With Regs[Counter] Do
  493. If (typ = Con_Ref) And
  494. (Not(cs_opt_size in current_settings.optimizerswitches) Or
  495. {$ifdef x86}
  496. {for movsl}
  497. (Ref.Base = R_EDI) Or
  498. {$endif}
  499. {don't destroy if reg contains a parameter, local or global variable}
  500. Not((NrOfMods = 1) And
  501. (PInstr(StartMod)^.oper[0].typ = top_ref) And
  502. ((PInstr(StartMod)^.oper[0].ref^.base = ProcInfo.FramePointer) Or
  503. Assigned(PInstr(StartMod)^.oper[0].ref^.Symbol)
  504. )
  505. )
  506. )
  507. Then DestroyReg(Counter, InstrSinceLastMod)
  508. *)
  509. End;
  510. Procedure TPaiProp.DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
  511. {Var Counter: TRegister;}
  512. Begin {initializes/desrtoys all registers}
  513. (*!!!!!!!!!
  514. For Counter := LoGPReg To HiGPReg Do
  515. Begin
  516. ReadReg(Counter);
  517. DestroyReg(Counter, InstrSinceLastMod);
  518. End;
  519. CondRegs.Init;
  520. { FPURegs.Init; }
  521. *)
  522. End;
  523. Procedure TPaiProp.DestroyOp(const o:Toper; var InstrSinceLastMod:
  524. TInstrSinceLastMod);
  525. Begin
  526. {!!!!!!!
  527. Case o.typ Of
  528. top_reg: DestroyReg(o.reg, InstrSinceLastMod);
  529. top_ref:
  530. Begin
  531. ReadRef(o.ref);
  532. DestroyRefs(o.ref^, R_NO, InstrSinceLastMod);
  533. End;
  534. top_symbol:;
  535. End;
  536. }
  537. End;
  538. Procedure TPaiProp.ReadReg(Reg: TRegister);
  539. Begin
  540. {!!!!!!!
  541. Reg := RegMaxSize(Reg);
  542. If Reg in General_Registers Then
  543. IncRState(RegMaxSize(Reg))
  544. }
  545. End;
  546. Procedure TPaiProp.ReadRef(Ref: PReference);
  547. Begin
  548. (*!!!!!!
  549. If Ref^.Base <> R_NO Then
  550. ReadReg(Ref^.Base);
  551. {$ifdef cpurefshaveindexreg}
  552. If Ref^.Index <> R_NO Then
  553. ReadReg(Ref^.Index);
  554. {$endif cpurefshaveindexreg}
  555. *)
  556. End;
  557. Procedure TPaiProp.ReadOp(const o:toper);
  558. Begin
  559. Case o.typ Of
  560. top_reg: ReadReg(o.reg);
  561. top_ref: ReadRef(o.ref);
  562. else
  563. internalerror(200410241);
  564. End;
  565. End;
  566. Procedure TPaiProp.ModifyReg(reg: TRegister; Var InstrSinceLastMod:
  567. TInstrSinceLastMod);
  568. Begin
  569. (*!!!!!!!
  570. With Regs[reg] Do
  571. If (Typ = Con_Ref)
  572. Then
  573. Begin
  574. IncState(WState);
  575. {also store how many instructions are part of the sequence in the first
  576. instructions PPaiProp, so it can be easily accessed from within
  577. CheckSequence}
  578. Inc(NrOfMods, InstrSinceLastMod[Reg]);
  579. PPaiProp(StartMod.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
  580. InstrSinceLastMod[Reg] := 0;
  581. End
  582. Else
  583. DestroyReg(Reg, InstrSinceLastMod);
  584. *)
  585. End;
  586. Procedure TPaiProp.ModifyOp(const oper: TOper; var InstrSinceLastMod:
  587. TInstrSinceLastMod);
  588. Begin
  589. If oper.typ = top_reg Then
  590. ModifyReg(RegMaxSize(oper.reg),InstrSinceLastMod)
  591. Else
  592. Begin
  593. ReadOp(oper);
  594. DestroyOp(oper, InstrSinceLastMod);
  595. End
  596. End;
  597. Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
  598. Begin
  599. //!!!! IncState(Regs[Reg].WState);
  600. End;
  601. Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
  602. Begin
  603. //!!!! IncState(Regs[Reg].RState);
  604. End;
  605. Function TPaiProp.GetWState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
  606. Begin
  607. Result:=0; { unimplemented }
  608. //!!!! GetWState := Regs[Reg].WState
  609. End;
  610. Function TPaiProp.GetRState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
  611. Begin
  612. Result:=0; { unimplemented }
  613. //!!!! GetRState := Regs[Reg].RState
  614. End;
  615. Function TPaiProp.GetRegContentType(Reg: TRegister): Byte; {$ifdef inl} inline;{$endif inl}
  616. Begin
  617. Result:=0; { unimplemented }
  618. //!!!! GetRegContentType := Regs[Reg].typ
  619. End;
  620. Destructor TPaiProp.Done;
  621. Begin
  622. //!!!! UsedRegs.Done;
  623. //!!!! CondRegs.Done;
  624. { DirFlag: TFlagContents; I386 specific}
  625. End;
  626. { ************************ private TPaiProp stuff ************************* }
  627. Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef inl} inline;{$endif inl}
  628. Begin
  629. If s <> High(TStateInt) Then Inc(s)
  630. Else s := 0
  631. End;
  632. Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Tai;
  633. RefsEq: TRefCompare): Boolean;
  634. Var Count: AWord;
  635. TmpResult: Boolean;
  636. Begin
  637. TmpResult := False;
  638. If (p.typ = ait_instruction) Then
  639. Begin
  640. Count := 0;
  641. Repeat
  642. If (TInstr(p).oper[Count]^.typ = Top_Ref) Then
  643. TmpResult := RefsEq(Ref, PInstr(p)^.oper[Count]^.ref^);
  644. Inc(Count);
  645. Until (Count = MaxOps) or TmpResult;
  646. End;
  647. RefInInstruction := TmpResult;
  648. End;
  649. Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent;
  650. RefsEq: TRefCompare): Boolean;
  651. Var p: Tai;
  652. Counter: Byte;
  653. TmpResult: Boolean;
  654. Begin
  655. p := Content.StartMod;
  656. TmpResult := False;
  657. Counter := 1;
  658. While Not(TmpResult) And
  659. (Counter <= Content.NrOfMods) Do
  660. Begin
  661. If (p.typ = ait_instruction) And
  662. RefInInstruction(Ref, p, @references_equal)
  663. Then TmpResult := True;
  664. Inc(Counter);
  665. GetNextInstruction(p,p)
  666. End;
  667. RefInSequence := TmpResult
  668. End;
  669. { ************************************************************************* }
  670. { ***************************** TAoptObj ********************************** }
  671. { ************************************************************************* }
  672. Constructor TAoptObj.create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
  673. _LabelInfo: PLabelInfo);
  674. Begin
  675. AsmL := _AsmL;
  676. BlockStart := _BlockStart;
  677. BlockEnd := _BlockEnd;
  678. LabelInfo := _LabelInfo;
  679. CreateUsedRegs(UsedRegs);
  680. End;
  681. destructor TAOptObj.Destroy;
  682. var
  683. i : TRegisterType;
  684. begin
  685. for i:=low(TRegisterType) to high(TRegisterType) do
  686. UsedRegs[i].Destroy;
  687. inherited Destroy;
  688. end;
  689. procedure TAOptObj.CreateUsedRegs(var regs: TAllUsedRegs);
  690. var
  691. i : TRegisterType;
  692. begin
  693. for i:=low(TRegisterType) to high(TRegisterType) do
  694. Regs[i]:=TUsedRegs.Create(i);
  695. end;
  696. procedure TAOptObj.ClearUsedRegs;
  697. var
  698. i : TRegisterType;
  699. begin
  700. for i:=low(TRegisterType) to high(TRegisterType) do
  701. UsedRegs[i].Clear;
  702. end;
  703. procedure TAOptObj.UpdateUsedRegs(p : Tai);
  704. var
  705. i : TRegisterType;
  706. begin
  707. for i:=low(TRegisterType) to high(TRegisterType) do
  708. UsedRegs[i].Update(p);
  709. end;
  710. procedure TAOptObj.UpdateUsedRegs(var Regs : TAllUsedRegs;p : Tai);
  711. var
  712. i : TRegisterType;
  713. begin
  714. for i:=low(TRegisterType) to high(TRegisterType) do
  715. Regs[i].Update(p);
  716. end;
  717. function TAOptObj.CopyUsedRegs(var dest: TAllUsedRegs): boolean;
  718. var
  719. i : TRegisterType;
  720. begin
  721. Result:=true;
  722. for i:=low(TRegisterType) to high(TRegisterType) do
  723. dest[i]:=TUsedRegs.Create_Regset(i,UsedRegs[i].GetUsedRegs);
  724. end;
  725. procedure TAOptObj.ReleaseUsedRegs(const regs: TAllUsedRegs);
  726. var
  727. i : TRegisterType;
  728. begin
  729. for i:=low(TRegisterType) to high(TRegisterType) do
  730. regs[i].Free;
  731. end;
  732. Function TAOptObj.RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean;
  733. begin
  734. result:=regs[getregtype(reg)].IsUsed(reg);
  735. end;
  736. procedure TAOptObj.IncludeRegInUsedRegs(reg: TRegister;
  737. var regs: TAllUsedRegs);
  738. begin
  739. include(regs[getregtype(reg)].UsedRegs,getsupreg(Reg));
  740. end;
  741. procedure TAOptObj.ExcludeRegFromUsedRegs(reg: TRegister;
  742. var regs: TAllUsedRegs);
  743. begin
  744. exclude(regs[getregtype(reg)].UsedRegs,getsupreg(Reg));
  745. end;
  746. Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
  747. Var TempP: Tai;
  748. Begin
  749. TempP := hp;
  750. While Assigned(TempP) and
  751. (TempP.typ In SkipInstr + [ait_label]) Do
  752. If (TempP.typ <> ait_Label) Or
  753. (Tai_label(TempP).labsym <> L)
  754. Then GetNextInstruction(TempP, TempP)
  755. Else
  756. Begin
  757. hp := TempP;
  758. FindLabel := True;
  759. exit
  760. End;
  761. FindLabel := False;
  762. End;
  763. Procedure TAOptObj.InsertLLItem(prev, foll, new_one : TLinkedListItem);
  764. Begin
  765. If Assigned(prev) Then
  766. If Assigned(foll) Then
  767. Begin
  768. If Assigned(new_one) Then
  769. Begin
  770. new_one.previous := prev;
  771. new_one.next := foll;
  772. prev.next := new_one;
  773. foll.previous := new_one;
  774. { should we update line information? }
  775. if (not (tai(new_one).typ in SkipLineInfo)) and
  776. (not (tai(foll).typ in SkipLineInfo)) then
  777. Tailineinfo(new_one).fileinfo := Tailineinfo(foll).fileinfo
  778. End
  779. End
  780. Else AsmL.Concat(new_one)
  781. Else If Assigned(Foll) Then AsmL.Insert(new_one)
  782. End;
  783. Function TAOptObj.SkipHead(P: Tai): Tai;
  784. Var OldP: Tai;
  785. Begin
  786. Repeat
  787. OldP := P;
  788. If (P.typ in SkipInstr) Or
  789. ((P.typ = ait_marker) And
  790. (Tai_Marker(P).Kind = mark_AsmBlockEnd)) Then
  791. GetNextInstruction(P, P)
  792. Else If ((P.Typ = Ait_Marker) And
  793. (Tai_Marker(P).Kind = mark_NoPropInfoStart)) Then
  794. { a marker of the type mark_NoPropInfoStart can't be the first instruction of a }
  795. { paasmoutput list }
  796. GetNextInstruction(Tai(P.Previous),P);
  797. If (P.Typ = Ait_Marker) And
  798. (Tai_Marker(P).Kind = mark_AsmBlockStart) Then
  799. Begin
  800. P := Tai(P.Next);
  801. While (P.typ <> Ait_Marker) Or
  802. (Tai_Marker(P).Kind <> mark_AsmBlockEnd) Do
  803. P := Tai(P.Next)
  804. End;
  805. Until P = OldP;
  806. SkipHead := P;
  807. End;
  808. Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean;
  809. Begin
  810. if o1.typ=o2.typ then
  811. Case o1.typ Of
  812. Top_Reg :
  813. OpsEqual:=o1.reg=o2.reg;
  814. Top_Ref :
  815. OpsEqual := references_equal(o1.ref^, o2.ref^);
  816. Top_Const :
  817. OpsEqual:=o1.val=o2.val;
  818. Top_None :
  819. OpsEqual := True
  820. else OpsEqual := False
  821. End
  822. else
  823. OpsEqual := False;
  824. End;
  825. Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
  826. Begin
  827. FindRegAlloc:=False;
  828. Repeat
  829. While Assigned(StartPai) And
  830. ((StartPai.typ in (SkipInstr - [ait_regAlloc])) Or
  831. ((StartPai.typ = ait_label) and
  832. Not(Tai_Label(StartPai).labsym.Is_Used))) Do
  833. StartPai := Tai(StartPai.Next);
  834. If Assigned(StartPai) And
  835. (StartPai.typ = ait_regAlloc) and (tai_regalloc(StartPai).ratype=ra_alloc) Then
  836. Begin
  837. if tai_regalloc(StartPai).Reg = Reg then
  838. begin
  839. FindRegAlloc:=true;
  840. exit;
  841. end;
  842. StartPai := Tai(StartPai.Next);
  843. End
  844. else
  845. exit;
  846. Until false;
  847. End;
  848. function TAOptObj.RegUsedAfterInstruction(reg: Tregister; p: tai;
  849. var AllUsedRegs: TAllUsedRegs): Boolean;
  850. begin
  851. AllUsedRegs[getregtype(reg)].Update(tai(p.Next));
  852. RegUsedAfterInstruction :=
  853. (AllUsedRegs[getregtype(reg)].IsUsed(reg)); { optimization and
  854. (not(getNextInstruction(p,p)) or
  855. not(regLoadedWithNewValue(supreg,false,p))); }
  856. end;
  857. function SkipLabels(hp: tai; var hp2: tai): boolean;
  858. {skips all labels and returns the next "real" instruction}
  859. begin
  860. while assigned(hp.next) and
  861. (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
  862. hp := tai(hp.next);
  863. if assigned(hp.next) then
  864. begin
  865. SkipLabels := True;
  866. hp2 := tai(hp.next)
  867. end
  868. else
  869. begin
  870. hp2 := hp;
  871. SkipLabels := False
  872. end;
  873. end;
  874. function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
  875. begin
  876. FindAnyLabel := false;
  877. while assigned(hp.next) and
  878. (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
  879. hp := tai(hp.next);
  880. if assigned(hp.next) and
  881. (tai(hp.next).typ = ait_label) then
  882. begin
  883. FindAnyLabel := true;
  884. l := tai_label(hp.next).labsym;
  885. end
  886. end;
  887. {$push}
  888. {$r-}
  889. function tAOptObj.getlabelwithsym(sym: tasmlabel): tai;
  890. begin
  891. if (int64(sym.labelnr) >= int64(labelinfo^.lowlabel)) and
  892. (int64(sym.labelnr) <= int64(labelinfo^.highlabel)) then { range check, a jump can go past an assembler block! }
  893. getlabelwithsym := labelinfo^.labeltable^[sym.labelnr-labelinfo^.lowlabel].paiobj
  894. else
  895. getlabelwithsym := nil;
  896. end;
  897. {$pop}
  898. function TAOptObj.GetFinalDestination(hp: taicpu; level: longint): boolean;
  899. {traces sucessive jumps to their final destination and sets it, e.g.
  900. je l1 je l3
  901. <code> <code>
  902. l1: becomes l1:
  903. je l2 je l3
  904. <code> <code>
  905. l2: l2:
  906. jmp l3 jmp l3
  907. the level parameter denotes how deeep we have already followed the jump,
  908. to avoid endless loops with constructs such as "l5: ; jmp l5" }
  909. var p1, p2: tai;
  910. l: tasmlabel;
  911. begin
  912. GetfinalDestination := false;
  913. if level > 20 then
  914. exit;
  915. p1 := getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
  916. if assigned(p1) then
  917. begin
  918. SkipLabels(p1,p1);
  919. if (tai(p1).typ = ait_instruction) and
  920. (taicpu(p1).is_jmp) then
  921. if { the next instruction after the label where the jump hp arrives}
  922. { is unconditional or of the same type as hp, so continue }
  923. (((taicpu(p1).opcode = aopt_uncondjmp) and
  924. {$ifdef arm}
  925. (taicpu(p1).condition = C_None) and
  926. {$endif arm}
  927. (taicpu(p1).oper[0]^.typ = top_ref) and
  928. (assigned(taicpu(p1).oper[0]^.ref^.symbol)) and
  929. (taicpu(p1).oper[0]^.ref^.symbol is TAsmLabel)) or
  930. conditions_equal(taicpu(p1).condition,hp.condition)) or
  931. { the next instruction after the label where the jump hp arrives}
  932. { is the opposite of hp (so this one is never taken), but after }
  933. { that one there is a branch that will be taken, so perform a }
  934. { little hack: set p1 equal to this instruction (that's what the}
  935. { last SkipLabels is for, only works with short bool evaluation)}
  936. (conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) and
  937. SkipLabels(p1,p2) and
  938. (p2.typ = ait_instruction) and
  939. (taicpu(p2).is_jmp) and
  940. (((taicpu(p2).opcode = aopt_uncondjmp) and
  941. {$ifdef arm}
  942. (taicpu(p1).condition = C_None) and
  943. {$endif arm}
  944. (taicpu(p2).oper[0]^.typ = top_ref) and
  945. (assigned(taicpu(p2).oper[0]^.ref^.symbol)) and
  946. (taicpu(p2).oper[0]^.ref^.symbol is TAsmLabel)) or
  947. (conditions_equal(taicpu(p2).condition,hp.condition))) and
  948. SkipLabels(p1,p1)) then
  949. begin
  950. { quick check for loops of the form "l5: ; jmp l5 }
  951. if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
  952. tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
  953. exit;
  954. if not GetFinalDestination(taicpu(p1),succ(level)) then
  955. exit;
  956. tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
  957. hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
  958. tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
  959. end
  960. else
  961. if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
  962. if not FindAnyLabel(p1,l) then
  963. begin
  964. {$ifdef finaldestdebug}
  965. insertllitem(asml,p1,p1.next,tai_comment.Create(
  966. strpnew('previous label inserted'))));
  967. {$endif finaldestdebug}
  968. current_asmdata.getjumplabel(l);
  969. insertllitem(p1,p1.next,tai_label.Create(l));
  970. tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
  971. hp.oper[0]^.ref^.symbol := l;
  972. l.increfs;
  973. { this won't work, since the new label isn't in the labeltable }
  974. { so it will fail the rangecheck. Labeltable should become a }
  975. { hashtable to support this: }
  976. { GetFinalDestination(asml, hp); }
  977. end
  978. else
  979. begin
  980. {$ifdef finaldestdebug}
  981. insertllitem(asml,p1,p1.next,tai_comment.Create(
  982. strpnew('next label reused'))));
  983. {$endif finaldestdebug}
  984. l.increfs;
  985. tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
  986. hp.oper[0]^.ref^.symbol := l;
  987. if not GetFinalDestination(hp,succ(level)) then
  988. exit;
  989. end;
  990. end;
  991. GetFinalDestination := true;
  992. end;
  993. procedure TAOptObj.PrePeepHoleOpts;
  994. begin
  995. end;
  996. procedure TAOptObj.PeepHoleOptPass1;
  997. var
  998. p,hp1,hp2 : tai;
  999. begin
  1000. p := BlockStart;
  1001. ClearUsedRegs;
  1002. while (p <> BlockEnd) Do
  1003. begin
  1004. UpdateUsedRegs(tai(p.next));
  1005. if PeepHoleOptPass1Cpu(p) then
  1006. continue;
  1007. case p.Typ Of
  1008. ait_instruction:
  1009. begin
  1010. { Handle Jmp Optimizations }
  1011. if taicpu(p).is_jmp then
  1012. begin
  1013. { the following if-block removes all code between a jmp and the next label,
  1014. because it can never be executed
  1015. }
  1016. if (taicpu(p).opcode = aopt_uncondjmp) and
  1017. {$ifdef arm}
  1018. (taicpu(p).condition = C_None) and
  1019. {$endif arm}
  1020. (taicpu(p).oper[0]^.typ = top_ref) and
  1021. (assigned(taicpu(p).oper[0]^.ref^.symbol)) and
  1022. (taicpu(p).oper[0]^.ref^.symbol is TAsmLabel) then
  1023. begin
  1024. hp2:=p;
  1025. while GetNextInstruction(hp2, hp1) and
  1026. (hp1.typ <> ait_label) do
  1027. if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
  1028. begin
  1029. if (hp1.typ = ait_instruction) and
  1030. taicpu(hp1).is_jmp and
  1031. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1032. assigned(taicpu(hp1).oper[0]^.ref^.symbol) and
  1033. (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) then
  1034. TAsmLabel(taicpu(hp1).oper[0]^.ref^.symbol).decrefs;
  1035. { don't kill start/end of assembler block,
  1036. no-line-info-start/end etc }
  1037. if hp1.typ<>ait_marker then
  1038. begin
  1039. asml.remove(hp1);
  1040. hp1.free;
  1041. end
  1042. else
  1043. hp2:=hp1;
  1044. end
  1045. else break;
  1046. end;
  1047. { remove jumps to a label coming right after them }
  1048. if GetNextInstruction(p, hp1) then
  1049. begin
  1050. if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
  1051. { TODO: FIXME removing the first instruction fails}
  1052. (p<>blockstart) then
  1053. begin
  1054. hp2:=tai(hp1.next);
  1055. asml.remove(p);
  1056. tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
  1057. p.free;
  1058. p:=hp2;
  1059. continue;
  1060. end
  1061. else
  1062. begin
  1063. if hp1.typ = ait_label then
  1064. SkipLabels(hp1,hp1);
  1065. if (tai(hp1).typ=ait_instruction) and
  1066. (taicpu(hp1).opcode=aopt_uncondjmp) and
  1067. {$ifdef arm}
  1068. (taicpu(hp1).condition=C_None) and
  1069. {$endif arm}
  1070. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1071. (assigned(taicpu(hp1).oper[0]^.ref^.symbol)) and
  1072. (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
  1073. GetNextInstruction(hp1, hp2) and
  1074. FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
  1075. begin
  1076. if (taicpu(p).opcode=aopt_condjmp)
  1077. {$ifdef arm}
  1078. and (taicpu(p).condition<>C_None)
  1079. {$endif arm}
  1080. then
  1081. begin
  1082. taicpu(p).condition:=inverse_cond(taicpu(p).condition);
  1083. tai_label(hp2).labsym.decrefs;
  1084. taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
  1085. { when freeing hp1, the reference count
  1086. isn't decreased, so don't increase
  1087. taicpu(p).oper[0]^.ref^.symbol.increfs;
  1088. }
  1089. {$ifdef SPARC}
  1090. hp2:=tai(hp1.next);
  1091. asml.remove(hp2);
  1092. hp2.free;
  1093. {$endif SPARC}
  1094. asml.remove(hp1);
  1095. hp1.free;
  1096. GetFinalDestination(taicpu(p),0);
  1097. end
  1098. else
  1099. begin
  1100. GetFinalDestination(taicpu(p),0);
  1101. p:=tai(p.next);
  1102. continue;
  1103. end;
  1104. end
  1105. else
  1106. GetFinalDestination(taicpu(p),0);
  1107. end;
  1108. end;
  1109. end
  1110. else
  1111. { All other optimizes }
  1112. begin
  1113. end; { if is_jmp }
  1114. end;
  1115. end;
  1116. UpdateUsedRegs(p);
  1117. p:=tai(p.next);
  1118. end;
  1119. end;
  1120. procedure TAOptObj.PeepHoleOptPass2;
  1121. begin
  1122. end;
  1123. procedure TAOptObj.PostPeepHoleOpts;
  1124. var
  1125. p: tai;
  1126. begin
  1127. p := BlockStart;
  1128. ClearUsedRegs;
  1129. while (p <> BlockEnd) Do
  1130. begin
  1131. UpdateUsedRegs(tai(p.next));
  1132. if PostPeepHoleOptsCpu(p) then
  1133. continue;
  1134. UpdateUsedRegs(p);
  1135. p:=tai(p.next);
  1136. end;
  1137. end;
  1138. function TAOptObj.PeepHoleOptPass1Cpu(var p: tai): boolean;
  1139. begin
  1140. result := false;
  1141. end;
  1142. function TAOptObj.PostPeepHoleOptsCpu(var p: tai): boolean;
  1143. begin
  1144. result := false;
  1145. end;
  1146. End.