daopt386.pas 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Jonas Maebe, member of the Freepascal
  4. development team
  5. This unit contains the data flow analyzer and several helper procedures
  6. and functions.
  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 DAOpt386;
  21. {$i defines.inc}
  22. Interface
  23. Uses
  24. GlobType,
  25. CObjects,Aasm,
  26. cpubase,cpuasm;
  27. {******************************* Constants *******************************}
  28. Const
  29. {Possible register content types}
  30. con_Unknown = 0;
  31. con_ref = 1;
  32. con_const = 2;
  33. { The contents aren't usable anymore for CSE, but they may still be }
  34. { usefull for detecting whether the result of a load is actually used }
  35. con_invalid = 3;
  36. { the reverse of the above (in case a (conditional) jump is encountered): }
  37. { CSE is still possible, but the original instruction can't be removed }
  38. con_noRemoveRef = 4;
  39. { same, but for constants }
  40. con_noRemoveConst = 5;
  41. {********************************* Types *********************************}
  42. type
  43. TRegArray = Array[R_EAX..R_BL] of TRegister;
  44. TRegSet = Set of R_EAX..R_BL;
  45. TRegInfo = Record
  46. NewRegsEncountered, OldRegsEncountered: TRegSet;
  47. RegsLoadedForRef: TRegSet;
  48. regsStillUsedAfterSeq: TRegSet;
  49. lastReload: array[R_EAX..R_EDI] of pai;
  50. New2OldReg: TRegArray;
  51. End;
  52. {possible actions on an operand: read, write or modify (= read & write)}
  53. TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
  54. {the possible states of a flag}
  55. TFlagContents = (F_Unknown, F_NotSet, F_Set);
  56. TContent = Packed Record
  57. {start and end of block instructions that defines the
  58. content of this register.}
  59. StartMod: pai;
  60. {how many instructions starting with StarMod does the block consist of}
  61. NrOfMods: Byte;
  62. {the type of the content of the register: unknown, memory, constant}
  63. Typ: Byte;
  64. case byte of
  65. {starts at 0, gets increased everytime the register is written to}
  66. 1: (WState: Byte;
  67. {starts at 0, gets increased everytime the register is read from}
  68. RState: Byte);
  69. { to compare both states in one operation }
  70. 2: (state: word);
  71. End;
  72. {Contents of the integer registers}
  73. TRegContent = Array[R_EAX..R_EDI] Of TContent;
  74. {contents of the FPU registers}
  75. TRegFPUContent = Array[R_ST..R_ST7] Of TContent;
  76. {$ifdef tempOpts}
  77. { linked list which allows searching/deleting based on value, no extra frills}
  78. PSearchLinkedListItem = ^TSearchLinkedListItem;
  79. TSearchLinkedListItem = object(TLinkedList_Item)
  80. constructor init;
  81. function equals(p: PSearchLinkedListItem): boolean; virtual;
  82. end;
  83. PSearchDoubleIntItem = ^TSearchDoubleInttem;
  84. TSearchDoubleIntItem = object(TLinkedList_Item)
  85. constructor init(_int1,_int2: longint);
  86. function equals(p: PSearchLinkedListItem): boolean; virtual;
  87. private
  88. int1, int2: longint;
  89. end;
  90. PSearchLinkedList = ^TSearchLinkedList;
  91. TSearchLinkedList = object(TLinkedList)
  92. function searchByValue(p: PSearchLinkedListItem): boolean;
  93. procedure removeByValue(p: PSearchLinkedListItem);
  94. end;
  95. {$endif tempOpts}
  96. {information record with the contents of every register. Every Pai object
  97. gets one of these assigned: a pointer to it is stored in the OptInfo field}
  98. TPaiProp = Record
  99. Regs: TRegContent;
  100. { FPURegs: TRegFPUContent;} {currently not yet used}
  101. { allocated Registers }
  102. UsedRegs: TRegSet;
  103. { status of the direction flag }
  104. DirFlag: TFlagContents;
  105. {$ifdef tempOpts}
  106. { currently used temps }
  107. tempAllocs: PSearchLinkedList;
  108. {$endif tempOpts}
  109. { can this instruction be removed? }
  110. CanBeRemoved: Boolean;
  111. End;
  112. PPaiProp = ^TPaiProp;
  113. TPaiPropBlock = Array[1..250000] Of TPaiProp;
  114. PPaiPropBlock = ^TPaiPropBlock;
  115. TInstrSinceLastMod = Array[R_EAX..R_EDI] Of Byte;
  116. TLabelTableItem = Record
  117. PaiObj: Pai;
  118. {$IfDef JumpAnal}
  119. InstrNr: Longint;
  120. RefsFound: Word;
  121. JmpsProcessed: Word
  122. {$EndIf JumpAnal}
  123. End;
  124. TLabelTable = Array[0..2500000] Of TLabelTableItem;
  125. PLabelTable = ^TLabelTable;
  126. {*********************** Procedures and Functions ************************}
  127. Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
  128. Function Reg32(Reg: TRegister): TRegister;
  129. Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
  130. Function RefsEqual(Const R1, R2: TReference): Boolean;
  131. Function IsGP32Reg(Reg: TRegister): Boolean;
  132. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  133. function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
  134. function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
  135. function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
  136. function RegInOp(Reg: TRegister; const o:toper): Boolean;
  137. function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
  138. reg: tregister; const c: tcontent): boolean;
  139. function writeToRegDestroysContents(destReg: tregister; reg: tregister;
  140. const c: tcontent): boolean;
  141. function writeDestroysContents(const op: toper; reg: tregister;
  142. const c: tcontent): boolean;
  143. Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
  144. Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
  145. Procedure SkipHead(var P: Pai);
  146. function labelCanBeSkipped(p: pai_label): boolean;
  147. Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
  148. Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
  149. hp: pai): boolean;
  150. Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
  151. Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
  152. Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
  153. Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
  154. Function OpsEqual(const o1,o2:toper): Boolean;
  155. Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
  156. Function DFAPass2(
  157. {$ifdef statedebug}
  158. AsmL: PAasmOutPut;
  159. {$endif statedebug}
  160. BlockStart, BlockEnd: Pai): Boolean;
  161. Procedure ShutDownDFA;
  162. Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean;
  163. Procedure IncState(Var S: Byte; amount: longint);
  164. {******************************* Variables *******************************}
  165. Var
  166. {the amount of PaiObjects in the current assembler list}
  167. NrOfPaiObjs: Longint;
  168. {Array which holds all TPaiProps}
  169. PaiPropBlock: PPaiPropBlock;
  170. LoLab, HiLab, LabDif: Longint;
  171. LTable: PLabelTable;
  172. {*********************** End of Interface section ************************}
  173. Implementation
  174. Uses
  175. globals, systems, verbose, hcodegen, symconst, tgeni386;
  176. Type
  177. TRefCompare = function(const r1, r2: TReference): Boolean;
  178. Var
  179. {How many instructions are between the current instruction and the last one
  180. that modified the register}
  181. NrOfInstrSinceLastMod: TInstrSinceLastMod;
  182. {$ifdef tempOpts}
  183. constructor TSearchLinkedListItem.init;
  184. begin
  185. end;
  186. function TSearchLinkedListItem.equals(p: PSearchLinkedListItem): boolean;
  187. begin
  188. equals := false;
  189. end;
  190. constructor TSearchDoubleIntItem.init(_int1,_int2: longint);
  191. begin
  192. int1 := _int1;
  193. int2 := _int2;
  194. end;
  195. function TSearchDoubleIntItem.equals(p: PSearchLinkedListItem): boolean;
  196. begin
  197. equals := (TSearchDoubleIntItem(p).int1 = int1) and
  198. (TSearchDoubleIntItem(p).int2 = int2);
  199. end;
  200. function TSearchLinkedList.searchByValue(p: PSearchLinkedListItem): boolean;
  201. var temp: PSearchLinkedListItem;
  202. begin
  203. temp := first;
  204. while (temp <> last^.next) and
  205. not(temp^.equals(p)) do
  206. temp := temp^.next;
  207. searchByValue := temp <> last^.next;
  208. end;
  209. procedure TSearchLinkedList.removeByValue(p: PSearchLinkedListItem);
  210. begin
  211. temp := first;
  212. while (temp <> last^.next) and
  213. not(temp^.equals(p)) do
  214. temp := temp^.next;
  215. if temp <> last^.next then
  216. begin
  217. remove(temp);
  218. dispose(temp,done);
  219. end;
  220. end;
  221. Procedure updateTempAllocs(Var UsedRegs: TRegSet; p: Pai);
  222. {updates UsedRegs with the RegAlloc Information coming after P}
  223. Begin
  224. Repeat
  225. While Assigned(p) And
  226. ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
  227. ((p^.typ = ait_label) And
  228. labelCanBeSkipped(pai_label(current)))) Do
  229. p := Pai(p^.next);
  230. While Assigned(p) And
  231. (p^.typ=ait_RegAlloc) Do
  232. Begin
  233. if pairegalloc(p)^.allocation then
  234. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  235. else
  236. UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  237. p := pai(p^.next);
  238. End;
  239. Until Not(Assigned(p)) Or
  240. (Not(p^.typ in SkipInstr) And
  241. Not((p^.typ = ait_label) And
  242. labelCanBeSkipped(pai_label(current))));
  243. End;
  244. {$endif tempOpts}
  245. {************************ Create the Label table ************************}
  246. Function FindLoHiLabels(Var LowLabel, HighLabel, LabelDif: Longint; BlockStart: Pai): Pai;
  247. {Walks through the paasmlist to find the lowest and highest label number}
  248. Var LabelFound: Boolean;
  249. P, lastP: Pai;
  250. Begin
  251. LabelFound := False;
  252. LowLabel := MaxLongint;
  253. HighLabel := 0;
  254. P := BlockStart;
  255. lastP := p;
  256. While Assigned(P) Do
  257. Begin
  258. If (Pai(p)^.typ = ait_label) Then
  259. If not labelCanBeSkipped(pai_label(p))
  260. Then
  261. Begin
  262. LabelFound := True;
  263. If (Pai_Label(p)^.l^.labelnr < LowLabel) Then
  264. LowLabel := Pai_Label(p)^.l^.labelnr;
  265. If (Pai_Label(p)^.l^.labelnr > HighLabel) Then
  266. HighLabel := Pai_Label(p)^.l^.labelnr;
  267. End;
  268. lastP := p;
  269. GetNextInstruction(p, p);
  270. End;
  271. if (lastP^.typ = ait_marker) and
  272. (pai_marker(lastP)^.kind = asmBlockStart) then
  273. FindLoHiLabels := lastP
  274. else FindLoHiLabels := nil;
  275. If LabelFound
  276. Then LabelDif := HighLabel+1-LowLabel
  277. Else LabelDif := 0;
  278. End;
  279. Function FindRegAlloc(Reg: TRegister; StartPai: Pai; alloc: boolean): Boolean;
  280. { Returns true if a ait_alloc object for Reg is found in the block of Pai's }
  281. { starting with StartPai and ending with the next "real" instruction }
  282. Begin
  283. FindRegAlloc := false;
  284. Repeat
  285. While Assigned(StartPai) And
  286. ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or
  287. ((StartPai^.typ = ait_label) and
  288. labelCanBeSkipped(pai_label(startPai)))) Do
  289. StartPai := Pai(StartPai^.Next);
  290. If Assigned(StartPai) and
  291. (StartPai^.typ = ait_regAlloc) then
  292. begin
  293. if (PairegAlloc(StartPai)^.allocation = alloc) and
  294. (PairegAlloc(StartPai)^.Reg = Reg) then
  295. begin
  296. FindRegAlloc:=true;
  297. break;
  298. end;
  299. StartPai := Pai(StartPai^.Next);
  300. end
  301. else
  302. break;
  303. Until false;
  304. End;
  305. Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
  306. Procedure DoRemoveLastDeallocForFuncRes(asmL: PAasmOutput; reg: TRegister);
  307. var
  308. hp2: pai;
  309. begin
  310. hp2 := p;
  311. repeat
  312. hp2 := pai(hp2^.previous);
  313. if assigned(hp2) and
  314. (hp2^.typ = ait_regalloc) and
  315. not(pairegalloc(hp2)^.allocation) and
  316. (pairegalloc(hp2)^.reg = reg) then
  317. begin
  318. asml^.remove(hp2);
  319. dispose(hp2,done);
  320. break;
  321. end;
  322. until not(assigned(hp2)) or
  323. regInInstruction(reg,hp2);
  324. end;
  325. begin
  326. if assigned(procinfo^.returntype.def) then
  327. case procinfo^.returntype.def^.deftype of
  328. arraydef,recorddef,pointerdef,
  329. stringdef,enumdef,procdef,objectdef,errordef,
  330. filedef,setdef,procvardef,
  331. classrefdef,forwarddef:
  332. DoRemoveLastDeallocForFuncRes(asmL,R_EAX);
  333. orddef:
  334. if procinfo^.returntype.def^.size <> 0 then
  335. begin
  336. DoRemoveLastDeallocForFuncRes(asmL,R_EAX);
  337. { for int64/qword }
  338. if procinfo^.returntype.def^.size = 8 then
  339. DoRemoveLastDeallocForFuncRes(asmL,R_EDX);
  340. end;
  341. end;
  342. end;
  343. procedure getNoDeallocRegs(var regs: TRegSet);
  344. var regCounter: TRegister;
  345. begin
  346. regs := [];
  347. if assigned(procinfo^.returntype.def) then
  348. case procinfo^.returntype.def^.deftype of
  349. arraydef,recorddef,pointerdef,
  350. stringdef,enumdef,procdef,objectdef,errordef,
  351. filedef,setdef,procvardef,
  352. classrefdef,forwarddef:
  353. regs := [R_EAX];
  354. orddef:
  355. if procinfo^.returntype.def^.size <> 0 then
  356. begin
  357. regs := [R_EAX];
  358. { for int64/qword }
  359. if procinfo^.returntype.def^.size = 8 then
  360. regs := regs + [R_EDX];
  361. end;
  362. end;
  363. for regCounter := R_EAX to R_EBX do
  364. if not(regCounter in usableregs) then
  365. regs := regs + [regCounter];
  366. end;
  367. Procedure AddRegDeallocFor(asmL: paasmOutput; reg: TRegister; p: pai);
  368. var hp1: pai;
  369. funcResRegs: TRegset;
  370. funcResReg: boolean;
  371. begin
  372. if not(reg in usableregs) then
  373. exit;
  374. getNoDeallocRegs(funcResRegs);
  375. funcResRegs := funcResRegs - usableregs;
  376. funcResReg := reg in funcResRegs;
  377. hp1 := p;
  378. while not(funcResReg and
  379. (p^.typ = ait_instruction) and
  380. (paicpu(p)^.opcode = A_JMP) and
  381. (pasmlabel(paicpu(p)^.oper[0].sym) = aktexit2label)) and
  382. getLastInstruction(p, p) And
  383. not(regInInstruction(reg, p)) Do
  384. hp1 := p;
  385. { don't insert a dealloc for registers which contain the function result }
  386. { if they are followed by a jump to the exit label (for exit(...)) }
  387. if not(funcResReg) or
  388. not((hp1^.typ = ait_instruction) and
  389. (paicpu(hp1)^.opcode = A_JMP) and
  390. (pasmlabel(paicpu(hp1)^.oper[0].sym) = aktexit2label)) then
  391. begin
  392. p := new(paiRegAlloc, deAlloc(reg));
  393. insertLLItem(AsmL, hp1^.previous, hp1, p);
  394. end;
  395. end;
  396. Procedure BuildLabelTableAndFixRegAlloc(asmL: PAasmOutput; Var LabelTable: PLabelTable; LowLabel: Longint;
  397. Var LabelDif: Longint; BlockStart, BlockEnd: Pai);
  398. {Builds a table with the locations of the labels in the paasmoutput.
  399. Also fixes some RegDeallocs like "# %eax released; push (%eax)"}
  400. Var p, hp1, hp2, lastP: Pai;
  401. regCounter: TRegister;
  402. UsedRegs, noDeallocRegs: TRegSet;
  403. Begin
  404. UsedRegs := [];
  405. If (LabelDif <> 0) Then
  406. Begin
  407. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  408. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  409. End;
  410. p := BlockStart;
  411. lastP := p;
  412. While (P <> BlockEnd) Do
  413. Begin
  414. Case p^.typ Of
  415. ait_Label:
  416. If not labelCanBeSkipped(pai_label(p)) Then
  417. LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
  418. ait_regAlloc:
  419. { ESI and EDI are (de)allocated manually, don't mess with them }
  420. if not(paiRegAlloc(p)^.Reg in [R_EDI,R_ESI]) then
  421. begin
  422. if PairegAlloc(p)^.Allocation then
  423. Begin
  424. If Not(paiRegAlloc(p)^.Reg in UsedRegs) Then
  425. UsedRegs := UsedRegs + [paiRegAlloc(p)^.Reg]
  426. Else
  427. addRegDeallocFor(asmL, paiRegAlloc(p)^.reg, p);
  428. End
  429. else
  430. begin
  431. UsedRegs := UsedRegs - [paiRegAlloc(p)^.Reg];
  432. hp1 := p;
  433. hp2 := nil;
  434. While Not(FindRegAlloc(paiRegAlloc(p)^.Reg, Pai(hp1^.Next),true)) And
  435. GetNextInstruction(hp1, hp1) And
  436. RegInInstruction(paiRegAlloc(p)^.Reg, hp1) Do
  437. hp2 := hp1;
  438. If hp2 <> nil Then
  439. Begin
  440. hp1 := Pai(p^.previous);
  441. AsmL^.Remove(p);
  442. InsertLLItem(AsmL, hp2, Pai(hp2^.Next), p);
  443. p := hp1;
  444. end;
  445. end;
  446. end;
  447. end;
  448. repeat
  449. lastP := p;
  450. P := Pai(P^.Next);
  451. until not(Assigned(p)) or
  452. not(p^.typ in (SkipInstr - [ait_regalloc]));
  453. End;
  454. { don't add deallocation for function result variable or for regvars}
  455. getNoDeallocRegs(noDeallocRegs);
  456. usedRegs := usedRegs - noDeallocRegs;
  457. for regCounter := R_EAX to R_EDI do
  458. if regCounter in usedRegs then
  459. addRegDeallocFor(asmL,regCounter,lastP);
  460. End;
  461. {************************ Search the Label table ************************}
  462. Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean;
  463. {searches for the specified label starting from hp as long as the
  464. encountered instructions are labels, to be able to optimize constructs like
  465. jne l2 jmp l2
  466. jmp l3 and l1:
  467. l1: l2:
  468. l2:}
  469. Var TempP: Pai;
  470. Begin
  471. TempP := hp;
  472. While Assigned(TempP) and
  473. (TempP^.typ In SkipInstr + [ait_label,ait_align]) Do
  474. If (TempP^.typ <> ait_Label) Or
  475. (pai_label(TempP)^.l <> L)
  476. Then GetNextInstruction(TempP, TempP)
  477. Else
  478. Begin
  479. hp := TempP;
  480. FindLabel := True;
  481. exit
  482. End;
  483. FindLabel := False;
  484. End;
  485. {************************ Some general functions ************************}
  486. Function TCh2Reg(Ch: TInsChange): TRegister;
  487. {converts a TChange variable to a TRegister}
  488. Begin
  489. If (Ch <= Ch_REDI) Then
  490. TCh2Reg := TRegister(Byte(Ch))
  491. Else
  492. If (Ch <= Ch_WEDI) Then
  493. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_REDI))
  494. Else
  495. If (Ch <= Ch_RWEDI) Then
  496. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_WEDI))
  497. Else
  498. If (Ch <= Ch_MEDI) Then
  499. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_RWEDI))
  500. Else InternalError($db)
  501. End;
  502. Function Reg32(Reg: TRegister): TRegister;
  503. {Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
  504. Begin
  505. Reg32 := Reg;
  506. If (Reg >= R_AX)
  507. Then
  508. If (Reg <= R_DI)
  509. Then Reg32 := Reg16ToReg32(Reg)
  510. Else
  511. If (Reg <= R_BL)
  512. Then Reg32 := Reg8toReg32(Reg);
  513. End;
  514. { inserts new_one between prev and foll }
  515. Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
  516. Begin
  517. If Assigned(prev) Then
  518. If Assigned(foll) Then
  519. Begin
  520. If Assigned(new_one) Then
  521. Begin
  522. new_one^.previous := prev;
  523. new_one^.next := foll;
  524. prev^.next := new_one;
  525. foll^.previous := new_one;
  526. Pai(new_one)^.fileinfo := Pai(foll)^.fileinfo;
  527. End;
  528. End
  529. Else AsmL^.Concat(new_one)
  530. Else If Assigned(Foll) Then AsmL^.Insert(new_one)
  531. End;
  532. {********************* Compare parts of Pai objects *********************}
  533. Function RegsSameSize(Reg1, Reg2: TRegister): Boolean;
  534. {returns true if Reg1 and Reg2 are of the same size (so if they're both
  535. 8bit, 16bit or 32bit)}
  536. Begin
  537. If (Reg1 <= R_EDI)
  538. Then RegsSameSize := (Reg2 <= R_EDI)
  539. Else
  540. If (Reg1 <= R_DI)
  541. Then RegsSameSize := (Reg2 in [R_AX..R_DI])
  542. Else
  543. If (Reg1 <= R_BL)
  544. Then RegsSameSize := (Reg2 in [R_AL..R_BL])
  545. Else RegsSameSize := False
  546. End;
  547. Procedure AddReg2RegInfo(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo);
  548. {updates the ???RegsEncountered and ???2???Reg fields of RegInfo. Assumes that
  549. OldReg and NewReg have the same size (has to be chcked in advance with
  550. RegsSameSize) and that neither equals R_NO}
  551. Begin
  552. With RegInfo Do
  553. Begin
  554. NewRegsEncountered := NewRegsEncountered + [NewReg];
  555. OldRegsEncountered := OldRegsEncountered + [OldReg];
  556. New2OldReg[NewReg] := OldReg;
  557. Case OldReg Of
  558. R_EAX..R_EDI:
  559. Begin
  560. NewRegsEncountered := NewRegsEncountered + [Reg32toReg16(NewReg)];
  561. OldRegsEncountered := OldRegsEncountered + [Reg32toReg16(OldReg)];
  562. New2OldReg[Reg32toReg16(NewReg)] := Reg32toReg16(OldReg);
  563. If (NewReg in [R_EAX..R_EBX]) And
  564. (OldReg in [R_EAX..R_EBX]) Then
  565. Begin
  566. NewRegsEncountered := NewRegsEncountered + [Reg32toReg8(NewReg)];
  567. OldRegsEncountered := OldRegsEncountered + [Reg32toReg8(OldReg)];
  568. New2OldReg[Reg32toReg8(NewReg)] := Reg32toReg8(OldReg);
  569. End;
  570. End;
  571. R_AX..R_DI:
  572. Begin
  573. NewRegsEncountered := NewRegsEncountered + [Reg16toReg32(NewReg)];
  574. OldRegsEncountered := OldRegsEncountered + [Reg16toReg32(OldReg)];
  575. New2OldReg[Reg16toReg32(NewReg)] := Reg16toReg32(OldReg);
  576. If (NewReg in [R_AX..R_BX]) And
  577. (OldReg in [R_AX..R_BX]) Then
  578. Begin
  579. NewRegsEncountered := NewRegsEncountered + [Reg16toReg8(NewReg)];
  580. OldRegsEncountered := OldRegsEncountered + [Reg16toReg8(OldReg)];
  581. New2OldReg[Reg16toReg8(NewReg)] := Reg16toReg8(OldReg);
  582. End;
  583. End;
  584. R_AL..R_BL:
  585. Begin
  586. NewRegsEncountered := NewRegsEncountered + [Reg8toReg32(NewReg)]
  587. + [Reg8toReg16(NewReg)];
  588. OldRegsEncountered := OldRegsEncountered + [Reg8toReg32(OldReg)]
  589. + [Reg8toReg16(OldReg)];
  590. New2OldReg[Reg8toReg32(NewReg)] := Reg8toReg32(OldReg);
  591. End;
  592. End;
  593. End;
  594. End;
  595. Procedure AddOp2RegInfo(const o:Toper; Var RegInfo: TRegInfo);
  596. Begin
  597. Case o.typ Of
  598. Top_Reg:
  599. If (o.reg <> R_NO) Then
  600. AddReg2RegInfo(o.reg, o.reg, RegInfo);
  601. Top_Ref:
  602. Begin
  603. If o.ref^.base <> R_NO Then
  604. AddReg2RegInfo(o.ref^.base, o.ref^.base, RegInfo);
  605. If o.ref^.index <> R_NO Then
  606. AddReg2RegInfo(o.ref^.index, o.ref^.index, RegInfo);
  607. End;
  608. End;
  609. End;
  610. Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OPAct: TOpAction): Boolean;
  611. Begin
  612. If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
  613. If RegsSameSize(OldReg, NewReg) Then
  614. With RegInfo Do
  615. {here we always check for the 32 bit component, because it is possible that
  616. the 8 bit component has not been set, event though NewReg already has been
  617. processed. This happens if it has been compared with a register that doesn't
  618. have an 8 bit component (such as EDI). In that case the 8 bit component is
  619. still set to R_NO and the comparison in the Else-part will fail}
  620. If (Reg32(OldReg) in OldRegsEncountered) Then
  621. If (Reg32(NewReg) in NewRegsEncountered) Then
  622. RegsEquivalent := (OldReg = New2OldReg[NewReg])
  623. { If we haven't encountered the new register yet, but we have encountered the
  624. old one already, the new one can only be correct if it's being written to
  625. (and consequently the old one is also being written to), otherwise
  626. movl -8(%ebp), %eax and movl -8(%ebp), %eax
  627. movl (%eax), %eax movl (%edx), %edx
  628. are considered equivalent}
  629. Else
  630. If (OpAct = OpAct_Write) Then
  631. Begin
  632. AddReg2RegInfo(OldReg, NewReg, RegInfo);
  633. RegsEquivalent := True
  634. End
  635. Else Regsequivalent := False
  636. Else
  637. If Not(Reg32(NewReg) in NewRegsEncountered) and
  638. ((OpAct = OpAct_Write) or
  639. ((newReg = oldReg) and
  640. not(newReg in usableregs + [R_EDI]))) Then
  641. Begin
  642. AddReg2RegInfo(OldReg, NewReg, RegInfo);
  643. RegsEquivalent := True
  644. End
  645. Else RegsEquivalent := False
  646. Else RegsEquivalent := False
  647. Else RegsEquivalent := OldReg = NewReg
  648. End;
  649. Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
  650. Begin
  651. If R1.is_immediate Then
  652. RefsEquivalent := R2.is_immediate and (R1.Offset = R2.Offset)
  653. Else
  654. RefsEquivalent := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
  655. RegsEquivalent(R1.Base, R2.Base, RegInfo, OpAct) And
  656. RegsEquivalent(R1.Index, R2.Index, RegInfo, OpAct) And
  657. (R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor) And
  658. (R1.Symbol = R2.Symbol);
  659. End;
  660. Function RefsEqual(Const R1, R2: TReference): Boolean;
  661. Begin
  662. If R1.is_immediate Then
  663. RefsEqual := R2.is_immediate and (R1.Offset = R2.Offset)
  664. Else
  665. RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
  666. (R1.Segment = R2.Segment) And (R1.Base = R2.Base) And
  667. (R1.Index = R2.Index) And (R1.ScaleFactor = R2.ScaleFactor) And
  668. (R1.Symbol=R2.Symbol);
  669. End;
  670. Function IsGP32Reg(Reg: TRegister): Boolean;
  671. {Checks if the register is a 32 bit general purpose register}
  672. Begin
  673. If (Reg >= R_EAX) and (Reg <= R_EBX)
  674. Then IsGP32Reg := True
  675. Else IsGP32reg := False
  676. End;
  677. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  678. Begin {checks whether Ref contains a reference to Reg}
  679. Reg := Reg32(Reg);
  680. RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
  681. End;
  682. function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
  683. var p: paicpu;
  684. opCount: byte;
  685. begin
  686. RegReadByInstruction := false;
  687. reg := reg32(reg);
  688. p := paicpu(hp);
  689. if hp^.typ <> ait_instruction then
  690. exit;
  691. case p^.opcode of
  692. A_IMUL:
  693. case p^.ops of
  694. 1: regReadByInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
  695. 2,3:
  696. regReadByInstruction := regInOp(reg,p^.oper[0]) or
  697. regInOp(reg,p^.oper[1]);
  698. end;
  699. A_IDIV,A_DIV,A_MUL:
  700. begin
  701. regReadByInstruction :=
  702. regInOp(reg,p^.oper[0]) or (reg = R_EAX);
  703. end;
  704. else
  705. begin
  706. for opCount := 0 to 2 do
  707. if (p^.oper[opCount].typ = top_ref) and
  708. RegInRef(reg,p^.oper[opCount].ref^) then
  709. begin
  710. RegReadByInstruction := true;
  711. exit
  712. end;
  713. for opCount := 1 to MaxCh do
  714. case InsProp[p^.opcode].Ch[opCount] of
  715. Ch_REAX..CH_REDI,CH_RWEAX..Ch_MEDI:
  716. if reg = TCh2Reg(InsProp[p^.opcode].Ch[opCount]) then
  717. begin
  718. RegReadByInstruction := true;
  719. exit
  720. end;
  721. Ch_RWOp1,Ch_ROp1,Ch_MOp1:
  722. if (p^.oper[0].typ = top_reg) and
  723. (reg32(p^.oper[0].reg) = reg) then
  724. begin
  725. RegReadByInstruction := true;
  726. exit
  727. end;
  728. Ch_RWOp2,Ch_ROp2,Ch_MOp2:
  729. if (p^.oper[1].typ = top_reg) and
  730. (reg32(p^.oper[1].reg) = reg) then
  731. begin
  732. RegReadByInstruction := true;
  733. exit
  734. end;
  735. Ch_RWOp3,Ch_ROp3,Ch_MOp3:
  736. if (p^.oper[2].typ = top_reg) and
  737. (reg32(p^.oper[2].reg) = reg) then
  738. begin
  739. RegReadByInstruction := true;
  740. exit
  741. end;
  742. end;
  743. end;
  744. end;
  745. end;
  746. function regInInstruction(Reg: TRegister; p1: Pai): Boolean;
  747. { Checks if Reg is used by the instruction p1 }
  748. { Difference with "regReadBysinstruction() or regModifiedByInstruction()": }
  749. { this one ignores CH_ALL opcodes, while regModifiedByInstruction doesn't }
  750. var p: paicpu;
  751. opCount: byte;
  752. begin
  753. reg := reg32(reg);
  754. regInInstruction := false;
  755. p := paicpu(p1);
  756. if p1^.typ <> ait_instruction then
  757. exit;
  758. case p^.opcode of
  759. A_IMUL:
  760. case p^.ops of
  761. 1: regInInstruction := (reg = R_EAX) or reginOp(reg,p^.oper[0]);
  762. 2,3:
  763. regInInstruction := regInOp(reg,p^.oper[0]) or
  764. regInOp(reg,p^.oper[1]) or regInOp(reg,p^.oper[2]);
  765. end;
  766. A_IDIV,A_DIV,A_MUL:
  767. regInInstruction :=
  768. regInOp(reg,p^.oper[0]) or
  769. (reg = R_EAX) or (reg = R_EDX)
  770. else
  771. begin
  772. for opCount := 1 to MaxCh do
  773. case InsProp[p^.opcode].Ch[opCount] of
  774. CH_REAX..CH_MEDI:
  775. if tch2reg(InsProp[p^.opcode].Ch[opCount]) = reg then
  776. begin
  777. regInInstruction := true;
  778. exit;
  779. end;
  780. Ch_ROp1..Ch_MOp1:
  781. if regInOp(reg,p^.oper[0]) then
  782. begin
  783. regInInstruction := true;
  784. exit
  785. end;
  786. Ch_ROp2..Ch_MOp2:
  787. if regInOp(reg,p^.oper[1]) then
  788. begin
  789. regInInstruction := true;
  790. exit
  791. end;
  792. Ch_ROp3..Ch_MOp3:
  793. if regInOp(reg,p^.oper[2]) then
  794. begin
  795. regInInstruction := true;
  796. exit
  797. end;
  798. end;
  799. end;
  800. end;
  801. end;
  802. Function RegInOp(Reg: TRegister; const o:toper): Boolean;
  803. Begin
  804. RegInOp := False;
  805. reg := reg32(reg);
  806. Case o.typ Of
  807. top_reg: RegInOp := Reg = reg32(o.reg);
  808. top_ref: RegInOp := (Reg = o.ref^.Base) Or
  809. (Reg = o.ref^.Index);
  810. End;
  811. End;
  812. Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
  813. Var InstrProp: TInsProp;
  814. TmpResult: Boolean;
  815. Cnt: Byte;
  816. Begin
  817. TmpResult := False;
  818. Reg := Reg32(Reg);
  819. If (p1^.typ = ait_instruction) Then
  820. Case paicpu(p1)^.opcode of
  821. A_IMUL:
  822. With paicpu(p1)^ Do
  823. TmpResult :=
  824. ((ops = 1) and (reg in [R_EAX,R_EDX])) or
  825. ((ops = 2) and (Reg32(oper[1].reg) = reg)) or
  826. ((ops = 3) and (Reg32(oper[2].reg) = reg));
  827. A_DIV, A_IDIV, A_MUL:
  828. With paicpu(p1)^ Do
  829. TmpResult :=
  830. (Reg = R_EAX) or
  831. (Reg = R_EDX);
  832. Else
  833. Begin
  834. Cnt := 1;
  835. InstrProp := InsProp[paicpu(p1)^.OpCode];
  836. While (Cnt <= MaxCh) And
  837. (InstrProp.Ch[Cnt] <> Ch_None) And
  838. Not(TmpResult) Do
  839. Begin
  840. Case InstrProp.Ch[Cnt] Of
  841. Ch_WEAX..Ch_MEDI:
  842. TmpResult := Reg = TCh2Reg(InstrProp.Ch[Cnt]);
  843. Ch_RWOp1,Ch_WOp1,Ch_Mop1:
  844. TmpResult := (paicpu(p1)^.oper[0].typ = top_reg) and
  845. (Reg32(paicpu(p1)^.oper[0].reg) = reg);
  846. Ch_RWOp2,Ch_WOp2,Ch_Mop2:
  847. TmpResult := (paicpu(p1)^.oper[1].typ = top_reg) and
  848. (Reg32(paicpu(p1)^.oper[1].reg) = reg);
  849. Ch_RWOp3,Ch_WOp3,Ch_Mop3:
  850. TmpResult := (paicpu(p1)^.oper[2].typ = top_reg) and
  851. (Reg32(paicpu(p1)^.oper[2].reg) = reg);
  852. Ch_FPU: TmpResult := Reg in [R_ST..R_ST7,R_MM0..R_MM7];
  853. Ch_ALL: TmpResult := true;
  854. End;
  855. Inc(Cnt)
  856. End
  857. End
  858. End;
  859. RegModifiedByInstruction := TmpResult
  860. End;
  861. {********************* GetNext and GetLastInstruction *********************}
  862. Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
  863. { skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the }
  864. { next pai object in Next. Returns false if there isn't any }
  865. Begin
  866. Repeat
  867. If (Current^.typ = ait_marker) And
  868. (Pai_Marker(Current)^.Kind = AsmBlockStart) Then
  869. Begin
  870. GetNextInstruction := False;
  871. Next := Nil;
  872. Exit
  873. End;
  874. Current := Pai(Current^.Next);
  875. While Assigned(Current) And
  876. ((current^.typ In skipInstr) or
  877. ((current^.typ = ait_label) and
  878. labelCanBeSkipped(pai_label(current)))) do
  879. Current := Pai(Current^.Next);
  880. If Assigned(Current) And
  881. (Current^.typ = ait_Marker) And
  882. (Pai_Marker(Current)^.Kind = NoPropInfoStart) Then
  883. Begin
  884. While Assigned(Current) And
  885. ((Current^.typ <> ait_Marker) Or
  886. (Pai_Marker(Current)^.Kind <> NoPropInfoEnd)) Do
  887. Current := Pai(Current^.Next);
  888. End;
  889. Until Not(Assigned(Current)) Or
  890. (Current^.typ <> ait_Marker) Or
  891. (Pai_Marker(Current)^.Kind <> NoPropInfoEnd);
  892. Next := Current;
  893. If Assigned(Current) And
  894. Not((Current^.typ In SkipInstr) or
  895. ((Current^.typ = ait_label) And
  896. labelCanBeSkipped(pai_label(current))))
  897. Then
  898. GetNextInstruction :=
  899. not((current^.typ = ait_marker) and
  900. (pai_marker(current)^.kind = asmBlockStart))
  901. Else
  902. Begin
  903. GetNextInstruction := False;
  904. Next := nil;
  905. End;
  906. End;
  907. Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
  908. {skips the ait-types in SkipInstr puts the previous pai object in
  909. Last. Returns false if there isn't any}
  910. Begin
  911. Repeat
  912. Current := Pai(Current^.previous);
  913. While Assigned(Current) And
  914. (((Current^.typ = ait_Marker) And
  915. Not(Pai_Marker(Current)^.Kind in [AsmBlockEnd,NoPropInfoEnd])) or
  916. (Current^.typ In SkipInstr) or
  917. ((Current^.typ = ait_label) And
  918. labelCanBeSkipped(pai_label(current)))) Do
  919. Current := Pai(Current^.previous);
  920. If Assigned(Current) And
  921. (Current^.typ = ait_Marker) And
  922. (Pai_Marker(Current)^.Kind = NoPropInfoEnd) Then
  923. Begin
  924. While Assigned(Current) And
  925. ((Current^.typ <> ait_Marker) Or
  926. (Pai_Marker(Current)^.Kind <> NoPropInfoStart)) Do
  927. Current := Pai(Current^.previous);
  928. End;
  929. Until Not(Assigned(Current)) Or
  930. (Current^.typ <> ait_Marker) Or
  931. (Pai_Marker(Current)^.Kind <> NoPropInfoStart);
  932. If Not(Assigned(Current)) or
  933. (Current^.typ In SkipInstr) or
  934. ((Current^.typ = ait_label) And
  935. labelCanBeSkipped(pai_label(current))) or
  936. ((Current^.typ = ait_Marker) And
  937. (Pai_Marker(Current)^.Kind = AsmBlockEnd))
  938. Then
  939. Begin
  940. Last := nil;
  941. GetLastInstruction := False
  942. End
  943. Else
  944. Begin
  945. Last := Current;
  946. GetLastInstruction := True;
  947. End;
  948. End;
  949. Procedure SkipHead(var P: Pai);
  950. Var OldP: Pai;
  951. Begin
  952. Repeat
  953. OldP := P;
  954. If (P^.typ in SkipInstr) Or
  955. ((P^.typ = ait_marker) And
  956. (Pai_Marker(P)^.Kind = AsmBlockEnd)) Then
  957. GetNextInstruction(P, P)
  958. Else If ((P^.Typ = Ait_Marker) And
  959. (Pai_Marker(P)^.Kind = NoPropInfoStart)) Then
  960. {a marker of the NoPropInfoStart can't be the first instruction of a
  961. paasmoutput list}
  962. GetNextInstruction(Pai(P^.Previous),P);
  963. Until P = OldP
  964. End;
  965. function labelCanBeSkipped(p: pai_label): boolean;
  966. begin
  967. labelCanBeSkipped := not(p^.l^.is_used) or p^.l^.is_addr;
  968. end;
  969. {******************* The Data Flow Analyzer functions ********************}
  970. function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
  971. hp: pai): boolean;
  972. { assumes reg is a 32bit register }
  973. var p: paicpu;
  974. begin
  975. p := paicpu(hp);
  976. regLoadedWithNewValue :=
  977. assigned(hp) and
  978. (hp^.typ = ait_instruction) and
  979. (((p^.opcode = A_MOV) or
  980. (p^.opcode = A_MOVZX) or
  981. (p^.opcode = A_MOVSX) or
  982. (p^.opcode = A_LEA)) and
  983. (p^.oper[1].typ = top_reg) and
  984. (Reg32(p^.oper[1].reg) = reg) and
  985. (canDependOnPrevValue or
  986. (p^.oper[0].typ <> top_ref) or
  987. not regInRef(reg,p^.oper[0].ref^)) or
  988. ((p^.opcode = A_POP) and
  989. (Reg32(p^.oper[0].reg) = reg)));
  990. end;
  991. Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
  992. {updates UsedRegs with the RegAlloc Information coming after P}
  993. Begin
  994. Repeat
  995. While Assigned(p) And
  996. ((p^.typ in (SkipInstr - [ait_RegAlloc])) or
  997. ((p^.typ = ait_label) And
  998. labelCanBeSkipped(pai_label(p)))) Do
  999. p := Pai(p^.next);
  1000. While Assigned(p) And
  1001. (p^.typ=ait_RegAlloc) Do
  1002. Begin
  1003. if pairegalloc(p)^.allocation then
  1004. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  1005. else
  1006. UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  1007. p := pai(p^.next);
  1008. End;
  1009. Until Not(Assigned(p)) Or
  1010. (Not(p^.typ in SkipInstr) And
  1011. Not((p^.typ = ait_label) And
  1012. labelCanBeSkipped(pai_label(p))));
  1013. End;
  1014. Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
  1015. { allocates register Reg between (and including) instructions p1 and p2 }
  1016. { the type of p1 and p2 must not be in SkipInstr }
  1017. var
  1018. hp: pai;
  1019. lastRemovedWasDealloc: boolean;
  1020. Begin
  1021. If not(reg in usableregs+[R_EDI,R_ESI]) or
  1022. not(assigned(p1)) Then
  1023. { this happens with registers which are loaded implicitely, outside the }
  1024. { current block (e.g. esi with self) }
  1025. exit;
  1026. lastRemovedWasDealloc := false;
  1027. {$ifdef allocregdebug}
  1028. hp := new(pai_asm_comment,init(strpnew('allocating '+att_reg2str[reg]+
  1029. ' from here...')));
  1030. insertllitem(asml,p1^.previous,p1,hp);
  1031. hp := new(pai_asm_comment,init(strpnew('allocated '+att_reg2str[reg]+
  1032. ' till here...')));
  1033. insertllitem(asml,p2,p1^.next,hp);
  1034. {$endif allocregdebug}
  1035. if Assigned(p1^.optInfo) and
  1036. not (reg in PPaiProp(p1^.OptInfo)^.UsedRegs) then
  1037. begin
  1038. hp := new(paiRegalloc,alloc(reg));
  1039. insertLLItem(asmL,p1^.previous,p1,hp);
  1040. end;
  1041. Repeat
  1042. If Assigned(p1^.OptInfo) Then
  1043. Include(PPaiProp(p1^.OptInfo)^.UsedRegs,Reg);
  1044. p1 := Pai(p1^.next);
  1045. Repeat
  1046. While assigned(p1) and
  1047. (p1^.typ in (SkipInstr-[ait_regalloc])) Do
  1048. p1 := Pai(p1^.next);
  1049. { remove all allocation/deallocation info about the register in between }
  1050. If assigned(p1) and
  1051. (p1^.typ = ait_regalloc) Then
  1052. If (PaiRegAlloc(p1)^.Reg = Reg) Then
  1053. Begin
  1054. lastRemovedWasDealloc := not PaiRegAlloc(p1)^.allocation;
  1055. hp := Pai(p1^.Next);
  1056. AsmL^.Remove(p1);
  1057. Dispose(p1, Done);
  1058. p1 := hp;
  1059. End
  1060. Else p1 := Pai(p1^.next);
  1061. Until not(assigned(p1)) or
  1062. Not(p1^.typ in SkipInstr);
  1063. Until not(assigned(p1)) or
  1064. (p1 = p2);
  1065. if assigned(p1) and lastRemovedWasDealloc then
  1066. begin
  1067. hp := new(paiRegalloc,dealloc(reg));
  1068. insertLLItem(asmL,p1,p1^.next,hp);
  1069. end;
  1070. End;
  1071. Procedure IncState(Var S: Byte; amount: longint);
  1072. {Increases S by 1, wraps around at $ffff to 0 (so we won't get overflow
  1073. errors}
  1074. Begin
  1075. if (s <= $ff - amount) then
  1076. inc(s, amount)
  1077. else s := longint(s) + amount - $ff;
  1078. End;
  1079. Function sequenceDependsonReg(Const Content: TContent; seqReg, Reg: TRegister): Boolean;
  1080. { Content is the sequence of instructions that describes the contents of }
  1081. { seqReg. Reg is being overwritten by the current instruction. If the }
  1082. { content of seqReg depends on reg (ie. because of a }
  1083. { "movl (seqreg,reg), seqReg" instruction), this function returns true }
  1084. Var p: Pai;
  1085. Counter: Byte;
  1086. TmpResult: Boolean;
  1087. RegsChecked: TRegSet;
  1088. Begin
  1089. RegsChecked := [];
  1090. p := Content.StartMod;
  1091. TmpResult := False;
  1092. Counter := 1;
  1093. While Not(TmpResult) And
  1094. (Counter <= Content.NrOfMods) Do
  1095. Begin
  1096. If (p^.typ = ait_instruction) and
  1097. ((Paicpu(p)^.opcode = A_MOV) or
  1098. (Paicpu(p)^.opcode = A_MOVZX) or
  1099. (Paicpu(p)^.opcode = A_MOVSX) or
  1100. (paicpu(p)^.opcode = A_LEA)) and
  1101. (Paicpu(p)^.oper[0].typ = top_ref) Then
  1102. With Paicpu(p)^.oper[0].ref^ Do
  1103. If ((Base = procinfo^.FramePointer) or
  1104. (assigned(symbol) and (base = R_NO))) And
  1105. (Index = R_NO) Then
  1106. Begin
  1107. RegsChecked := RegsChecked + [Reg32(Paicpu(p)^.oper[1].reg)];
  1108. If Reg = Reg32(Paicpu(p)^.oper[1].reg) Then
  1109. Break;
  1110. End
  1111. Else
  1112. tmpResult :=
  1113. regReadByInstruction(reg,p) and
  1114. regModifiedByInstruction(seqReg,p)
  1115. Else
  1116. tmpResult :=
  1117. regReadByInstruction(reg,p) and
  1118. regModifiedByInstruction(seqReg,p);
  1119. Inc(Counter);
  1120. GetNextInstruction(p,p)
  1121. End;
  1122. sequenceDependsonReg := TmpResult
  1123. End;
  1124. procedure invalidateDepedingRegs(p1: ppaiProp; reg: tregister);
  1125. var
  1126. counter: tregister;
  1127. begin
  1128. for counter := R_EAX to R_EDI Do
  1129. if counter <> reg then
  1130. with p1^.regs[counter] Do
  1131. if (typ in [con_ref,con_noRemoveRef]) and
  1132. sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
  1133. if typ in [con_ref,con_invalid] then
  1134. typ := con_invalid
  1135. { con_invalid and con_noRemoveRef = con_unknown }
  1136. else typ := con_unknown;
  1137. end;
  1138. Procedure DestroyReg(p1: PPaiProp; Reg: TRegister; doIncState:Boolean);
  1139. {Destroys the contents of the register Reg in the PPaiProp p1, as well as the
  1140. contents of registers are loaded with a memory location based on Reg.
  1141. doIncState is false when this register has to be destroyed not because
  1142. it's contents are directly modified/overwritten, but because of an indirect
  1143. action (e.g. this register holds the contents of a variable and the value
  1144. of the variable in memory is changed) }
  1145. Var TmpWState, TmpRState: Byte;
  1146. Counter: TRegister;
  1147. Begin
  1148. Reg := Reg32(Reg);
  1149. { the following happens for fpu registers }
  1150. if (reg < low(NrOfInstrSinceLastMod)) or
  1151. (reg > high(NrOfInstrSinceLastMod)) then
  1152. exit;
  1153. NrOfInstrSinceLastMod[Reg] := 0;
  1154. if (reg >= R_EAX) and (reg <= R_EDI) then
  1155. begin
  1156. with p1^.regs[reg] do
  1157. begin
  1158. if doIncState then
  1159. begin
  1160. incState(wstate,1);
  1161. typ := con_unknown;
  1162. end
  1163. else
  1164. if typ in [con_ref,con_invalid] then
  1165. typ := con_invalid
  1166. { con_invalid and con_noRemoveRef = con_unknown }
  1167. else typ := con_unknown;
  1168. end;
  1169. invalidateDepedingRegs(p1,reg);
  1170. end;
  1171. End;
  1172. {Procedure AddRegsToSet(p: Pai; Var RegSet: TRegSet);
  1173. Begin
  1174. If (p^.typ = ait_instruction) Then
  1175. Begin
  1176. Case Paicpu(p)^.oper[0].typ Of
  1177. top_reg:
  1178. If Not(Paicpu(p)^.oper[0].reg in [R_NO,R_ESP,procinfo^.FramePointer]) Then
  1179. RegSet := RegSet + [Paicpu(p)^.oper[0].reg];
  1180. top_ref:
  1181. With TReference(Paicpu(p)^.oper[0]^) Do
  1182. Begin
  1183. If Not(Base in [procinfo^.FramePointer,R_NO,R_ESP])
  1184. Then RegSet := RegSet + [Base];
  1185. If Not(Index in [procinfo^.FramePointer,R_NO,R_ESP])
  1186. Then RegSet := RegSet + [Index];
  1187. End;
  1188. End;
  1189. Case Paicpu(p)^.oper[1].typ Of
  1190. top_reg:
  1191. If Not(Paicpu(p)^.oper[1].reg in [R_NO,R_ESP,procinfo^.FramePointer]) Then
  1192. If RegSet := RegSet + [TRegister(TwoWords(Paicpu(p)^.oper[1]).Word1];
  1193. top_ref:
  1194. With TReference(Paicpu(p)^.oper[1]^) Do
  1195. Begin
  1196. If Not(Base in [procinfo^.FramePointer,R_NO,R_ESP])
  1197. Then RegSet := RegSet + [Base];
  1198. If Not(Index in [procinfo^.FramePointer,R_NO,R_ESP])
  1199. Then RegSet := RegSet + [Index];
  1200. End;
  1201. End;
  1202. End;
  1203. End;}
  1204. Function OpsEquivalent(const o1, o2: toper; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
  1205. Begin {checks whether the two ops are equivalent}
  1206. OpsEquivalent := False;
  1207. if o1.typ=o2.typ then
  1208. Case o1.typ Of
  1209. Top_Reg:
  1210. OpsEquivalent :=RegsEquivalent(o1.reg,o2.reg, RegInfo, OpAct);
  1211. Top_Ref:
  1212. OpsEquivalent := RefsEquivalent(o1.ref^, o2.ref^, RegInfo, OpAct);
  1213. Top_Const:
  1214. OpsEquivalent := o1.val = o2.val;
  1215. Top_None:
  1216. OpsEquivalent := True
  1217. End;
  1218. End;
  1219. Function OpsEqual(const o1,o2:toper): Boolean;
  1220. Begin {checks whether the two ops are equal}
  1221. OpsEqual := False;
  1222. if o1.typ=o2.typ then
  1223. Case o1.typ Of
  1224. Top_Reg :
  1225. OpsEqual:=o1.reg=o2.reg;
  1226. Top_Ref :
  1227. OpsEqual := RefsEqual(o1.ref^, o2.ref^);
  1228. Top_Const :
  1229. OpsEqual:=o1.val=o2.val;
  1230. Top_Symbol :
  1231. OpsEqual:=(o1.sym=o2.sym) and (o1.symofs=o2.symofs);
  1232. Top_None :
  1233. OpsEqual := True
  1234. End;
  1235. End;
  1236. Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
  1237. {$ifdef csdebug}
  1238. var
  1239. hp: pai;
  1240. {$endif csdebug}
  1241. Begin {checks whether two Paicpu instructions are equal}
  1242. If Assigned(p1) And Assigned(p2) And
  1243. (Pai(p1)^.typ = ait_instruction) And
  1244. (Pai(p1)^.typ = ait_instruction) And
  1245. (Paicpu(p1)^.opcode = Paicpu(p2)^.opcode) And
  1246. (Paicpu(p1)^.oper[0].typ = Paicpu(p2)^.oper[0].typ) And
  1247. (Paicpu(p1)^.oper[1].typ = Paicpu(p2)^.oper[1].typ) And
  1248. (Paicpu(p1)^.oper[2].typ = Paicpu(p2)^.oper[2].typ)
  1249. Then
  1250. {both instructions have the same structure:
  1251. "<operator> <operand of type1>, <operand of type 2>"}
  1252. If ((Paicpu(p1)^.opcode = A_MOV) or
  1253. (Paicpu(p1)^.opcode = A_MOVZX) or
  1254. (Paicpu(p1)^.opcode = A_MOVSX)) And
  1255. (Paicpu(p1)^.oper[0].typ = top_ref) {then .oper[1]t = top_reg} Then
  1256. If Not(RegInRef(Paicpu(p1)^.oper[1].reg, Paicpu(p1)^.oper[0].ref^)) Then
  1257. {the "old" instruction is a load of a register with a new value, not with
  1258. a value based on the contents of this register (so no "mov (reg), reg")}
  1259. If Not(RegInRef(Paicpu(p2)^.oper[1].reg, Paicpu(p2)^.oper[0].ref^)) And
  1260. RefsEqual(Paicpu(p1)^.oper[0].ref^, Paicpu(p2)^.oper[0].ref^)
  1261. Then
  1262. {the "new" instruction is also a load of a register with a new value, and
  1263. this value is fetched from the same memory location}
  1264. Begin
  1265. With Paicpu(p2)^.oper[0].ref^ Do
  1266. Begin
  1267. If Not(Base in [procinfo^.FramePointer, R_NO, R_ESP]) Then
  1268. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Base];
  1269. If Not(Index in [procinfo^.FramePointer, R_NO, R_ESP]) Then
  1270. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Index];
  1271. End;
  1272. {add the registers from the reference (.oper[0]) to the RegInfo, all registers
  1273. from the reference are the same in the old and in the new instruction
  1274. sequence}
  1275. AddOp2RegInfo(Paicpu(p1)^.oper[0], RegInfo);
  1276. {the registers from .oper[1] have to be equivalent, but not necessarily equal}
  1277. InstructionsEquivalent :=
  1278. RegsEquivalent(Paicpu(p1)^.oper[1].reg, Paicpu(p2)^.oper[1].reg, RegInfo, OpAct_Write);
  1279. End
  1280. {the registers are loaded with values from different memory locations. If
  1281. this was allowed, the instructions "mov -4(esi),eax" and "mov -4(ebp),eax"
  1282. would be considered equivalent}
  1283. Else InstructionsEquivalent := False
  1284. Else
  1285. {load register with a value based on the current value of this register}
  1286. Begin
  1287. With Paicpu(p2)^.oper[0].ref^ Do
  1288. Begin
  1289. If Not(Base in [procinfo^.FramePointer,
  1290. Reg32(Paicpu(p2)^.oper[1].reg),R_NO,R_ESP]) Then
  1291. {it won't do any harm if the register is already in RegsLoadedForRef}
  1292. Begin
  1293. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Base];
  1294. {$ifdef csdebug}
  1295. Writeln(att_reg2str[base], ' added');
  1296. {$endif csdebug}
  1297. end;
  1298. If Not(Index in [procinfo^.FramePointer,
  1299. Reg32(Paicpu(p2)^.oper[1].reg),R_NO,R_ESP]) Then
  1300. Begin
  1301. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef + [Index];
  1302. {$ifdef csdebug}
  1303. Writeln(att_reg2str[index], ' added');
  1304. {$endif csdebug}
  1305. end;
  1306. End;
  1307. If Not(Reg32(Paicpu(p2)^.oper[1].reg) In [procinfo^.FramePointer,R_NO,R_ESP])
  1308. Then
  1309. Begin
  1310. RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef -
  1311. [Reg32(Paicpu(p2)^.oper[1].reg)];
  1312. {$ifdef csdebug}
  1313. Writeln(att_reg2str[Reg32(Paicpu(p2)^.oper[1].reg)], ' removed');
  1314. {$endif csdebug}
  1315. end;
  1316. InstructionsEquivalent :=
  1317. OpsEquivalent(Paicpu(p1)^.oper[0], Paicpu(p2)^.oper[0], RegInfo, OpAct_Read) And
  1318. OpsEquivalent(Paicpu(p1)^.oper[1], Paicpu(p2)^.oper[1], RegInfo, OpAct_Write)
  1319. End
  1320. Else
  1321. {an instruction <> mov, movzx, movsx}
  1322. begin
  1323. {$ifdef csdebug}
  1324. hp := new(pai_asm_comment,init(strpnew('checking if equivalent')));
  1325. hp^.previous := p2;
  1326. hp^.next := p2^.next;
  1327. p2^.next^.previous := hp;
  1328. p2^.next := hp;
  1329. {$endif csdebug}
  1330. InstructionsEquivalent :=
  1331. OpsEquivalent(Paicpu(p1)^.oper[0], Paicpu(p2)^.oper[0], RegInfo, OpAct_Unknown) And
  1332. OpsEquivalent(Paicpu(p1)^.oper[1], Paicpu(p2)^.oper[1], RegInfo, OpAct_Unknown) And
  1333. OpsEquivalent(Paicpu(p1)^.oper[2], Paicpu(p2)^.oper[2], RegInfo, OpAct_Unknown)
  1334. end
  1335. {the instructions haven't even got the same structure, so they're certainly
  1336. not equivalent}
  1337. Else
  1338. begin
  1339. {$ifdef csdebug}
  1340. hp := new(pai_asm_comment,init(strpnew('different opcodes/format')));
  1341. hp^.previous := p2;
  1342. hp^.next := p2^.next;
  1343. p2^.next^.previous := hp;
  1344. p2^.next := hp;
  1345. {$endif csdebug}
  1346. InstructionsEquivalent := False;
  1347. end;
  1348. {$ifdef csdebug}
  1349. hp := new(pai_asm_comment,init(strpnew('instreq: '+tostr(byte(instructionsequivalent)))));
  1350. hp^.previous := p2;
  1351. hp^.next := p2^.next;
  1352. p2^.next^.previous := hp;
  1353. p2^.next := hp;
  1354. {$endif csdebug}
  1355. End;
  1356. (*
  1357. Function InstructionsEqual(p1, p2: Pai): Boolean;
  1358. Begin {checks whether two Paicpu instructions are equal}
  1359. InstructionsEqual :=
  1360. Assigned(p1) And Assigned(p2) And
  1361. ((Pai(p1)^.typ = ait_instruction) And
  1362. (Pai(p1)^.typ = ait_instruction) And
  1363. (Paicpu(p1)^.opcode = Paicpu(p2)^.opcode) And
  1364. (Paicpu(p1)^.oper[0].typ = Paicpu(p2)^.oper[0].typ) And
  1365. (Paicpu(p1)^.oper[1].typ = Paicpu(p2)^.oper[1].typ) And
  1366. OpsEqual(Paicpu(p1)^.oper[0].typ, Paicpu(p1)^.oper[0], Paicpu(p2)^.oper[0]) And
  1367. OpsEqual(Paicpu(p1)^.oper[1].typ, Paicpu(p1)^.oper[1], Paicpu(p2)^.oper[1]))
  1368. End;
  1369. *)
  1370. Procedure ReadReg(p: PPaiProp; Reg: TRegister);
  1371. Begin
  1372. Reg := Reg32(Reg);
  1373. If Reg in [R_EAX..R_EDI] Then
  1374. incState(p^.regs[Reg].rstate,1)
  1375. End;
  1376. Procedure ReadRef(p: PPaiProp; Ref: PReference);
  1377. Begin
  1378. If Ref^.Base <> R_NO Then
  1379. ReadReg(p, Ref^.Base);
  1380. If Ref^.Index <> R_NO Then
  1381. ReadReg(p, Ref^.Index);
  1382. End;
  1383. Procedure ReadOp(P: PPaiProp;const o:toper);
  1384. Begin
  1385. Case o.typ Of
  1386. top_reg: ReadReg(P, o.reg);
  1387. top_ref: ReadRef(P, o.ref);
  1388. top_symbol : ;
  1389. End;
  1390. End;
  1391. Function RefInInstruction(Const Ref: TReference; p: Pai;
  1392. RefsEq: TRefCompare): Boolean;
  1393. {checks whehter Ref is used in P}
  1394. Var TmpResult: Boolean;
  1395. Begin
  1396. TmpResult := False;
  1397. If (p^.typ = ait_instruction) Then
  1398. Begin
  1399. If (Paicpu(p)^.oper[0].typ = Top_Ref) Then
  1400. TmpResult := RefsEq(Ref, Paicpu(p)^.oper[0].ref^);
  1401. If Not(TmpResult) And (Paicpu(p)^.oper[1].typ = Top_Ref) Then
  1402. TmpResult := RefsEq(Ref, Paicpu(p)^.oper[1].ref^);
  1403. If Not(TmpResult) And (Paicpu(p)^.oper[2].typ = Top_Ref) Then
  1404. TmpResult := RefsEq(Ref, Paicpu(p)^.oper[2].ref^);
  1405. End;
  1406. RefInInstruction := TmpResult;
  1407. End;
  1408. Function RefInSequence(Const Ref: TReference; Content: TContent;
  1409. RefsEq: TRefCompare): Boolean;
  1410. {checks the whole sequence of Content (so StartMod and and the next NrOfMods
  1411. Pai objects) to see whether Ref is used somewhere}
  1412. Var p: Pai;
  1413. Counter: Byte;
  1414. TmpResult: Boolean;
  1415. Begin
  1416. p := Content.StartMod;
  1417. TmpResult := False;
  1418. Counter := 1;
  1419. While Not(TmpResult) And
  1420. (Counter <= Content.NrOfMods) Do
  1421. Begin
  1422. If (p^.typ = ait_instruction) And
  1423. RefInInstruction(Ref, p, RefsEq)
  1424. Then TmpResult := True;
  1425. Inc(Counter);
  1426. GetNextInstruction(p,p)
  1427. End;
  1428. RefInSequence := TmpResult
  1429. End;
  1430. Function ArrayRefsEq(const r1, r2: TReference): Boolean;
  1431. Begin
  1432. ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
  1433. (R1.Segment = R2.Segment) And
  1434. (R1.Symbol=R2.Symbol) And
  1435. ((Assigned(R1.Symbol)) Or
  1436. (R1.Base = R2.Base))
  1437. End;
  1438. function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
  1439. reg: tregister; const c: tcontent): boolean;
  1440. { returns whether the contents c of reg are invalid after regWritten is }
  1441. { is written to ref }
  1442. var
  1443. refsEq: trefCompare;
  1444. begin
  1445. if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
  1446. begin
  1447. writeToMemDestroysContents := false;
  1448. exit;
  1449. end;
  1450. reg := reg32(reg);
  1451. regWritten := reg32(regWritten);
  1452. if (ref.base = procinfo^.framePointer) or
  1453. assigned(ref.symbol) Then
  1454. begin
  1455. if (ref.index <> R_NO) or
  1456. (assigned(ref.symbol) and
  1457. (ref.base <> R_NO)) then
  1458. { local/global variable or parameter which is an array }
  1459. refsEq := {$ifdef fpc}@{$endif}arrayRefsEq
  1460. else
  1461. { local/global variable or parameter which is not an array }
  1462. refsEq := {$ifdef fpc}@{$endif}refsEqual;
  1463. { write something to a parameter, a local or global variable, so }
  1464. { * with uncertain optimizations on: }
  1465. { - destroy the contents of registers whose contents have somewhere a }
  1466. { "mov?? (Ref), %reg". WhichReg (this is the register whose contents }
  1467. { are being written to memory) is not destroyed if it's StartMod is }
  1468. { of that form and NrOfMods = 1 (so if it holds ref, but is not a }
  1469. { pointer based on Ref) }
  1470. { * with uncertain optimizations off: }
  1471. { - also destroy registers that contain any pointer }
  1472. with c do
  1473. writeToMemDestroysContents :=
  1474. (typ in [con_ref,con_noRemoveRef]) and
  1475. ((not(cs_uncertainOpts in aktglobalswitches) and
  1476. (nrOfMods <> 1)
  1477. ) or
  1478. (refInSequence(ref,c,refsEq) and
  1479. ((reg <> regWritten) or
  1480. ((nrOfMods <> 1) and
  1481. {StarMod is always of the type ait_instruction}
  1482. (paicpu(StartMod)^.oper[0].typ = top_ref) and
  1483. refsEq(Paicpu(StartMod)^.oper[0].ref^, ref)
  1484. )
  1485. )
  1486. )
  1487. )
  1488. end
  1489. else
  1490. { write something to a pointer location, so }
  1491. { * with uncertain optimzations on: }
  1492. { - do not destroy registers which contain a local/global variable or }
  1493. { a parameter, except if DestroyRefs is called because of a "movsl" }
  1494. { * with uncertain optimzations off: }
  1495. { - destroy every register which contains a memory location }
  1496. with c do
  1497. writeToMemDestroysContents :=
  1498. (typ in [con_ref,con_noRemoveRef]) and
  1499. (not(cs_UncertainOpts in aktglobalswitches) or
  1500. { for movsl }
  1501. ((ref.base = R_EDI) and (ref.index = R_EDI)) or
  1502. { don't destroy if reg contains a parameter, local or global variable }
  1503. not((nrOfMods = 1) and
  1504. (paicpu(startMod)^.oper[0].typ = top_ref) and
  1505. ((paicpu(startMod)^.oper[0].ref^.base = procinfo^.framePointer) or
  1506. assigned(paicpu(startMod)^.oper[0].ref^.symbol)
  1507. )
  1508. )
  1509. )
  1510. end;
  1511. function writeToRegDestroysContents(destReg: tregister; reg: tregister;
  1512. const c: tcontent): boolean;
  1513. { returns whether the contents c of reg are invalid after destReg is }
  1514. { modified }
  1515. begin
  1516. writeToRegDestroysContents :=
  1517. (c.typ <> con_unknown) and
  1518. sequenceDependsOnReg(c,reg,reg32(destReg));
  1519. end;
  1520. function writeDestroysContents(const op: toper; reg: tregister;
  1521. const c: tcontent): boolean;
  1522. { returns whether the contents c of reg are invalid after regWritten is }
  1523. { is written to op }
  1524. begin
  1525. reg := reg32(reg);
  1526. case op.typ of
  1527. top_reg:
  1528. writeDestroysContents :=
  1529. writeToRegDestroysContents(op.reg,reg,c);
  1530. top_ref:
  1531. writeDestroysContents :=
  1532. writeToMemDestroysContents(R_NO,op.ref^,reg,c);
  1533. else
  1534. writeDestroysContents := false;
  1535. end;
  1536. end;
  1537. procedure destroyRefs(p: pai; const ref: treference; regWritten: tregister);
  1538. { destroys all registers which possibly contain a reference to Ref, regWritten }
  1539. { is the register whose contents are being written to memory (if this proc }
  1540. { is called because of a "mov?? %reg, (mem)" instruction) }
  1541. var
  1542. counter: TRegister;
  1543. begin
  1544. for counter := R_EAX to R_EDI Do
  1545. if writeToMemDestroysContents(regWritten,ref,counter,
  1546. ppaiProp(p^.optInfo)^.regs[counter]) then
  1547. destroyReg(ppaiProp(p^.optInfo), counter, false)
  1548. End;
  1549. Procedure DestroyAllRegs(p: PPaiProp);
  1550. Var Counter: TRegister;
  1551. Begin {initializes/desrtoys all registers}
  1552. For Counter := R_EAX To R_EDI Do
  1553. Begin
  1554. ReadReg(p, Counter);
  1555. DestroyReg(p, Counter, true);
  1556. End;
  1557. p^.DirFlag := F_Unknown;
  1558. End;
  1559. Procedure DestroyOp(PaiObj: Pai; const o:Toper);
  1560. {$ifdef statedebug}
  1561. var hp: pai;
  1562. {$endif statedebug}
  1563. Begin
  1564. Case o.typ Of
  1565. top_reg:
  1566. begin
  1567. {$ifdef statedebug}
  1568. hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[o.reg])));
  1569. hp^.next := paiobj^.next;
  1570. hp^.previous := paiobj;
  1571. paiobj^.next := hp;
  1572. if assigned(hp^.next) then
  1573. hp^.next^.previous := hp;
  1574. {$endif statedebug}
  1575. DestroyReg(PPaiProp(PaiObj^.OptInfo), reg32(o.reg), true);
  1576. end;
  1577. top_ref:
  1578. Begin
  1579. ReadRef(PPaiProp(PaiObj^.OptInfo), o.ref);
  1580. DestroyRefs(PaiObj, o.ref^, R_NO);
  1581. End;
  1582. top_symbol:;
  1583. End;
  1584. End;
  1585. Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
  1586. {gathers the RegAlloc data... still need to think about where to store it to
  1587. avoid global vars}
  1588. Var BlockEnd: Pai;
  1589. Begin
  1590. BlockEnd := FindLoHiLabels(LoLab, HiLab, LabDif, BlockStart);
  1591. BuildLabelTableAndFixRegAlloc(AsmL, LTable, LoLab, LabDif, BlockStart, BlockEnd);
  1592. DFAPass1 := BlockEnd;
  1593. End;
  1594. Procedure AddInstr2RegContents({$ifdef statedebug} asml: paasmoutput; {$endif}
  1595. p: paicpu; reg: TRegister);
  1596. {$ifdef statedebug}
  1597. var hp: pai;
  1598. {$endif statedebug}
  1599. Begin
  1600. Reg := Reg32(Reg);
  1601. With PPaiProp(p^.optinfo)^.Regs[reg] Do
  1602. if (typ in [con_ref,con_noRemoveRef])
  1603. Then
  1604. Begin
  1605. incState(wstate,1);
  1606. {also store how many instructions are part of the sequence in the first
  1607. instructions PPaiProp, so it can be easily accessed from within
  1608. CheckSequence}
  1609. Inc(NrOfMods, NrOfInstrSinceLastMod[Reg]);
  1610. PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
  1611. NrOfInstrSinceLastMod[Reg] := 0;
  1612. {$ifdef StateDebug}
  1613. hp := new(pai_asm_comment,init(strpnew(att_reg2str[reg]+': '+tostr(PPaiProp(p^.optinfo)^.Regs[reg].WState)
  1614. + ' -- ' + tostr(PPaiProp(p^.optinfo)^.Regs[reg].nrofmods))));
  1615. InsertLLItem(AsmL, p, p^.next, hp);
  1616. {$endif StateDebug}
  1617. End
  1618. Else
  1619. Begin
  1620. {$ifdef statedebug}
  1621. hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[reg])));
  1622. insertllitem(asml,p,p^.next,hp);
  1623. {$endif statedebug}
  1624. DestroyReg(PPaiProp(p^.optinfo), Reg, true);
  1625. {$ifdef StateDebug}
  1626. hp := new(pai_asm_comment,init(strpnew(att_reg2str[reg]+': '+tostr(PPaiProp(p^.optinfo)^.Regs[reg].WState))));
  1627. InsertLLItem(AsmL, p, p^.next, hp);
  1628. {$endif StateDebug}
  1629. End
  1630. End;
  1631. Procedure AddInstr2OpContents({$ifdef statedebug} asml: paasmoutput; {$endif}
  1632. p: paicpu; const oper: TOper);
  1633. Begin
  1634. If oper.typ = top_reg Then
  1635. AddInstr2RegContents({$ifdef statedebug} asml, {$endif}p, oper.reg)
  1636. Else
  1637. Begin
  1638. ReadOp(PPaiProp(p^.optinfo), oper);
  1639. DestroyOp(p, oper);
  1640. End
  1641. End;
  1642. Procedure DoDFAPass2(
  1643. {$Ifdef StateDebug}
  1644. AsmL: PAasmOutput;
  1645. {$endif statedebug}
  1646. BlockStart, BlockEnd: Pai);
  1647. {Analyzes the Data Flow of an assembler list. Starts creating the reg
  1648. contents for the instructions starting with p. Returns the last pai which has
  1649. been processed}
  1650. Var
  1651. CurProp: PPaiProp;
  1652. Cnt, InstrCnt : Longint;
  1653. InstrProp: TInsProp;
  1654. UsedRegs: TRegSet;
  1655. p, hp : Pai;
  1656. TmpRef: TReference;
  1657. TmpReg: TRegister;
  1658. {$ifdef AnalyzeLoops}
  1659. TmpState: Byte;
  1660. {$endif AnalyzeLoops}
  1661. Begin
  1662. p := BlockStart;
  1663. UsedRegs := [];
  1664. UpdateUsedregs(UsedRegs, p);
  1665. SkipHead(P);
  1666. BlockStart := p;
  1667. InstrCnt := 1;
  1668. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
  1669. While (P <> BlockEnd) Do
  1670. Begin
  1671. CurProp := @PaiPropBlock^[InstrCnt];
  1672. If (p <> BlockStart)
  1673. Then
  1674. Begin
  1675. {$ifdef JumpAnal}
  1676. If (p^.Typ <> ait_label) Then
  1677. {$endif JumpAnal}
  1678. Begin
  1679. GetLastInstruction(p, hp);
  1680. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  1681. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  1682. End
  1683. End
  1684. Else
  1685. Begin
  1686. FillChar(CurProp^, SizeOf(CurProp^), 0);
  1687. { For TmpReg := R_EAX to R_EDI Do
  1688. CurProp^.Regs[TmpReg].WState := 1;}
  1689. End;
  1690. CurProp^.UsedRegs := UsedRegs;
  1691. CurProp^.CanBeRemoved := False;
  1692. UpdateUsedRegs(UsedRegs, Pai(p^.Next));
  1693. For TmpReg := R_EAX To R_EDI Do
  1694. Inc(NrOfInstrSinceLastMod[TmpReg]);
  1695. Case p^.typ Of
  1696. ait_marker:;
  1697. ait_label:
  1698. {$Ifndef JumpAnal}
  1699. If not labelCanBeSkipped(pai_label(p)) Then
  1700. DestroyAllRegs(CurProp);
  1701. {$Else JumpAnal}
  1702. Begin
  1703. If not labelCanBeSkipped(pai_label(p)) Then
  1704. With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
  1705. {$IfDef AnalyzeLoops}
  1706. If (RefsFound = Pai_Label(p)^.l^.RefCount)
  1707. {$Else AnalyzeLoops}
  1708. If (JmpsProcessed = Pai_Label(p)^.l^.RefCount)
  1709. {$EndIf AnalyzeLoops}
  1710. Then
  1711. {all jumps to this label have been found}
  1712. {$IfDef AnalyzeLoops}
  1713. If (JmpsProcessed > 0)
  1714. Then
  1715. {$EndIf AnalyzeLoops}
  1716. {we've processed at least one jump to this label}
  1717. Begin
  1718. If (GetLastInstruction(p, hp) And
  1719. Not(((hp^.typ = ait_instruction)) And
  1720. (paicpu_labeled(hp)^.is_jmp))
  1721. Then
  1722. {previous instruction not a JMP -> the contents of the registers after the
  1723. previous intruction has been executed have to be taken into account as well}
  1724. For TmpReg := R_EAX to R_EDI Do
  1725. Begin
  1726. If (CurProp^.Regs[TmpReg].WState <>
  1727. PPaiProp(hp^.OptInfo)^.Regs[TmpReg].WState)
  1728. Then DestroyReg(CurProp, TmpReg, true)
  1729. End
  1730. End
  1731. {$IfDef AnalyzeLoops}
  1732. Else
  1733. {a label from a backward jump (e.g. a loop), no jump to this label has
  1734. already been processed}
  1735. If GetLastInstruction(p, hp) And
  1736. Not(hp^.typ = ait_instruction) And
  1737. (paicpu_labeled(hp)^.opcode = A_JMP))
  1738. Then
  1739. {previous instruction not a jmp, so keep all the registers' contents from the
  1740. previous instruction}
  1741. Begin
  1742. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  1743. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  1744. End
  1745. Else
  1746. {previous instruction a jmp and no jump to this label processed yet}
  1747. Begin
  1748. hp := p;
  1749. Cnt := InstrCnt;
  1750. {continue until we find a jump to the label or a label which has already
  1751. been processed}
  1752. While GetNextInstruction(hp, hp) And
  1753. Not((hp^.typ = ait_instruction) And
  1754. (paicpu(hp)^.is_jmp) and
  1755. (pasmlabel(paicpu(hp)^.oper[0].sym)^.labelnr = Pai_Label(p)^.l^.labelnr)) And
  1756. Not((hp^.typ = ait_label) And
  1757. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].RefsFound
  1758. = Pai_Label(hp)^.l^.RefCount) And
  1759. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].JmpsProcessed > 0)) Do
  1760. Inc(Cnt);
  1761. If (hp^.typ = ait_label)
  1762. Then
  1763. {there's a processed label after the current one}
  1764. Begin
  1765. CurProp^.Regs := PaiPropBlock^[Cnt].Regs;
  1766. CurProp^.DirFlag := PaiPropBlock^[Cnt].DirFlag;
  1767. End
  1768. Else
  1769. {there's no label anymore after the current one, or they haven't been
  1770. processed yet}
  1771. Begin
  1772. GetLastInstruction(p, hp);
  1773. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  1774. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  1775. DestroyAllRegs(PPaiProp(hp^.OptInfo))
  1776. End
  1777. End
  1778. {$EndIf AnalyzeLoops}
  1779. Else
  1780. {not all references to this label have been found, so destroy all registers}
  1781. Begin
  1782. GetLastInstruction(p, hp);
  1783. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  1784. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  1785. DestroyAllRegs(CurProp)
  1786. End;
  1787. End;
  1788. {$EndIf JumpAnal}
  1789. {$ifdef GDB}
  1790. ait_stabs, ait_stabn, ait_stab_function_name:;
  1791. {$endif GDB}
  1792. ait_align: ; { may destroy flags !!! }
  1793. ait_instruction:
  1794. Begin
  1795. if paicpu(p)^.is_jmp then
  1796. begin
  1797. {$IfNDef JumpAnal}
  1798. for tmpReg := R_EAX to R_EDI do
  1799. with curProp^.regs[tmpReg] do
  1800. case typ of
  1801. con_ref: typ := con_noRemoveRef;
  1802. con_const: typ := con_noRemoveConst;
  1803. con_invalid: typ := con_unknown;
  1804. end;
  1805. {$Else JumpAnal}
  1806. With LTable^[pasmlabel(paicpu(p)^.oper[0].sym)^.labelnr-LoLab] Do
  1807. If (RefsFound = pasmlabel(paicpu(p)^.oper[0].sym)^.RefCount) Then
  1808. Begin
  1809. If (InstrCnt < InstrNr)
  1810. Then
  1811. {forward jump}
  1812. If (JmpsProcessed = 0) Then
  1813. {no jump to this label has been processed yet}
  1814. Begin
  1815. PaiPropBlock^[InstrNr].Regs := CurProp^.Regs;
  1816. PaiPropBlock^[InstrNr].DirFlag := CurProp^.DirFlag;
  1817. Inc(JmpsProcessed);
  1818. End
  1819. Else
  1820. Begin
  1821. For TmpReg := R_EAX to R_EDI Do
  1822. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  1823. CurProp^.Regs[TmpReg].WState) Then
  1824. DestroyReg(@PaiPropBlock^[InstrNr], TmpReg, true);
  1825. Inc(JmpsProcessed);
  1826. End
  1827. {$ifdef AnalyzeLoops}
  1828. Else
  1829. { backward jump, a loop for example}
  1830. { If (JmpsProcessed > 0) Or
  1831. Not(GetLastInstruction(PaiObj, hp) And
  1832. (hp^.typ = ait_labeled_instruction) And
  1833. (paicpu_labeled(hp)^.opcode = A_JMP))
  1834. Then}
  1835. {instruction prior to label is not a jmp, or at least one jump to the label
  1836. has yet been processed}
  1837. Begin
  1838. Inc(JmpsProcessed);
  1839. For TmpReg := R_EAX to R_EDI Do
  1840. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  1841. CurProp^.Regs[TmpReg].WState)
  1842. Then
  1843. Begin
  1844. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1845. Cnt := InstrNr;
  1846. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1847. Begin
  1848. DestroyReg(@PaiPropBlock^[Cnt], TmpReg, true);
  1849. Inc(Cnt);
  1850. End;
  1851. While (Cnt <= InstrCnt) Do
  1852. Begin
  1853. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  1854. Inc(Cnt)
  1855. End
  1856. End;
  1857. End
  1858. { Else }
  1859. {instruction prior to label is a jmp and no jumps to the label have yet been
  1860. processed}
  1861. { Begin
  1862. Inc(JmpsProcessed);
  1863. For TmpReg := R_EAX to R_EDI Do
  1864. Begin
  1865. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1866. Cnt := InstrNr;
  1867. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1868. Begin
  1869. PaiPropBlock^[Cnt].Regs[TmpReg] := CurProp^.Regs[TmpReg];
  1870. Inc(Cnt);
  1871. End;
  1872. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  1873. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  1874. Begin
  1875. DestroyReg(@PaiPropBlock^[Cnt], TmpReg, true);
  1876. Inc(Cnt);
  1877. End;
  1878. While (Cnt <= InstrCnt) Do
  1879. Begin
  1880. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  1881. Inc(Cnt)
  1882. End
  1883. End
  1884. End}
  1885. {$endif AnalyzeLoops}
  1886. End;
  1887. {$EndIf JumpAnal}
  1888. end
  1889. else
  1890. begin
  1891. InstrProp := InsProp[Paicpu(p)^.opcode];
  1892. Case Paicpu(p)^.opcode Of
  1893. A_MOV, A_MOVZX, A_MOVSX:
  1894. Begin
  1895. Case Paicpu(p)^.oper[0].typ Of
  1896. Top_Reg:
  1897. Case Paicpu(p)^.oper[1].typ Of
  1898. Top_Reg:
  1899. Begin
  1900. {$ifdef statedebug}
  1901. hp := new(pai_asm_comment,init(strpnew('destroying '+
  1902. att_reg2str[Paicpu(p)^.oper[1].reg])));
  1903. insertllitem(asml,p,p^.next,hp);
  1904. {$endif statedebug}
  1905. DestroyReg(CurProp, Paicpu(p)^.oper[1].reg, true);
  1906. ReadReg(CurProp, Paicpu(p)^.oper[0].reg);
  1907. { CurProp^.Regs[Paicpu(p)^.oper[1].reg] :=
  1908. CurProp^.Regs[Paicpu(p)^.oper[0].reg];
  1909. If (CurProp^.Regs[Paicpu(p)^.oper[1].reg].ModReg = R_NO) Then
  1910. CurProp^.Regs[Paicpu(p)^.oper[1].reg].ModReg :=
  1911. Paicpu(p)^.oper[0].reg;}
  1912. End;
  1913. Top_Ref:
  1914. Begin
  1915. ReadReg(CurProp, Paicpu(p)^.oper[0].reg);
  1916. ReadRef(CurProp, Paicpu(p)^.oper[1].ref);
  1917. DestroyRefs(p, Paicpu(p)^.oper[1].ref^, Paicpu(p)^.oper[0].reg);
  1918. End;
  1919. End;
  1920. Top_Ref:
  1921. Begin {destination is always a register in this case}
  1922. ReadRef(CurProp, Paicpu(p)^.oper[0].ref);
  1923. TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
  1924. If RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^) And
  1925. (curProp^.regs[tmpReg].typ in [con_ref,con_noRemoveRef])
  1926. Then
  1927. Begin
  1928. With CurProp^.Regs[TmpReg] Do
  1929. Begin
  1930. incState(wstate,1);
  1931. {also store how many instructions are part of the sequence in the first
  1932. instructions PPaiProp, so it can be easily accessed from within
  1933. CheckSequence}
  1934. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  1935. PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
  1936. NrOfInstrSinceLastMod[TmpReg] := 0;
  1937. { Destroy the contents of the registers }
  1938. { that depended on the previous value of }
  1939. { this register }
  1940. invalidateDepedingRegs(curProp,tmpReg);
  1941. End;
  1942. End
  1943. Else
  1944. Begin
  1945. {$ifdef statedebug}
  1946. hp := new(pai_asm_comment,init(strpnew('destroying & initing '+att_reg2str[tmpreg])));
  1947. insertllitem(asml,p,p^.next,hp);
  1948. {$endif statedebug}
  1949. DestroyReg(CurProp, TmpReg, true);
  1950. If Not(RegInRef(TmpReg, Paicpu(p)^.oper[0].ref^)) Then
  1951. With CurProp^.Regs[TmpReg] Do
  1952. Begin
  1953. Typ := Con_Ref;
  1954. StartMod := p;
  1955. NrOfMods := 1;
  1956. End
  1957. End;
  1958. {$ifdef StateDebug}
  1959. hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
  1960. InsertLLItem(AsmL, p, p^.next, hp);
  1961. {$endif StateDebug}
  1962. End;
  1963. top_symbol,Top_Const:
  1964. Begin
  1965. Case Paicpu(p)^.oper[1].typ Of
  1966. Top_Reg:
  1967. Begin
  1968. TmpReg := Reg32(Paicpu(p)^.oper[1].reg);
  1969. {$ifdef statedebug}
  1970. hp := new(pai_asm_comment,init(strpnew('destroying '+att_reg2str[tmpreg])));
  1971. insertllitem(asml,p,p^.next,hp);
  1972. {$endif statedebug}
  1973. With CurProp^.Regs[TmpReg] Do
  1974. Begin
  1975. DestroyReg(CurProp, TmpReg, true);
  1976. typ := Con_Const;
  1977. StartMod := p;
  1978. End
  1979. End;
  1980. Top_Ref:
  1981. Begin
  1982. ReadRef(CurProp, Paicpu(p)^.oper[1].ref);
  1983. DestroyRefs(P, Paicpu(p)^.oper[1].ref^, R_NO);
  1984. End;
  1985. End;
  1986. End;
  1987. End;
  1988. End;
  1989. A_DIV, A_IDIV, A_MUL:
  1990. Begin
  1991. ReadOp(Curprop, Paicpu(p)^.oper[0]);
  1992. ReadReg(CurProp,R_EAX);
  1993. If (Paicpu(p)^.OpCode = A_IDIV) or
  1994. (Paicpu(p)^.OpCode = A_DIV) Then
  1995. ReadReg(CurProp,R_EDX);
  1996. {$ifdef statedebug}
  1997. hp := new(pai_asm_comment,init(strpnew('destroying eax and edx')));
  1998. insertllitem(asml,p,p^.next,hp);
  1999. {$endif statedebug}
  2000. DestroyReg(CurProp, R_EAX, true);
  2001. DestroyReg(CurProp, R_EDX, true)
  2002. End;
  2003. A_IMUL:
  2004. Begin
  2005. ReadOp(CurProp,Paicpu(p)^.oper[0]);
  2006. ReadOp(CurProp,Paicpu(p)^.oper[1]);
  2007. If (Paicpu(p)^.oper[2].typ = top_none) Then
  2008. If (Paicpu(p)^.oper[1].typ = top_none) Then
  2009. Begin
  2010. ReadReg(CurProp,R_EAX);
  2011. {$ifdef statedebug}
  2012. hp := new(pai_asm_comment,init(strpnew('destroying eax and edx')));
  2013. insertllitem(asml,p,p^.next,hp);
  2014. {$endif statedebug}
  2015. DestroyReg(CurProp, R_EAX, true);
  2016. DestroyReg(CurProp, R_EDX, true)
  2017. End
  2018. Else
  2019. AddInstr2OpContents(
  2020. {$ifdef statedebug}asml,{$endif}
  2021. Paicpu(p), Paicpu(p)^.oper[1])
  2022. Else
  2023. AddInstr2OpContents({$ifdef statedebug}asml,{$endif}
  2024. Paicpu(p), Paicpu(p)^.oper[2]);
  2025. End;
  2026. A_LEA:
  2027. begin
  2028. readop(curprop,paicpu(p)^.oper[0]);
  2029. if reginref(paicpu(p)^.oper[1].reg,paicpu(p)^.oper[0].ref^) then
  2030. AddInstr2RegContents({$ifdef statedebug}asml,{$endif}
  2031. paicpu(p), paicpu(p)^.oper[1].reg)
  2032. else
  2033. begin
  2034. {$ifdef statedebug}
  2035. hp := new(pai_asm_comment,init(strpnew('destroying '+
  2036. att_reg2str[paicpu(p)^.oper[1].reg])));
  2037. insertllitem(asml,p,p^.next,hp);
  2038. {$endif statedebug}
  2039. destroyreg(curprop,paicpu(p)^.oper[1].reg,true);
  2040. end;
  2041. end;
  2042. Else
  2043. Begin
  2044. Cnt := 1;
  2045. While (Cnt <= MaxCh) And
  2046. (InstrProp.Ch[Cnt] <> Ch_None) Do
  2047. Begin
  2048. Case InstrProp.Ch[Cnt] Of
  2049. Ch_REAX..Ch_REDI: ReadReg(CurProp,TCh2Reg(InstrProp.Ch[Cnt]));
  2050. Ch_WEAX..Ch_RWEDI:
  2051. Begin
  2052. If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
  2053. ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  2054. {$ifdef statedebug}
  2055. hp := new(pai_asm_comment,init(strpnew('destroying '+
  2056. att_reg2str[TCh2Reg(InstrProp.Ch[Cnt])])));
  2057. insertllitem(asml,p,p^.next,hp);
  2058. {$endif statedebug}
  2059. DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]), true);
  2060. End;
  2061. Ch_MEAX..Ch_MEDI:
  2062. AddInstr2RegContents({$ifdef statedebug} asml,{$endif}
  2063. Paicpu(p),TCh2Reg(InstrProp.Ch[Cnt]));
  2064. Ch_CDirFlag: CurProp^.DirFlag := F_NotSet;
  2065. Ch_SDirFlag: CurProp^.DirFlag := F_Set;
  2066. Ch_Rop1: ReadOp(CurProp, Paicpu(p)^.oper[0]);
  2067. Ch_Rop2: ReadOp(CurProp, Paicpu(p)^.oper[1]);
  2068. Ch_ROp3: ReadOp(CurProp, Paicpu(p)^.oper[2]);
  2069. Ch_Wop1..Ch_RWop1:
  2070. Begin
  2071. If (InstrProp.Ch[Cnt] in [Ch_RWop1]) Then
  2072. ReadOp(CurProp, Paicpu(p)^.oper[0]);
  2073. DestroyOp(p, Paicpu(p)^.oper[0]);
  2074. End;
  2075. Ch_Mop1:
  2076. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  2077. Paicpu(p), Paicpu(p)^.oper[0]);
  2078. Ch_Wop2..Ch_RWop2:
  2079. Begin
  2080. If (InstrProp.Ch[Cnt] = Ch_RWop2) Then
  2081. ReadOp(CurProp, Paicpu(p)^.oper[1]);
  2082. DestroyOp(p, Paicpu(p)^.oper[1]);
  2083. End;
  2084. Ch_Mop2:
  2085. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  2086. Paicpu(p), Paicpu(p)^.oper[1]);
  2087. Ch_WOp3..Ch_RWOp3:
  2088. Begin
  2089. If (InstrProp.Ch[Cnt] = Ch_RWOp3) Then
  2090. ReadOp(CurProp, Paicpu(p)^.oper[2]);
  2091. DestroyOp(p, Paicpu(p)^.oper[2]);
  2092. End;
  2093. Ch_Mop3:
  2094. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  2095. Paicpu(p), Paicpu(p)^.oper[2]);
  2096. Ch_WMemEDI:
  2097. Begin
  2098. ReadReg(CurProp, R_EDI);
  2099. FillChar(TmpRef, SizeOf(TmpRef), 0);
  2100. TmpRef.Base := R_EDI;
  2101. tmpRef.index := R_EDI;
  2102. DestroyRefs(p, TmpRef, R_NO)
  2103. End;
  2104. Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
  2105. Else
  2106. Begin
  2107. {$ifdef statedebug}
  2108. hp := new(pai_asm_comment,init(strpnew(
  2109. 'destroying all regs for prev instruction')));
  2110. insertllitem(asml,p, p^.next,hp);
  2111. {$endif statedebug}
  2112. DestroyAllRegs(CurProp);
  2113. End;
  2114. End;
  2115. Inc(Cnt);
  2116. End
  2117. End;
  2118. end;
  2119. End;
  2120. End
  2121. Else
  2122. Begin
  2123. {$ifdef statedebug}
  2124. hp := new(pai_asm_comment,init(strpnew(
  2125. 'destroying all regs: unknown pai: '+tostr(ord(p^.typ)))));
  2126. insertllitem(asml,p, p^.next,hp);
  2127. {$endif statedebug}
  2128. DestroyAllRegs(CurProp);
  2129. End;
  2130. End;
  2131. Inc(InstrCnt);
  2132. GetNextInstruction(p, p);
  2133. End;
  2134. End;
  2135. Function InitDFAPass2(BlockStart, BlockEnd: Pai): Boolean;
  2136. {reserves memory for the PPaiProps in one big memory block when not using
  2137. TP, returns False if not enough memory is available for the optimizer in all
  2138. cases}
  2139. Var p: Pai;
  2140. Count: Longint;
  2141. { TmpStr: String; }
  2142. Begin
  2143. P := BlockStart;
  2144. SkipHead(P);
  2145. NrOfPaiObjs := 0;
  2146. While (P <> BlockEnd) Do
  2147. Begin
  2148. {$IfDef JumpAnal}
  2149. Case P^.Typ Of
  2150. ait_label:
  2151. Begin
  2152. If not labelCanBeSkipped(pai_label(p)) Then
  2153. LTable^[Pai_Label(P)^.l^.labelnr-LoLab].InstrNr := NrOfPaiObjs
  2154. End;
  2155. ait_instruction:
  2156. begin
  2157. if paicpu(p)^.is_jmp then
  2158. begin
  2159. If (pasmlabel(paicpu(P)^.oper[0].sym)^.labelnr >= LoLab) And
  2160. (pasmlabel(paicpu(P)^.oper[0].sym)^.labelnr <= HiLab) Then
  2161. Inc(LTable^[pasmlabel(paicpu(P)^.oper[0].sym)^.labelnr-LoLab].RefsFound);
  2162. end;
  2163. end;
  2164. { ait_instruction:
  2165. Begin
  2166. If (Paicpu(p)^.opcode = A_PUSH) And
  2167. (Paicpu(p)^.oper[0].typ = top_symbol) And
  2168. (PCSymbol(Paicpu(p)^.oper[0])^.offset = 0) Then
  2169. Begin
  2170. TmpStr := StrPas(PCSymbol(Paicpu(p)^.oper[0])^.symbol);
  2171. If}
  2172. End;
  2173. {$EndIf JumpAnal}
  2174. Inc(NrOfPaiObjs);
  2175. GetNextInstruction(p, p);
  2176. End;
  2177. {Uncomment the next line to see how much memory the reloading optimizer needs}
  2178. { Writeln((NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4)));}
  2179. {no need to check mem/maxavail, we've got as much virtual memory as we want}
  2180. If NrOfPaiObjs <> 0 Then
  2181. Begin
  2182. InitDFAPass2 := True;
  2183. GetMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4));
  2184. p := BlockStart;
  2185. SkipHead(p);
  2186. For Count := 1 To NrOfPaiObjs Do
  2187. Begin
  2188. PPaiProp(p^.OptInfo) := @PaiPropBlock^[Count];
  2189. GetNextInstruction(p, p);
  2190. End;
  2191. End
  2192. Else InitDFAPass2 := False;
  2193. End;
  2194. Function DFAPass2(
  2195. {$ifdef statedebug}
  2196. AsmL: PAasmOutPut;
  2197. {$endif statedebug}
  2198. BlockStart, BlockEnd: Pai): Boolean;
  2199. Begin
  2200. If InitDFAPass2(BlockStart, BlockEnd) Then
  2201. Begin
  2202. DoDFAPass2(
  2203. {$ifdef statedebug}
  2204. asml,
  2205. {$endif statedebug}
  2206. BlockStart, BlockEnd);
  2207. DFAPass2 := True
  2208. End
  2209. Else DFAPass2 := False;
  2210. End;
  2211. Procedure ShutDownDFA;
  2212. Begin
  2213. If LabDif <> 0 Then
  2214. FreeMem(LTable, LabDif*SizeOf(TLabelTableItem));
  2215. End;
  2216. End.
  2217. {
  2218. $Log$
  2219. Revision 1.15 2000-09-30 13:07:23 jonas
  2220. * fixed support for -Or with new features of CSE
  2221. Revision 1.14 2000/09/29 23:14:11 jonas
  2222. + writeToMemDestroysContents() and writeDestroysContents() to support the
  2223. new features of the CSE
  2224. Revision 1.13 2000/09/25 09:50:30 jonas
  2225. - removed TP conditional code
  2226. Revision 1.12 2000/09/24 21:19:50 peter
  2227. * delphi compile fixes
  2228. Revision 1.11 2000/09/24 15:06:15 peter
  2229. * use defines.inc
  2230. Revision 1.10 2000/09/22 15:00:20 jonas
  2231. * fixed bug in regsEquivalent (in some rare cases, registers with
  2232. completely unrelated content were considered equivalent) (merged
  2233. from fixes branch)
  2234. Revision 1.9 2000/09/20 15:00:58 jonas
  2235. + much improved CSE: the CSE now searches further back for sequences it
  2236. can reuse. After I've also implemented register renaming, the effect
  2237. should be even better (afaik web bug 1088 will then even be optimized
  2238. properly). I don't know about the slow down factor this adds. Maybe
  2239. a new optimization level should be introduced?
  2240. Revision 1.8 2000/08/25 19:39:18 jonas
  2241. * bugfix to FindRegAlloc function (caused wrong regalloc info in
  2242. some cases) (merged from fixes branch)
  2243. Revision 1.7 2000/08/23 12:55:10 jonas
  2244. * fix for web bug 1112 and a bit of clean up in csopt386 (merged from
  2245. fixes branch)
  2246. Revision 1.6 2000/08/19 17:53:29 jonas
  2247. * fixed a potential bug in destroyregs regarding the removal of
  2248. unused loads
  2249. * added destroyDependingRegs() procedure and use it for the fix in
  2250. the previous commit (safer/more complete than what was done before)
  2251. Revision 1.5 2000/08/19 09:08:59 jonas
  2252. * fixed bug where the contents of a register would not be destroyed
  2253. if another register on which these contents depend is modified
  2254. (not really merged, but same idea as fix in fixes branch,
  2255. LAST_MERGE tag is updated)
  2256. Revision 1.4 2000/07/21 15:19:54 jonas
  2257. * daopt386: changes to getnextinstruction/getlastinstruction so they
  2258. ignore labels who have is_addr set
  2259. + daopt386/csopt386: remove loads of registers which are overwritten
  2260. before their contents are used (especially usefull for removing superfluous
  2261. maybe_loadesi outputs and push/pops transformed by below optimization
  2262. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  2263. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  2264. currently because I don't know whether it's safe to do this under Win32/
  2265. Linux (because of problems we had when using esp as frame pointer on
  2266. those os'es)
  2267. Revision 1.3 2000/07/14 05:11:48 michael
  2268. + Patch to 1.1
  2269. Revision 1.2 2000/07/13 11:32:40 michael
  2270. + removed logs
  2271. }