LLVM: lib/MCA/HardwareUnits/RegisterFile.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
19
20#define DEBUG_TYPE "llvm-mca"
21
22namespace llvm {
23namespace mca {
24
25const unsigned WriteRef::INVALID_IID = std::numeric_limits::max();
26
31
33 : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
34 Write(WS) {}
35
37 assert(Write && Write->isExecuted() && "Cannot commit before write back!");
38 RegisterID = Write->getRegisterID();
39 WriteResID = Write->getWriteResourceID();
40 Write = nullptr;
41}
42
44 assert(Write && Write->isExecuted() && "Not executed!");
45 WriteBackCycle = Cycle;
46}
47
49 return isValid() && (!Write || Write->isExecuted());
50}
51
56
58 if (Write)
59 return Write->getWriteResourceID();
60 return WriteResID;
61}
62
64 if (Write)
65 return Write->getRegisterID();
66 return RegisterID;
67}
68
70 unsigned NumRegs)
71 : MRI(mri),
72 RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
73 ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
75}
76
77void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
78
79
80
81
84 return;
85
86
87
88
90
91
92 for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
94 assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
95
96
97
102 }
103}
104
106 for (RegisterMappingTracker &RMT : RegisterFiles)
107 RMT.NumMoveEliminated = 0;
108}
109
111 assert(IS && IS->isExecuted() && "Unexpected internal state found!");
113 if (WS.isEliminated())
114 return;
115
116 MCPhysReg RegID = WS.getRegisterID();
117
118
119
120 if (!RegID)
121 continue;
122
124 "The number of cycles should be known at this point!");
125 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
126
127 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
128 if (RenameAs && RenameAs != RegID)
129 RegID = RenameAs;
130
131 WriteRef &WR = RegisterMappings[RegID].first;
134
135 for (MCPhysReg I : MRI.subregs(RegID)) {
136 WriteRef &OtherWR = RegisterMappings[I].first;
139 }
140
141 if (!WS.clearsSuperRegisters())
142 continue;
143
144 for (MCPhysReg I : MRI.superregs(RegID)) {
145 WriteRef &OtherWR = RegisterMappings[I].first;
148 }
149 }
150}
151
154
155
156
157
158
159 unsigned RegisterFileIndex = RegisterFiles.size();
162
163
164
165
166
167
168
169 if (Entries.empty())
170 return;
171
172
176 RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
177 IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
178 if (IPC.first && IPC.first != RegisterFileIndex) {
179
180
181
182 errs() << "warning: register " << MRI.getName(Reg)
183 << " defined in multiple register files.";
184 }
185 IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
186 Entry.RenameAs = Reg;
187 Entry.AllowMoveElimination = RCE.AllowMoveElimination;
188
189
191 RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second;
192 if (!OtherEntry.IndexPlusCost.first &&
193 (!OtherEntry.RenameAs ||
194 MRI.isSuperRegister(I, OtherEntry.RenameAs))) {
195 OtherEntry.IndexPlusCost = IPC;
196 OtherEntry.RenameAs = Reg;
197 }
198 }
199 }
200 }
201}
202
203void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
205 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
206 unsigned Cost = Entry.IndexPlusCost.second;
207 if (RegisterFileIndex) {
208 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
209 RMT.NumUsedPhysRegs += Cost;
210 UsedPhysRegs[RegisterFileIndex] += Cost;
211 }
212
213
214 RegisterFiles[0].NumUsedPhysRegs += Cost;
215 UsedPhysRegs[0] += Cost;
216}
217
218void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
220 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
221 unsigned Cost = Entry.IndexPlusCost.second;
222 if (RegisterFileIndex) {
223 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
224 RMT.NumUsedPhysRegs -= Cost;
225 FreedPhysRegs[RegisterFileIndex] += Cost;
226 }
227
228
229 RegisterFiles[0].NumUsedPhysRegs -= Cost;
230 FreedPhysRegs[0] += Cost;
231}
232
237
238
239
240 if (!RegID)
241 return;
242
244 dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
245 << MRI.getName(RegID) << "]\n";
246 });
247
248
249
250
251
252
253
254
255
256
257
258
259
260
263 bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
264 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
265 WS.setPRF(RRI.IndexPlusCost.first);
266
267 if (RRI.RenameAs && RRI.RenameAs != RegID) {
268 RegID = RRI.RenameAs;
269 WriteRef &OtherWrite = RegisterMappings[RegID].first;
270
272
273
274
275 ShouldAllocatePhysRegs = false;
276
278 if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
279
280 assert(!IsEliminated && "Unexpected partial update!");
282 }
283 }
284 }
285
286
289 ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
292 ZeroRegisters.setBitVal(I, IsWriteZero);
293
294
295
296 if (!IsEliminated) {
297
298
299 const WriteRef &OtherWrite = RegisterMappings[RegID].first;
303
304 if (ShouldAllocatePhysRegs)
305 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
306 return;
307 }
308 }
309
310
311 RegisterMappings[RegID].first = Write;
312 RegisterMappings[RegID].second.AliasRegID = 0U;
315 RegisterMappings[I].first = Write;
316 RegisterMappings[I].second.AliasRegID = 0U;
317 }
318
319
320
321
322 if (ShouldAllocatePhysRegs)
323 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
324 }
325
327 return;
328
329 for (MCPhysReg I : MRI.superregs(RegID)) {
330 if (!IsEliminated) {
331 RegisterMappings[I].first = Write;
332 RegisterMappings[I].second.AliasRegID = 0U;
333 }
334
335 ZeroRegisters.setBitVal(I, IsWriteZero);
336 }
337}
338
341
342
344 return;
345
347
348
349
350 if (!RegID)
351 return;
352
354 "Invalidating a write of unknown cycles!");
355 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
356
357 bool ShouldFreePhysRegs = !WS.isWriteZero();
358 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
359 if (RenameAs && RenameAs != RegID) {
360 RegID = RenameAs;
361
363
364 ShouldFreePhysRegs = false;
365 }
366 }
367
368 if (ShouldFreePhysRegs)
369 freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
370
371 WriteRef &WR = RegisterMappings[RegID].first;
374
375 for (MCPhysReg I : MRI.subregs(RegID)) {
376 WriteRef &OtherWR = RegisterMappings[I].first;
379 }
380
382 return;
383
384 for (MCPhysReg I : MRI.superregs(RegID)) {
385 WriteRef &OtherWR = RegisterMappings[I].first;
388 }
389}
390
392 unsigned RegisterFileIndex) const {
393 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
394 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
395 const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
396
397
398 const RegisterRenamingInfo &RRIFrom = RMFrom.second;
399 if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
400 return false;
401
402 const RegisterRenamingInfo &RRITo = RMTo.second;
403 if (RRITo.IndexPlusCost.first != RegisterFileIndex)
404 return false;
405
406
407
408 if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
409 return false;
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425 if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
427 return false;
428
429 bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
430 return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
431}
432
435 if (Writes.size() != Reads.size())
436 return false;
437
438
439
440
441
442 if (Writes.empty() || Writes.size() > 2)
443 return false;
444
445
446 const RegisterRenamingInfo &RRInfo =
447 RegisterMappings[Writes[0].getRegisterID()].second;
448 unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
449 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
450
451
452 if (RMT.MaxMoveEliminatedPerCycle &&
453 (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
454 return false;
455
456 for (size_t I = 0, E = Writes.size(); I < E; ++I) {
460 return false;
461 }
462
463 for (size_t I = 0, E = Writes.size(); I < E; ++I) {
466
467 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
468 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
469 const RegisterRenamingInfo &RRIFrom = RMFrom.second;
470 const RegisterRenamingInfo &RRITo = RMTo.second;
471
472
474 RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
476
477 const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
478 if (RMAlias.AliasRegID)
479 AliasedReg = RMAlias.AliasRegID;
480
481 RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
484 RegisterMappings[I].second.AliasRegID = AliasedReg;
485
486 if (ZeroRegisters[RS.getRegisterID()]) {
488 RS.setReadZero();
489 }
490
492 RMT.NumMoveEliminated++;
493 }
494
495 return true;
496}
497
500 assert((!Write || Write->getCyclesLeft() <= 0) &&
501 "Inconsistent state found!");
502 return WriteBackCycle;
503}
504
509
517 MCPhysReg RegID = RS.getRegisterID();
518 assert(RegID && RegID < RegisterMappings.size());
519 LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
520 << MRI.getName(RegID) << '\n');
521
522
523 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
524 if (RRI.AliasRegID)
525 RegID = RRI.AliasRegID;
526
527 const WriteRef &WR = RegisterMappings[RegID].first;
533 if (ReadAdvance < 0) {
535 if (Elapsed < static_cast<unsigned>(-ReadAdvance))
537 }
538 }
539
540
541 for (MCPhysReg I : MRI.subregs(RegID)) {
542 const WriteRef &WR = RegisterMappings[I].first;
548 if (ReadAdvance < 0) {
550 if (Elapsed < static_cast<unsigned>(-ReadAdvance))
552 }
553 }
554 }
555
556
557 if (Writes.size() > 1) {
560 });
562 Writes.resize(std::distance(Writes.begin(), It));
563 }
564
566 for (const WriteRef &WR : Writes) {
568 dbgs() << "[PRF] Found a dependent use of Register "
569 << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
571 }
572 });
573}
574
581
585
587 for (const WriteRef &WR : Writes) {
588 const WriteState *WS = WR.getWriteState();
591
594 continue;
595
596 Hazard.RegisterID = WR.getRegisterID();
598 continue;
599 }
600
601 int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
602 if (CyclesLeft > 0) {
603 if (Hazard.CyclesLeft < CyclesLeft) {
604 Hazard.RegisterID = WR.getRegisterID();
606 }
607 }
608 }
610
611 for (const WriteRef &WR : CommittedWrites) {
612 unsigned WriteResID = WR.getWriteResourceID();
615 int CyclesLeft = NegReadAdvance - Elapsed;
616 assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
617 if (Hazard.CyclesLeft < CyclesLeft) {
618 Hazard.RegisterID = WR.getRegisterID();
620 }
621 }
622
623 return Hazard;
624}
625
628 MCPhysReg RegID = RS.getRegisterID();
629 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
630 RS.setPRF(RRI.IndexPlusCost.first);
631 if (RS.isIndependentFromDef())
632 return;
633
634 if (ZeroRegisters[RS.getRegisterID()])
635 RS.setReadZero();
636
639 collectWrites(STI, RS, DependentWrites, CompletedWrites);
640 RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
641
642
643
644
648 for (WriteRef &WR : DependentWrites) {
649 unsigned WriteResID = WR.getWriteResourceID();
650 WriteState &WS = *WR.getWriteState();
652 WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
653 }
654
655 for (WriteRef &WR : CompletedWrites) {
656 unsigned WriteResID = WR.getWriteResourceID();
657 assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
659 unsigned ReadAdvance = static_cast<unsigned>(
662 assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
663 RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
664 ReadAdvance - Elapsed);
665 }
666}
667
670
671
672 for (const MCPhysReg RegID : Regs) {
673 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
674 const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
675 if (Entry.first)
676 NumPhysRegs[Entry.first] += Entry.second;
677 NumPhysRegs[0] += Entry.second;
678 }
679
680 unsigned Response = 0;
682 unsigned NumRegs = NumPhysRegs[I];
683 if (!NumRegs)
684 continue;
685
686 const RegisterMappingTracker &RMT = RegisterFiles[I];
687 if (!RMT.NumPhysRegs) {
688
689
690 continue;
691 }
692
693 if (RMT.NumPhysRegs < NumRegs) {
694
695
696
697
699 dbgs() << "[PRF] Not enough registers in the register file.\n");
700
701
702
703
704
705
706 NumRegs = RMT.NumPhysRegs;
707 }
708
709 if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
710 Response |= (1U << I);
711 }
712
713 return Response;
714}
715
716#ifndef NDEBUG
721 else
722 dbgs() << "(null)";
723}
724
726 for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
727 const RegisterMapping &RM = RegisterMappings[I];
728 const RegisterRenamingInfo &RRI = RM.second;
729 if (ZeroRegisters[I]) {
730 dbgs() << MRI.getName(I) << ", " << I
731 << ", PRF=" << RRI.IndexPlusCost.first
732 << ", Cost=" << RRI.IndexPlusCost.second
733 << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
734 << ",";
735 RM.first.dump();
736 dbgs() << '\n';
737 }
738 }
739
741 dbgs() << "Register File #" << I;
742 const RegisterMappingTracker &RMT = RegisterFiles[I];
743 dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
744 << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
745 }
746}
747#endif
748
749}
750}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
This file defines a register mapping file class.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
MCRegisterClass - Base class of TargetRegisterClass.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx, unsigned WriteResID) const
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SmallVectorImpl< WriteState > & getDefs()
An instruction propagated through the simulated instruction pipeline.
Tracks register operand latency in cycles.
void collectWrites(const MCSubtargetInfo &STI, const ReadState &RS, SmallVectorImpl< WriteRef > &Writes, SmallVectorImpl< WriteRef > &CommittedWrites) const
Definition RegisterFile.cpp:510
unsigned getElapsedCyclesFromWriteBack(const WriteRef &WR) const
Definition RegisterFile.cpp:505
void dump() const
Definition RegisterFile.cpp:725
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
Definition RegisterFile.cpp:233
unsigned isAvailable(ArrayRef< MCPhysReg > Regs) const
Definition RegisterFile.cpp:668
unsigned getNumRegisterFiles() const
void cycleStart()
Definition RegisterFile.cpp:105
RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, const ReadState &RS) const
Definition RegisterFile.cpp:576
void removeRegisterWrite(const WriteState &WS, MutableArrayRef< unsigned > FreedPhysRegs)
Definition RegisterFile.cpp:339
bool tryEliminateMoveOrSwap(MutableArrayRef< WriteState > Writes, MutableArrayRef< ReadState > Reads)
Definition RegisterFile.cpp:433
RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri, unsigned NumRegs=0)
Definition RegisterFile.cpp:69
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const
Definition RegisterFile.cpp:626
bool canEliminateMove(const WriteState &WS, const ReadState &RS, unsigned PRFIndex) const
Definition RegisterFile.cpp:391
void onInstructionExecuted(Instruction *IS)
Definition RegisterFile.cpp:110
A reference to a register write.
unsigned getSourceIndex() const
unsigned getWriteResourceID() const
Definition RegisterFile.cpp:57
void notifyExecuted(unsigned Cycle)
Definition RegisterFile.cpp:43
bool isWriteZero() const
Definition RegisterFile.cpp:52
void commit()
Definition RegisterFile.cpp:36
void dump() const
Definition RegisterFile.cpp:717
const WriteState * getWriteState() const
MCPhysReg getRegisterID() const
Definition RegisterFile.cpp:63
unsigned getWriteBackCycle() const
Definition RegisterFile.cpp:498
bool hasKnownWriteBackCycle() const
Definition RegisterFile.cpp:48
Tracks uses of a register definition (e.g.
bool isEliminated() const
unsigned getLatency() const
void setPRF(unsigned PRF)
int getCyclesLeft() const
bool clearsSuperRegisters() const
MCPhysReg getRegisterID() const
unsigned getWriteResourceID() const
LLVM_ABI void addUser(unsigned IID, ReadState *Use, int ReadAdvance)
static std::function< bool(MCPhysReg)> isNonArtificial(const MCRegisterInfo &MRI)
Definition RegisterFile.cpp:28
constexpr int UNKNOWN_CYCLES
This is an optimization pass for GlobalISel generic memory operations.
auto unique(Range &&R, Predicate P)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Specify the cost of a register definition in terms of number of physical register allocated at regist...
A register file descriptor.
uint16_t NumRegisterCostEntries
bool AllowZeroMoveEliminationOnly
uint16_t RegisterCostEntryIdx
uint16_t MaxMovesEliminatedPerCycle
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
bool hasExtraProcessorInfo() const
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
const MCExtraProcessorInfo & getExtraProcessorInfo() const
A register read descriptor.