daopt386.pas 94 KB

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