aoptda.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit contains the assembler optimizer data flow analyzer.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. Unit aoptda;
  20. Interface
  21. uses Aasm, TAoptObj, TAoptCpu;
  22. Type TAsmDFA = Object(TAoptCpu)
  23. { uses the same constructor as TAoptCpu = constructor from TAoptObj }
  24. Destructor Done;
  25. private
  26. { How many instructions are between the current instruction and the }
  27. { last one that modified the register }
  28. NrOfInstrSinceLastMod: TInstrSinceLastMod;
  29. Procedure BuildLabelTableAndFixRegAlloc;
  30. Function FindLoHiLabels(BlockStart: Pai): Pai;
  31. End;
  32. Implementation
  33. uses aoptmsc
  34. {$ifdef i386}
  35. , ao386msc
  36. {$endif i386}
  37. ;
  38. Destructor TAsmDFA.Done;
  39. Begin
  40. End;
  41. Procedure TAsmOptimizer.DoDFAPass2;
  42. { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
  43. { for the instructions between blockstart and blockend. Returns the last pai }
  44. { which has been processed }
  45. Var
  46. CurProp: PPaiProp;
  47. Cnt, InstrCnt : Longint;
  48. InstrProp: TAsmInstrucProp;
  49. UsedRegs: TRegSet;
  50. p, hp, NewBlockStart : Pai;
  51. TmpRef: TReference;
  52. TmpReg: TRegister;
  53. {$ifdef AnalyzeLoops}
  54. TmpState: Byte;
  55. {$endif AnalyzeLoops}
  56. Begin
  57. p := BlockStart;
  58. UsedRegs.init;
  59. UsedRegs.Update(p);
  60. NewBlockStart := SkipHead(p);
  61. InstrCnt := 1;
  62. { done implicitely by the constructor
  63. FillChar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0); }
  64. While (P <> BlockEnd) Do
  65. Begin
  66. CurProp := New(PPaiProp, init);
  67. If (p <> NewBlockStart)
  68. Then
  69. Begin
  70. {$ifdef JumpAnal}
  71. If (p^.Typ <> ait_label) Then
  72. {$endif JumpAnal}
  73. Begin
  74. GetLastInstruction(p, hp);
  75. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  76. CurProp^.CondRegs.Flags :=
  77. PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
  78. End
  79. End;
  80. CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
  81. { CurProp^.CanBeRemoved := False;}
  82. UsedRegs.Update(Pai(p^.Next)));
  83. PPaiProp(p^.OptInfo) := CurProp;
  84. For TmpReg := R_EAX To R_EDI Do
  85. Inc(NrOfInstrSinceLastMod[TmpReg]);
  86. Case p^.typ Of
  87. ait_label:
  88. {$Ifndef JumpAnal}
  89. If (Pai_label(p)^.l^.is_used) Then
  90. CurProp^.DestroyAllRegs;
  91. {$Else JumpAnal}
  92. Begin
  93. If (Pai_Label(p)^.is_used) Then
  94. With LTable^[Pai_Label(p)^.l^.labelnr-LoLab] Do
  95. {$IfDef AnalyzeLoops}
  96. If (RefsFound = Pai_Label(p)^.l^.RefCount)
  97. {$Else AnalyzeLoops}
  98. If (JmpsProcessed = Pai_Label(p)^.l^.RefCount)
  99. {$EndIf AnalyzeLoops}
  100. Then
  101. {all jumps to this label have been found}
  102. {$IfDef AnalyzeLoops}
  103. If (JmpsProcessed > 0)
  104. Then
  105. {$EndIf AnalyzeLoops}
  106. {we've processed at least one jump to this label}
  107. Begin
  108. If (GetLastInstruction(p, hp) And
  109. Not(((hp^.typ = ait_instruction)) And
  110. (pai386_labeled(hp)^.is_jmp))
  111. Then
  112. {previous instruction not a JMP -> the contents of the registers after the
  113. previous intruction has been executed have to be taken into account as well}
  114. For TmpReg := R_EAX to R_EDI Do
  115. Begin
  116. If (CurProp^.Regs[TmpReg].WState <>
  117. PPaiProp(hp^.OptInfo)^.Regs[TmpReg].WState)
  118. Then DestroyReg(CurProp, TmpReg)
  119. End
  120. End
  121. {$IfDef AnalyzeLoops}
  122. Else
  123. {a label from a backward jump (e.g. a loop), no jump to this label has
  124. already been processed}
  125. If GetLastInstruction(p, hp) And
  126. Not(hp^.typ = ait_instruction) And
  127. (pai386_labeled(hp)^.opcode = A_JMP))
  128. Then
  129. {previous instruction not a jmp, so keep all the registers' contents from the
  130. previous instruction}
  131. Begin
  132. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  133. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  134. End
  135. Else
  136. {previous instruction a jmp and no jump to this label processed yet}
  137. Begin
  138. hp := p;
  139. Cnt := InstrCnt;
  140. {continue until we find a jump to the label or a label which has already
  141. been processed}
  142. While GetNextInstruction(hp, hp) And
  143. Not((hp^.typ = ait_instruction) And
  144. (pai386(hp)^.is_jmp) and
  145. (pasmlabel(pai386(hp)^.oper[0].sym)^.labelnr = Pai_Label(p)^.l^.labelnr)) And
  146. Not((hp^.typ = ait_label) And
  147. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].RefsFound
  148. = Pai_Label(hp)^.l^.RefCount) And
  149. (LTable^[Pai_Label(hp)^.l^.labelnr-LoLab].JmpsProcessed > 0)) Do
  150. Inc(Cnt);
  151. If (hp^.typ = ait_label)
  152. Then
  153. {there's a processed label after the current one}
  154. Begin
  155. CurProp^.Regs := PaiPropBlock^[Cnt].Regs;
  156. CurProp^.DirFlag := PaiPropBlock^[Cnt].DirFlag;
  157. End
  158. Else
  159. {there's no label anymore after the current one, or they haven't been
  160. processed yet}
  161. Begin
  162. GetLastInstruction(p, hp);
  163. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  164. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  165. DestroyAllRegs(PPaiProp(hp^.OptInfo))
  166. End
  167. End
  168. {$EndIf AnalyzeLoops}
  169. Else
  170. {not all references to this label have been found, so destroy all registers}
  171. Begin
  172. GetLastInstruction(p, hp);
  173. CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
  174. CurProp^.DirFlag := PPaiProp(hp^.OptInfo)^.DirFlag;
  175. DestroyAllRegs(CurProp)
  176. End;
  177. End;
  178. {$EndIf JumpAnal}
  179. {$ifdef GDB}
  180. ait_stabs, ait_stabn, ait_stab_function_name:;
  181. {$endif GDB}
  182. ait_instruction:
  183. Begin
  184. if pai386(p)^.is_jmp then
  185. begin
  186. {$IfNDef JumpAnal}
  187. ;
  188. {$Else JumpAnal}
  189. With LTable^[pasmlabel(pai386(p)^.oper[0].sym)^.labelnr-LoLab] Do
  190. If (RefsFound = pasmlabel(pai386(p)^.oper[0].sym)^.RefCount) Then
  191. Begin
  192. If (InstrCnt < InstrNr)
  193. Then
  194. {forward jump}
  195. If (JmpsProcessed = 0) Then
  196. {no jump to this label has been processed yet}
  197. Begin
  198. PaiPropBlock^[InstrNr].Regs := CurProp^.Regs;
  199. PaiPropBlock^[InstrNr].DirFlag := CurProp^.DirFlag;
  200. Inc(JmpsProcessed);
  201. End
  202. Else
  203. Begin
  204. For TmpReg := R_EAX to R_EDI Do
  205. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  206. CurProp^.Regs[TmpReg].WState) Then
  207. DestroyReg(@PaiPropBlock^[InstrNr], TmpReg);
  208. Inc(JmpsProcessed);
  209. End
  210. {$ifdef AnalyzeLoops}
  211. Else
  212. { backward jump, a loop for example}
  213. { If (JmpsProcessed > 0) Or
  214. Not(GetLastInstruction(PaiObj, hp) And
  215. (hp^.typ = ait_labeled_instruction) And
  216. (pai386_labeled(hp)^.opcode = A_JMP))
  217. Then}
  218. {instruction prior to label is not a jmp, or at least one jump to the label
  219. has yet been processed}
  220. Begin
  221. Inc(JmpsProcessed);
  222. For TmpReg := R_EAX to R_EDI Do
  223. If (PaiPropBlock^[InstrNr].Regs[TmpReg].WState <>
  224. CurProp^.Regs[TmpReg].WState)
  225. Then
  226. Begin
  227. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  228. Cnt := InstrNr;
  229. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  230. Begin
  231. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  232. Inc(Cnt);
  233. End;
  234. While (Cnt <= InstrCnt) Do
  235. Begin
  236. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  237. Inc(Cnt)
  238. End
  239. End;
  240. End
  241. { Else }
  242. {instruction prior to label is a jmp and no jumps to the label have yet been
  243. processed}
  244. { Begin
  245. Inc(JmpsProcessed);
  246. For TmpReg := R_EAX to R_EDI Do
  247. Begin
  248. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  249. Cnt := InstrNr;
  250. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  251. Begin
  252. PaiPropBlock^[Cnt].Regs[TmpReg] := CurProp^.Regs[TmpReg];
  253. Inc(Cnt);
  254. End;
  255. TmpState := PaiPropBlock^[InstrNr].Regs[TmpReg].WState;
  256. While (TmpState = PaiPropBlock^[Cnt].Regs[TmpReg].WState) Do
  257. Begin
  258. DestroyReg(@PaiPropBlock^[Cnt], TmpReg);
  259. Inc(Cnt);
  260. End;
  261. While (Cnt <= InstrCnt) Do
  262. Begin
  263. Inc(PaiPropBlock^[Cnt].Regs[TmpReg].WState);
  264. Inc(Cnt)
  265. End
  266. End
  267. End}
  268. {$endif AnalyzeLoops}
  269. End;
  270. {$EndIf JumpAnal}
  271. end
  272. else
  273. begin
  274. InstrProp := AsmInstr[PInstr(p)^.opcode];
  275. If IsStoreInstr(p) Then
  276. Begin
  277. CurProp^.ReadReg(PInstr(p)^.oper[StoreSrc].reg);
  278. CurProp^.ReadRef(PInstr(p)^.oper[StoreDst].ref);
  279. CurProp^.DestroyRefs(PInstr(p)^.oper[StoreDst].ref^,
  280. PInstr(p)^.oper[StoreSrc].reg);
  281. End
  282. Else If IsLoadInstr(p) Then
  283. Begin
  284. CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
  285. CurProp^.ReadReg(PInstr(p)^.oper[LoadDst].reg);
  286. TmpReg := RegMaxSize(PInstr(p)^.oper[1].reg);
  287. If RegInRef(TmpReg, Pai386(p)^.oper[0].ref^) And
  288. (CurProp^.Regs[TmpReg].Typ = Con_Ref)
  289. Then
  290. Begin
  291. With CurProp^.Regs[TmpReg] Do
  292. Begin
  293. IncState(WState);
  294. {also store how many instructions are part of the sequence in the first
  295. instructions PPaiProp, so it can be easily accessed from within
  296. CheckSequence}
  297. Inc(NrOfMods, NrOfInstrSinceLastMod[TmpReg]);
  298. PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
  299. NrOfInstrSinceLastMod[TmpReg] := 0;
  300. End;
  301. End
  302. Else
  303. Begin
  304. DestroyReg(CurProp, TmpReg);
  305. If Not(RegInRef(TmpReg, Pai386(p)^.oper[0].ref^)) Then
  306. With CurProp^.Regs[TmpReg] Do
  307. Begin
  308. Typ := Con_Ref;
  309. StartMod := p;
  310. NrOfMods := 1;
  311. End
  312. End;
  313. {$ifdef StateDebug}
  314. hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
  315. InsertLLItem(AsmL, p, p^.next, hp);
  316. {$endif StateDebug}
  317. End;
  318. Top_Const:
  319. Begin
  320. Case Pai386(p)^.oper[1].typ Of
  321. Top_Reg:
  322. Begin
  323. TmpReg := Reg32(Pai386(p)^.oper[1].reg);
  324. With CurProp^.Regs[TmpReg] Do
  325. Begin
  326. DestroyReg(CurProp, TmpReg);
  327. typ := Con_Const;
  328. StartMod := p;
  329. End
  330. End;
  331. Top_Ref:
  332. Begin
  333. ReadRef(CurProp, Pai386(p)^.oper[1].ref);
  334. DestroyRefs(P, Pai386(p)^.oper[1].ref^, R_NO);
  335. End;
  336. End;
  337. End;
  338. End;
  339. End;
  340. A_IMUL:
  341. Begin
  342. ReadOp(CurProp, Pai386(p)^.oper[0]);
  343. ReadOp(CurProp, Pai386(p)^.oper[1]);
  344. If (Pai386(p)^.oper[2].typ = top_none) Then
  345. If (Pai386(p)^.oper[1].typ = top_none) Then
  346. Begin
  347. DestroyReg(CurProp, R_EAX);
  348. DestroyReg(CurProp, R_EDX)
  349. End
  350. Else
  351. {$ifdef arithopt}
  352. AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[1])
  353. {$else arithopt}
  354. DestroyOp(p, Pai386(p)^.oper[1])
  355. {$endif arithopt}
  356. Else
  357. {$ifdef arithopt}
  358. AddInstr2OpContents(Pai386(p), Pai386(p)^.oper[2]);
  359. {$else arithopt}
  360. DestroyOp(p, Pai386(p)^.oper[2]);
  361. {$endif arithopt}
  362. End;
  363. A_XOR:
  364. Begin
  365. ReadOp(CurProp, Pai386(p)^.oper[0]);
  366. ReadOp(CurProp, Pai386(p)^.oper[1]);
  367. If (Pai386(p)^.oper[0].typ = top_reg) And
  368. (Pai386(p)^.oper[1].typ = top_reg) And
  369. (Pai386(p)^.oper[0].reg = Pai386(p)^.oper[1].reg)
  370. Then
  371. Begin
  372. DestroyReg(CurProp, Pai386(p)^.oper[0].reg);
  373. CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].typ := Con_Const;
  374. CurProp^.Regs[Reg32(Pai386(p)^.oper[0].reg)].StartMod := Pointer(0)
  375. End
  376. Else
  377. DestroyOp(p, Pai386(p)^.oper[1]);
  378. End
  379. Else
  380. Begin
  381. Cnt := 1;
  382. While (Cnt <= MaxCh) And
  383. (InstrProp.Ch[Cnt] <> C_None) Do
  384. Begin
  385. Case InstrProp.Ch[Cnt] Of
  386. C_REAX..C_REDI: ReadReg(CurProp,TCh2Reg(InstrProp.Ch[Cnt]));
  387. C_WEAX..C_RWEDI:
  388. Begin
  389. If (InstrProp.Ch[Cnt] >= C_RWEAX) Then
  390. ReadReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  391. DestroyReg(CurProp, TCh2Reg(InstrProp.Ch[Cnt]));
  392. End;
  393. {$ifdef arithopt}
  394. C_MEAX..C_MEDI:
  395. AddInstr2RegContents({$ifdef statedebug} asml, {$endif}
  396. Pai386(p),
  397. TCh2Reg(InstrProp.Ch[Cnt]));
  398. {$endif arithopt}
  399. C_CDirFlag: CurProp^.DirFlag := F_NotSet;
  400. C_SDirFlag: CurProp^.DirFlag := F_Set;
  401. C_Rop1: ReadOp(CurProp, Pai386(p)^.oper[0]);
  402. C_Rop2: ReadOp(CurProp, Pai386(p)^.oper[1]);
  403. C_ROp3: ReadOp(CurProp, Pai386(p)^.oper[2]);
  404. C_Wop1..C_RWop1:
  405. Begin
  406. If (InstrProp.Ch[Cnt] in [C_RWop1]) Then
  407. ReadOp(CurProp, Pai386(p)^.oper[0]);
  408. DestroyOp(p, Pai386(p)^.oper[0]);
  409. End;
  410. {$ifdef arithopt}
  411. C_Mop1:
  412. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  413. Pai386(p), Pai386(p)^.oper[0]);
  414. {$endif arithopt}
  415. C_Wop2..C_RWop2:
  416. Begin
  417. If (InstrProp.Ch[Cnt] = C_RWop2) Then
  418. ReadOp(CurProp, Pai386(p)^.oper[1]);
  419. DestroyOp(p, Pai386(p)^.oper[1]);
  420. End;
  421. {$ifdef arithopt}
  422. C_Mop2:
  423. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  424. Pai386(p), Pai386(p)^.oper[1]);
  425. {$endif arithopt}
  426. C_WOp3..C_RWOp3:
  427. Begin
  428. If (InstrProp.Ch[Cnt] = C_RWOp3) Then
  429. ReadOp(CurProp, Pai386(p)^.oper[2]);
  430. DestroyOp(p, Pai386(p)^.oper[2]);
  431. End;
  432. {$ifdef arithopt}
  433. C_Mop3:
  434. AddInstr2OpContents({$ifdef statedebug} asml, {$endif}
  435. Pai386(p), Pai386(p)^.oper[2]);
  436. {$endif arithopt}
  437. C_WMemEDI:
  438. Begin
  439. ReadReg(CurProp, R_EDI);
  440. FillChar(TmpRef, SizeOf(TmpRef), 0);
  441. TmpRef.Base := R_EDI;
  442. DestroyRefs(p, TmpRef, R_NO)
  443. End;
  444. C_RFlags, C_WFlags, C_RWFlags, C_FPU:
  445. Else
  446. Begin
  447. DestroyAllRegs(CurProp);
  448. End;
  449. End;
  450. Inc(Cnt);
  451. End
  452. End;
  453. end;
  454. End;
  455. End
  456. Else
  457. Begin
  458. DestroyAllRegs(CurProp);
  459. End;
  460. End;
  461. Inc(InstrCnt);
  462. GetNextInstruction(p, p);
  463. End;
  464. End;
  465. End.