RegisterFile.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. ///
  10. /// This file defines a register mapping file class. This class is responsible
  11. /// for managing hardware register files and the tracking of data dependencies
  12. /// between registers.
  13. ///
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/MCA/HardwareUnits/RegisterFile.h"
  16. #include "llvm/MCA/Instruction.h"
  17. #include "llvm/Support/Debug.h"
  18. #define DEBUG_TYPE "llvm-mca"
  19. namespace llvm {
  20. namespace mca {
  21. const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
  22. WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
  23. : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
  24. Write(WS) {}
  25. void WriteRef::commit() {
  26. assert(Write && Write->isExecuted() && "Cannot commit before write back!");
  27. RegisterID = Write->getRegisterID();
  28. WriteResID = Write->getWriteResourceID();
  29. Write = nullptr;
  30. }
  31. void WriteRef::notifyExecuted(unsigned Cycle) {
  32. assert(Write && Write->isExecuted() && "Not executed!");
  33. WriteBackCycle = Cycle;
  34. }
  35. bool WriteRef::hasKnownWriteBackCycle() const {
  36. return isValid() && (!Write || Write->isExecuted());
  37. }
  38. bool WriteRef::isWriteZero() const {
  39. assert(isValid() && "Invalid null WriteState found!");
  40. return getWriteState()->isWriteZero();
  41. }
  42. unsigned WriteRef::getWriteResourceID() const {
  43. if (Write)
  44. return Write->getWriteResourceID();
  45. return WriteResID;
  46. }
  47. MCPhysReg WriteRef::getRegisterID() const {
  48. if (Write)
  49. return Write->getRegisterID();
  50. return RegisterID;
  51. }
  52. RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
  53. unsigned NumRegs)
  54. : MRI(mri),
  55. RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
  56. ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
  57. initialize(SM, NumRegs);
  58. }
  59. void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
  60. // Create a default register file that "sees" all the machine registers
  61. // declared by the target. The number of physical registers in the default
  62. // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
  63. // means: this register file has an unbounded number of physical registers.
  64. RegisterFiles.emplace_back(NumRegs);
  65. if (!SM.hasExtraProcessorInfo())
  66. return;
  67. // For each user defined register file, allocate a RegisterMappingTracker
  68. // object. The size of every register file, as well as the mapping between
  69. // register files and register classes is specified via tablegen.
  70. const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
  71. // Skip invalid register file at index 0.
  72. for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
  73. const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
  74. assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
  75. // The cost of a register definition is equivalent to the number of
  76. // physical registers that are allocated at register renaming stage.
  77. unsigned Length = RF.NumRegisterCostEntries;
  78. const MCRegisterCostEntry *FirstElt =
  79. &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
  80. addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
  81. }
  82. }
  83. void RegisterFile::cycleStart() {
  84. for (RegisterMappingTracker &RMT : RegisterFiles)
  85. RMT.NumMoveEliminated = 0;
  86. }
  87. void RegisterFile::onInstructionExecuted(Instruction *IS) {
  88. assert(IS && IS->isExecuted() && "Unexpected internal state found!");
  89. for (WriteState &WS : IS->getDefs()) {
  90. if (WS.isEliminated())
  91. return;
  92. MCPhysReg RegID = WS.getRegisterID();
  93. // This allows InstrPostProcess to remove register Defs
  94. // by setting their RegisterID to 0.
  95. if (!RegID)
  96. continue;
  97. assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
  98. "The number of cycles should be known at this point!");
  99. assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
  100. MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
  101. if (RenameAs && RenameAs != RegID)
  102. RegID = RenameAs;
  103. WriteRef &WR = RegisterMappings[RegID].first;
  104. if (WR.getWriteState() == &WS)
  105. WR.notifyExecuted(CurrentCycle);
  106. for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  107. WriteRef &OtherWR = RegisterMappings[*I].first;
  108. if (OtherWR.getWriteState() == &WS)
  109. OtherWR.notifyExecuted(CurrentCycle);
  110. }
  111. if (!WS.clearsSuperRegisters())
  112. continue;
  113. for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  114. WriteRef &OtherWR = RegisterMappings[*I].first;
  115. if (OtherWR.getWriteState() == &WS)
  116. OtherWR.notifyExecuted(CurrentCycle);
  117. }
  118. }
  119. }
  120. void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
  121. ArrayRef<MCRegisterCostEntry> Entries) {
  122. // A default register file is always allocated at index #0. That register file
  123. // is mainly used to count the total number of mappings created by all
  124. // register files at runtime. Users can limit the number of available physical
  125. // registers in register file #0 through the command line flag
  126. // `-register-file-size`.
  127. unsigned RegisterFileIndex = RegisterFiles.size();
  128. RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
  129. RF.AllowZeroMoveEliminationOnly);
  130. // Special case where there is no register class identifier in the set.
  131. // An empty set of register classes means: this register file contains all
  132. // the physical registers specified by the target.
  133. // We optimistically assume that a register can be renamed at the cost of a
  134. // single physical register. The constructor of RegisterFile ensures that
  135. // a RegisterMapping exists for each logical register defined by the Target.
  136. if (Entries.empty())
  137. return;
  138. // Now update the cost of individual registers.
  139. for (const MCRegisterCostEntry &RCE : Entries) {
  140. const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
  141. for (const MCPhysReg Reg : RC) {
  142. RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
  143. IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
  144. if (IPC.first && IPC.first != RegisterFileIndex) {
  145. // The only register file that is allowed to overlap is the default
  146. // register file at index #0. The analysis is inaccurate if register
  147. // files overlap.
  148. errs() << "warning: register " << MRI.getName(Reg)
  149. << " defined in multiple register files.";
  150. }
  151. IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
  152. Entry.RenameAs = Reg;
  153. Entry.AllowMoveElimination = RCE.AllowMoveElimination;
  154. // Assume the same cost for each sub-register.
  155. for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
  156. RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
  157. if (!OtherEntry.IndexPlusCost.first &&
  158. (!OtherEntry.RenameAs ||
  159. MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
  160. OtherEntry.IndexPlusCost = IPC;
  161. OtherEntry.RenameAs = Reg;
  162. }
  163. }
  164. }
  165. }
  166. }
  167. void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
  168. MutableArrayRef<unsigned> UsedPhysRegs) {
  169. unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
  170. unsigned Cost = Entry.IndexPlusCost.second;
  171. if (RegisterFileIndex) {
  172. RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
  173. RMT.NumUsedPhysRegs += Cost;
  174. UsedPhysRegs[RegisterFileIndex] += Cost;
  175. }
  176. // Now update the default register mapping tracker.
  177. RegisterFiles[0].NumUsedPhysRegs += Cost;
  178. UsedPhysRegs[0] += Cost;
  179. }
  180. void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
  181. MutableArrayRef<unsigned> FreedPhysRegs) {
  182. unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
  183. unsigned Cost = Entry.IndexPlusCost.second;
  184. if (RegisterFileIndex) {
  185. RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
  186. RMT.NumUsedPhysRegs -= Cost;
  187. FreedPhysRegs[RegisterFileIndex] += Cost;
  188. }
  189. // Now update the default register mapping tracker.
  190. RegisterFiles[0].NumUsedPhysRegs -= Cost;
  191. FreedPhysRegs[0] += Cost;
  192. }
  193. void RegisterFile::addRegisterWrite(WriteRef Write,
  194. MutableArrayRef<unsigned> UsedPhysRegs) {
  195. WriteState &WS = *Write.getWriteState();
  196. MCPhysReg RegID = WS.getRegisterID();
  197. // This allows InstrPostProcess to remove register Defs
  198. // by setting their RegisterID to 0.
  199. if (!RegID)
  200. return;
  201. LLVM_DEBUG({
  202. dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
  203. << MRI.getName(RegID) << "]\n";
  204. });
  205. // If RenameAs is equal to RegID, then RegID is subject to register renaming
  206. // and false dependencies on RegID are all eliminated.
  207. // If RenameAs references the invalid register, then we optimistically assume
  208. // that it can be renamed. In the absence of tablegen descriptors for register
  209. // files, RenameAs is always set to the invalid register ID. In all other
  210. // cases, RenameAs must be either equal to RegID, or it must reference a
  211. // super-register of RegID.
  212. // If RenameAs is a super-register of RegID, then a write to RegID has always
  213. // a false dependency on RenameAs. The only exception is for when the write
  214. // implicitly clears the upper portion of the underlying register.
  215. // If a write clears its super-registers, then it is renamed as `RenameAs`.
  216. bool IsWriteZero = WS.isWriteZero();
  217. bool IsEliminated = WS.isEliminated();
  218. bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
  219. const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
  220. WS.setPRF(RRI.IndexPlusCost.first);
  221. if (RRI.RenameAs && RRI.RenameAs != RegID) {
  222. RegID = RRI.RenameAs;
  223. WriteRef &OtherWrite = RegisterMappings[RegID].first;
  224. if (!WS.clearsSuperRegisters()) {
  225. // The processor keeps the definition of `RegID` together with register
  226. // `RenameAs`. Since this partial write is not renamed, no physical
  227. // register is allocated.
  228. ShouldAllocatePhysRegs = false;
  229. WriteState *OtherWS = OtherWrite.getWriteState();
  230. if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
  231. // This partial write has a false dependency on RenameAs.
  232. assert(!IsEliminated && "Unexpected partial update!");
  233. OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
  234. }
  235. }
  236. }
  237. // Update zero registers.
  238. MCPhysReg ZeroRegisterID =
  239. WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
  240. ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
  241. for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
  242. ZeroRegisters.setBitVal(*I, IsWriteZero);
  243. // If this move has been eliminated, then method tryEliminateMoveOrSwap should
  244. // have already updated all the register mappings.
  245. if (!IsEliminated) {
  246. // Check if this is one of multiple writes performed by this
  247. // instruction to register RegID.
  248. const WriteRef &OtherWrite = RegisterMappings[RegID].first;
  249. const WriteState *OtherWS = OtherWrite.getWriteState();
  250. if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
  251. if (OtherWS->getLatency() > WS.getLatency()) {
  252. // Conservatively keep the slowest write on RegID.
  253. if (ShouldAllocatePhysRegs)
  254. allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
  255. return;
  256. }
  257. }
  258. // Update the mapping for register RegID including its sub-registers.
  259. RegisterMappings[RegID].first = Write;
  260. RegisterMappings[RegID].second.AliasRegID = 0U;
  261. for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  262. RegisterMappings[*I].first = Write;
  263. RegisterMappings[*I].second.AliasRegID = 0U;
  264. }
  265. // No physical registers are allocated for instructions that are optimized
  266. // in hardware. For example, zero-latency data-dependency breaking
  267. // instructions don't consume physical registers.
  268. if (ShouldAllocatePhysRegs)
  269. allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
  270. }
  271. if (!WS.clearsSuperRegisters())
  272. return;
  273. for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  274. if (!IsEliminated) {
  275. RegisterMappings[*I].first = Write;
  276. RegisterMappings[*I].second.AliasRegID = 0U;
  277. }
  278. ZeroRegisters.setBitVal(*I, IsWriteZero);
  279. }
  280. }
  281. void RegisterFile::removeRegisterWrite(
  282. const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
  283. // Early exit if this write was eliminated. A write eliminated at register
  284. // renaming stage generates an alias, and it is not added to the PRF.
  285. if (WS.isEliminated())
  286. return;
  287. MCPhysReg RegID = WS.getRegisterID();
  288. // This allows InstrPostProcess to remove register Defs
  289. // by setting their RegisterID to 0.
  290. if (!RegID)
  291. return;
  292. assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
  293. "Invalidating a write of unknown cycles!");
  294. assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
  295. bool ShouldFreePhysRegs = !WS.isWriteZero();
  296. MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
  297. if (RenameAs && RenameAs != RegID) {
  298. RegID = RenameAs;
  299. if (!WS.clearsSuperRegisters()) {
  300. // Keep the definition of `RegID` together with register `RenameAs`.
  301. ShouldFreePhysRegs = false;
  302. }
  303. }
  304. if (ShouldFreePhysRegs)
  305. freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
  306. WriteRef &WR = RegisterMappings[RegID].first;
  307. if (WR.getWriteState() == &WS)
  308. WR.commit();
  309. for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  310. WriteRef &OtherWR = RegisterMappings[*I].first;
  311. if (OtherWR.getWriteState() == &WS)
  312. OtherWR.commit();
  313. }
  314. if (!WS.clearsSuperRegisters())
  315. return;
  316. for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  317. WriteRef &OtherWR = RegisterMappings[*I].first;
  318. if (OtherWR.getWriteState() == &WS)
  319. OtherWR.commit();
  320. }
  321. }
  322. bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
  323. unsigned RegisterFileIndex) const {
  324. const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
  325. const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
  326. const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
  327. // From and To must be owned by the PRF at index `RegisterFileIndex`.
  328. const RegisterRenamingInfo &RRIFrom = RMFrom.second;
  329. if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
  330. return false;
  331. const RegisterRenamingInfo &RRITo = RMTo.second;
  332. if (RRITo.IndexPlusCost.first != RegisterFileIndex)
  333. return false;
  334. // Early exit if the destination register is from a register class that
  335. // doesn't allow move elimination.
  336. if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
  337. return false;
  338. // We only allow move elimination for writes that update a full physical
  339. // register. On X86, move elimination is possible with 32-bit general purpose
  340. // registers because writes to those registers are not partial writes. If a
  341. // register move is a partial write, then we conservatively assume that move
  342. // elimination fails, since it would either trigger a partial update, or the
  343. // issue of a merge opcode.
  344. //
  345. // Note that this constraint may be lifted in future. For example, we could
  346. // make this model more flexible, and let users customize the set of registers
  347. // (i.e. register classes) that allow move elimination.
  348. //
  349. // For now, we assume that there is a strong correlation between registers
  350. // that allow move elimination, and how those same registers are renamed in
  351. // hardware.
  352. if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
  353. if (!WS.clearsSuperRegisters())
  354. return false;
  355. bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
  356. return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
  357. }
  358. bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
  359. MutableArrayRef<ReadState> Reads) {
  360. if (Writes.size() != Reads.size())
  361. return false;
  362. // This logic assumes that writes and reads are contributed by a register move
  363. // or a register swap operation. In particular, it assumes a simple register
  364. // move if there is only one write. It assumes a swap operation if there are
  365. // exactly two writes.
  366. if (Writes.empty() || Writes.size() > 2)
  367. return false;
  368. // All registers must be owned by the same PRF.
  369. const RegisterRenamingInfo &RRInfo =
  370. RegisterMappings[Writes[0].getRegisterID()].second;
  371. unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
  372. RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
  373. // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
  374. if (RMT.MaxMoveEliminatedPerCycle &&
  375. (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
  376. return false;
  377. for (size_t I = 0, E = Writes.size(); I < E; ++I) {
  378. const ReadState &RS = Reads[I];
  379. const WriteState &WS = Writes[E - (I + 1)];
  380. if (!canEliminateMove(WS, RS, RegisterFileIndex))
  381. return false;
  382. }
  383. for (size_t I = 0, E = Writes.size(); I < E; ++I) {
  384. ReadState &RS = Reads[I];
  385. WriteState &WS = Writes[E - (I + 1)];
  386. const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
  387. const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
  388. const RegisterRenamingInfo &RRIFrom = RMFrom.second;
  389. const RegisterRenamingInfo &RRITo = RMTo.second;
  390. // Construct an alias.
  391. MCPhysReg AliasedReg =
  392. RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
  393. MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
  394. const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
  395. if (RMAlias.AliasRegID)
  396. AliasedReg = RMAlias.AliasRegID;
  397. RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
  398. for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
  399. RegisterMappings[*I].second.AliasRegID = AliasedReg;
  400. if (ZeroRegisters[RS.getRegisterID()]) {
  401. WS.setWriteZero();
  402. RS.setReadZero();
  403. }
  404. WS.setEliminated();
  405. RMT.NumMoveEliminated++;
  406. }
  407. return true;
  408. }
  409. unsigned WriteRef::getWriteBackCycle() const {
  410. assert(hasKnownWriteBackCycle() && "Instruction not executed!");
  411. assert((!Write || Write->getCyclesLeft() <= 0) &&
  412. "Inconsistent state found!");
  413. return WriteBackCycle;
  414. }
  415. unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
  416. assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
  417. return CurrentCycle - WR.getWriteBackCycle();
  418. }
  419. void RegisterFile::collectWrites(
  420. const MCSubtargetInfo &STI, const ReadState &RS,
  421. SmallVectorImpl<WriteRef> &Writes,
  422. SmallVectorImpl<WriteRef> &CommittedWrites) const {
  423. const ReadDescriptor &RD = RS.getDescriptor();
  424. const MCSchedModel &SM = STI.getSchedModel();
  425. const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
  426. MCPhysReg RegID = RS.getRegisterID();
  427. assert(RegID && RegID < RegisterMappings.size());
  428. LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
  429. << MRI.getName(RegID) << '\n');
  430. // Check if this is an alias.
  431. const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
  432. if (RRI.AliasRegID)
  433. RegID = RRI.AliasRegID;
  434. const WriteRef &WR = RegisterMappings[RegID].first;
  435. if (WR.getWriteState()) {
  436. Writes.push_back(WR);
  437. } else if (WR.hasKnownWriteBackCycle()) {
  438. unsigned WriteResID = WR.getWriteResourceID();
  439. int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
  440. if (ReadAdvance < 0) {
  441. unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
  442. if (Elapsed < static_cast<unsigned>(-ReadAdvance))
  443. CommittedWrites.push_back(WR);
  444. }
  445. }
  446. // Handle potential partial register updates.
  447. for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
  448. const WriteRef &WR = RegisterMappings[*I].first;
  449. if (WR.getWriteState()) {
  450. Writes.push_back(WR);
  451. } else if (WR.hasKnownWriteBackCycle()) {
  452. unsigned WriteResID = WR.getWriteResourceID();
  453. int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
  454. if (ReadAdvance < 0) {
  455. unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
  456. if (Elapsed < static_cast<unsigned>(-ReadAdvance))
  457. CommittedWrites.push_back(WR);
  458. }
  459. }
  460. }
  461. // Remove duplicate entries and resize the input vector.
  462. if (Writes.size() > 1) {
  463. sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
  464. return Lhs.getWriteState() < Rhs.getWriteState();
  465. });
  466. auto It = std::unique(Writes.begin(), Writes.end());
  467. Writes.resize(std::distance(Writes.begin(), It));
  468. }
  469. LLVM_DEBUG({
  470. for (const WriteRef &WR : Writes) {
  471. const WriteState &WS = *WR.getWriteState();
  472. dbgs() << "[PRF] Found a dependent use of Register "
  473. << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
  474. << WR.getSourceIndex() << ")\n";
  475. }
  476. });
  477. }
  478. RegisterFile::RAWHazard
  479. RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
  480. const ReadState &RS) const {
  481. RAWHazard Hazard;
  482. SmallVector<WriteRef, 4> Writes;
  483. SmallVector<WriteRef, 4> CommittedWrites;
  484. const MCSchedModel &SM = STI.getSchedModel();
  485. const ReadDescriptor &RD = RS.getDescriptor();
  486. const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
  487. collectWrites(STI, RS, Writes, CommittedWrites);
  488. for (const WriteRef &WR : Writes) {
  489. const WriteState *WS = WR.getWriteState();
  490. unsigned WriteResID = WS->getWriteResourceID();
  491. int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
  492. if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
  493. if (Hazard.isValid())
  494. continue;
  495. Hazard.RegisterID = WR.getRegisterID();
  496. Hazard.CyclesLeft = UNKNOWN_CYCLES;
  497. continue;
  498. }
  499. int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
  500. if (CyclesLeft > 0) {
  501. if (Hazard.CyclesLeft < CyclesLeft) {
  502. Hazard.RegisterID = WR.getRegisterID();
  503. Hazard.CyclesLeft = CyclesLeft;
  504. }
  505. }
  506. }
  507. Writes.clear();
  508. for (const WriteRef &WR : CommittedWrites) {
  509. unsigned WriteResID = WR.getWriteResourceID();
  510. int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
  511. int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
  512. int CyclesLeft = NegReadAdvance - Elapsed;
  513. assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
  514. if (Hazard.CyclesLeft < CyclesLeft) {
  515. Hazard.RegisterID = WR.getRegisterID();
  516. Hazard.CyclesLeft = CyclesLeft;
  517. }
  518. }
  519. return Hazard;
  520. }
  521. void RegisterFile::addRegisterRead(ReadState &RS,
  522. const MCSubtargetInfo &STI) const {
  523. MCPhysReg RegID = RS.getRegisterID();
  524. const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
  525. RS.setPRF(RRI.IndexPlusCost.first);
  526. if (RS.isIndependentFromDef())
  527. return;
  528. if (ZeroRegisters[RS.getRegisterID()])
  529. RS.setReadZero();
  530. SmallVector<WriteRef, 4> DependentWrites;
  531. SmallVector<WriteRef, 4> CompletedWrites;
  532. collectWrites(STI, RS, DependentWrites, CompletedWrites);
  533. RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
  534. // We know that this read depends on all the writes in DependentWrites.
  535. // For each write, check if we have ReadAdvance information, and use it
  536. // to figure out in how many cycles this read will be available.
  537. const ReadDescriptor &RD = RS.getDescriptor();
  538. const MCSchedModel &SM = STI.getSchedModel();
  539. const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
  540. for (WriteRef &WR : DependentWrites) {
  541. unsigned WriteResID = WR.getWriteResourceID();
  542. WriteState &WS = *WR.getWriteState();
  543. int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
  544. WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
  545. }
  546. for (WriteRef &WR : CompletedWrites) {
  547. unsigned WriteResID = WR.getWriteResourceID();
  548. assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
  549. assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
  550. unsigned ReadAdvance = static_cast<unsigned>(
  551. -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
  552. unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
  553. assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
  554. RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
  555. ReadAdvance - Elapsed);
  556. }
  557. }
  558. unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
  559. SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
  560. // Find how many new mappings must be created for each register file.
  561. for (const MCPhysReg RegID : Regs) {
  562. const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
  563. const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
  564. if (Entry.first)
  565. NumPhysRegs[Entry.first] += Entry.second;
  566. NumPhysRegs[0] += Entry.second;
  567. }
  568. unsigned Response = 0;
  569. for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
  570. unsigned NumRegs = NumPhysRegs[I];
  571. if (!NumRegs)
  572. continue;
  573. const RegisterMappingTracker &RMT = RegisterFiles[I];
  574. if (!RMT.NumPhysRegs) {
  575. // The register file has an unbounded number of microarchitectural
  576. // registers.
  577. continue;
  578. }
  579. if (RMT.NumPhysRegs < NumRegs) {
  580. // The current register file is too small. This may occur if the number of
  581. // microarchitectural registers in register file #0 was changed by the
  582. // users via flag -reg-file-size. Alternatively, the scheduling model
  583. // specified a too small number of registers for this register file.
  584. LLVM_DEBUG(
  585. dbgs() << "[PRF] Not enough registers in the register file.\n");
  586. // FIXME: Normalize the instruction register count to match the
  587. // NumPhysRegs value. This is a highly unusual case, and is not expected
  588. // to occur. This normalization is hiding an inconsistency in either the
  589. // scheduling model or in the value that the user might have specified
  590. // for NumPhysRegs.
  591. NumRegs = RMT.NumPhysRegs;
  592. }
  593. if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
  594. Response |= (1U << I);
  595. }
  596. return Response;
  597. }
  598. #ifndef NDEBUG
  599. void WriteRef::dump() const {
  600. dbgs() << "IID=" << getSourceIndex() << ' ';
  601. if (isValid())
  602. getWriteState()->dump();
  603. else
  604. dbgs() << "(null)";
  605. }
  606. void RegisterFile::dump() const {
  607. for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
  608. const RegisterMapping &RM = RegisterMappings[I];
  609. const RegisterRenamingInfo &RRI = RM.second;
  610. if (ZeroRegisters[I]) {
  611. dbgs() << MRI.getName(I) << ", " << I
  612. << ", PRF=" << RRI.IndexPlusCost.first
  613. << ", Cost=" << RRI.IndexPlusCost.second
  614. << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
  615. << ",";
  616. RM.first.dump();
  617. dbgs() << '\n';
  618. }
  619. }
  620. for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
  621. dbgs() << "Register File #" << I;
  622. const RegisterMappingTracker &RMT = RegisterFiles[I];
  623. dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
  624. << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
  625. }
  626. }
  627. #endif
  628. } // namespace mca
  629. } // namespace llvm