LLVM: lib/MCA/InstrBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
23
24#define DEBUG_TYPE "llvm-mca-instrbuilder"
25
26namespace llvm {
27namespace mca {
28
30
36 : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), IM(im), FirstCallInst(true),
37 FirstReturnInst(true), CallLatency(cl) {
41}
42
48
49
50 using ResourcePlusCycles = std::pair<uint64_t, ResourceUsage>;
52
53
54
55
56
57
58
59
60
61
62
64
66 APInt Buffers(NumProcResources, 0);
67
68 bool AllInOrderResources = true;
69 bool AnyDispatchHazards = false;
74#ifndef NDEBUG
76 << "Ignoring invalid write of zero cycles on processor resource "
77 << PR.Name << "\n";
79 << " (write index #" << I << ")\n";
80#endif
81 continue;
82 }
83
86 AllInOrderResources = false;
87 } else {
89 AnyDispatchHazards |= (PR.BufferSize == 0);
90 AllInOrderResources &= (PR.BufferSize <= 1);
91 }
92
98 }
99 }
100
101 ID.MustIssueImmediately = AllInOrderResources && AnyDispatchHazards;
102
103
104
105 sort(Worklist, [](const ResourcePlusCycles &A, const ResourcePlusCycles &B) {
108 if (popcntA < popcntB)
109 return true;
110 if (popcntA > popcntB)
111 return false;
113 });
114
115 uint64_t UsedResourceUnits = 0;
116 uint64_t UsedResourceGroups = 0;
117 uint64_t UnitsFromResourceGroups = 0;
118
119
120
121 ID.HasPartiallyOverlappingGroups = false;
122
123 for (unsigned I = 0, E = Worklist.size(); I < E; ++I) {
124 ResourcePlusCycles &A = Worklist[I];
125 if (.second.size()) {
128 continue;
129 }
130
131 ID.Resources.emplace_back(A);
132 uint64_t NormalizedMask = A.first;
133
135 UsedResourceUnits |= A.first;
136 } else {
137
139 if (UnitsFromResourceGroups & NormalizedMask)
140 ID.HasPartiallyOverlappingGroups = true;
141
142 UnitsFromResourceGroups |= NormalizedMask;
143 UsedResourceGroups |= (A.first ^ NormalizedMask);
144 }
145
146 for (unsigned J = I + 1; J < E; ++J) {
147 ResourcePlusCycles &B = Worklist[J];
148 if ((NormalizedMask & B.first) == NormalizedMask) {
149 B.second.CS.subtract(A.second.size() - SuperResources[A.first]);
151 B.second.NumUnits++;
152 }
153 }
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 for (ResourcePlusCycles &RPC : ID.Resources) {
174 if (llvm::popcount(RPC.first) > 1 && !RPC.second.isReserved()) {
175
178 if (RPC.second.NumUnits > (unsigned)llvm::popcount(Mask)) {
179 RPC.second.setReserved();
180 RPC.second.NumUnits = MaxResourceUnits;
181 }
182 }
183 }
184
185
186 for (const std::pair<uint64_t, unsigned> &SR : SuperResources) {
187 for (unsigned I = 1, E = NumProcResources; I < E; ++I) {
190 continue;
191
192 uint64_t Mask = ProcResourceMasks[I];
193 if (Mask != SR.first && ((Mask & SR.first) == SR.first))
195 }
196 }
197
199 ID.UsedProcResUnits = UsedResourceUnits;
200 ID.UsedProcResGroups = UsedResourceGroups;
201
203 for (const std::pair<uint64_t, ResourceUsage> &R : ID.Resources)
204 dbgs() << "\t\tResource Mask=" << format_hex(R.first, 16) << ", "
205 << "Reserved=" << R.second.isReserved() << ", "
206 << "#Units=" << R.second.NumUnits << ", "
207 << "cy=" << R.second.size() << '\n';
209 while (BufferIDs) {
210 uint64_t Current = BufferIDs & (-BufferIDs);
211 dbgs() << "\t\tBuffer Mask=" << format_hex(Current, 16) << '\n';
212 BufferIDs ^= Current;
213 }
214 dbgs() << "\t\t Used Units=" << format_hex(ID.UsedProcResUnits, 16) << '\n';
215 dbgs() << "\t\tUsed Groups=" << format_hex(ID.UsedProcResGroups, 16)
216 << '\n';
217 dbgs() << "\t\tHasPartiallyOverlappingGroups="
218 << ID.HasPartiallyOverlappingGroups << '\n';
219 });
220}
221
225 unsigned CallLatency) {
226 if (MCDesc.isCall()) {
227
228
229 ID.MaxLatency = CallLatency;
230 return;
231 }
232
234
235
236 ID.MaxLatency = Latency < 0 ? CallLatency : static_cast(Latency);
237}
238
240
242 unsigned NumExplicitDefs = MCDesc.getNumDefs();
245 if (Op.isReg())
246 --NumExplicitDefs;
247 }
248
249 if (NumExplicitDefs) {
250 return make_error<InstructionError>(
251 "Expected more register operand definitions.", MCI);
252 }
253
255
258 std::string Message =
259 "expected a register operand for an optional definition. Instruction "
260 "has not been correctly analyzed.";
261 return make_error<InstructionError>(Message, MCI);
262 }
263 }
264
266}
267
268void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
269 unsigned SchedClassID) {
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 unsigned NumExplicitDefs = MCDesc.getNumDefs();
318 unsigned NumImplicitDefs = MCDesc.implicit_defs().size();
320 unsigned TotalDefs = NumExplicitDefs + NumImplicitDefs;
322 TotalDefs++;
323
325 ID.Writes.resize(TotalDefs + NumVariadicOps);
326
327
328
329 unsigned CurrentDef = 0;
330 unsigned OptionalDefIdx = MCDesc.getNumOperands() - 1;
331 unsigned i = 0;
332 for (; i < MCI.getNumOperands() && CurrentDef < NumExplicitDefs; ++i) {
334 if (.isReg())
335 continue;
336
337 if (MCDesc.operands()[CurrentDef].isOptionalDef()) {
338 OptionalDefIdx = CurrentDef++;
339 continue;
340 }
342 CurrentDef++;
343 continue;
344 }
345
346 WriteDescriptor &Write = ID.Writes[CurrentDef];
347 Write.OpIndex = i;
348 if (CurrentDef < NumWriteLatencyEntries) {
349 const MCWriteLatencyEntry &WLE =
351
353 WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
354 Write.SClassOrWriteResourceID = WLE.WriteResourceID;
355 } else {
356
357 Write.Latency = ID.MaxLatency;
358 Write.SClassOrWriteResourceID = 0;
359 }
360 Write.IsOptionalDef = false;
362 dbgs() << "\t\t[Def] OpIdx=" << Write.OpIndex
363 << ", Latency=" << Write.Latency
364 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
365 });
366 CurrentDef++;
367 }
368
369 assert(CurrentDef == NumExplicitDefs &&
370 "Expected more register operand definitions.");
371 for (CurrentDef = 0; CurrentDef < NumImplicitDefs; ++CurrentDef) {
372 unsigned Index = NumExplicitDefs + CurrentDef;
374 Write.OpIndex = ~CurrentDef;
376 if (Index < NumWriteLatencyEntries) {
377 const MCWriteLatencyEntry &WLE =
379
381 WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
382 Write.SClassOrWriteResourceID = WLE.WriteResourceID;
383 } else {
384
385 Write.Latency = ID.MaxLatency;
386 Write.SClassOrWriteResourceID = 0;
387 }
388
389 Write.IsOptionalDef = false;
390 assert(Write.RegisterID != 0 && "Expected a valid phys register!");
392 dbgs() << "\t\t[Def][I] OpIdx=" << ~Write.OpIndex
393 << ", PhysReg=" << MRI.getName(Write.RegisterID)
394 << ", Latency=" << Write.Latency
395 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
396 });
397 }
398
400 WriteDescriptor &Write = ID.Writes[NumExplicitDefs + NumImplicitDefs];
401 Write.OpIndex = OptionalDefIdx;
402
403 Write.Latency = ID.MaxLatency;
404 Write.SClassOrWriteResourceID = 0;
405 Write.IsOptionalDef = true;
407 dbgs() << "\t\t[Def][O] OpIdx=" << Write.OpIndex
408 << ", Latency=" << Write.Latency
409 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
410 });
411 }
412
413 if (!NumVariadicOps)
414 return;
415
417 CurrentDef = NumExplicitDefs + NumImplicitDefs + MCDesc.hasOptionalDef();
419 I < NumVariadicOps && !AssumeUsesOnly; ++I, ++OpIndex) {
421 if (.isReg())
422 continue;
424 continue;
425
426 WriteDescriptor &Write = ID.Writes[CurrentDef];
428
429 Write.Latency = ID.MaxLatency;
430 Write.SClassOrWriteResourceID = 0;
431 Write.IsOptionalDef = false;
432 ++CurrentDef;
434 dbgs() << "\t\t[Def][V] OpIdx=" << Write.OpIndex
435 << ", Latency=" << Write.Latency
436 << ", WriteResourceID=" << Write.SClassOrWriteResourceID << '\n';
437 });
438 }
439
440 ID.Writes.resize(CurrentDef);
441}
442
443void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
444 unsigned SchedClassID) {
445 const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
446 unsigned NumExplicitUses = MCDesc.getNumOperands() - MCDesc.getNumDefs();
447 unsigned NumImplicitUses = MCDesc.implicit_uses().size();
448
449 if (MCDesc.hasOptionalDef())
450 --NumExplicitUses;
451 unsigned NumVariadicOps = MCI.getNumOperands() - MCDesc.getNumOperands();
452 unsigned TotalUses = NumExplicitUses + NumImplicitUses + NumVariadicOps;
453 ID.Reads.resize(TotalUses);
454 unsigned CurrentUse = 0;
455 for (unsigned I = 0, OpIndex = MCDesc.getNumDefs(); I < NumExplicitUses;
457 const MCOperand &Op = MCI.getOperand(OpIndex);
458 if (.isReg())
459 continue;
461 continue;
462
463 ReadDescriptor &Read = ID.Reads[CurrentUse];
466 Read.SchedClassID = SchedClassID;
467 ++CurrentUse;
469 << ", UseIndex=" << Read.UseIndex << '\n');
470 }
471
472
473
474 for (unsigned I = 0; I < NumImplicitUses; ++I) {
475 ReadDescriptor &Read = ID.Reads[CurrentUse + I];
476 Read.OpIndex = ~I;
477 Read.UseIndex = NumExplicitUses + I;
478 Read.RegisterID = MCDesc.implicit_uses()[I];
480 continue;
481 Read.SchedClassID = SchedClassID;
483 << ", UseIndex=" << Read.UseIndex << ", RegisterID="
484 << MRI.getName(Read.RegisterID) << '\n');
485 }
486
487 CurrentUse += NumImplicitUses;
488
489 bool AssumeDefsOnly = MCDesc.variadicOpsAreDefs();
490 for (unsigned I = 0, OpIndex = MCDesc.getNumOperands();
491 I < NumVariadicOps && !AssumeDefsOnly; ++I, ++OpIndex) {
492 const MCOperand &Op = MCI.getOperand(OpIndex);
493 if (.isReg())
494 continue;
495
496 ReadDescriptor &Read = ID.Reads[CurrentUse];
498 Read.UseIndex = NumExplicitUses + NumImplicitUses + I;
499 Read.SchedClassID = SchedClassID;
500 ++CurrentUse;
502 << ", UseIndex=" << Read.UseIndex << '\n');
503 }
504
505 ID.Reads.resize(CurrentUse);
506}
507
513
514 return TypeHash;
515}
516
520 InstructionHash =
522 }
523 return InstructionHash;
524}
525
526Error InstrBuilder::verifyInstrDesc(const InstrDesc &ID,
527 const MCInst &MCI) const {
528 if (ID.NumMicroOps != 0)
530
531 bool UsesBuffers = ID.UsedBuffers;
532 bool UsesResources = .Resources.empty();
533 if (!UsesBuffers && !UsesResources)
535
536
537
538 StringRef Message = "found an inconsistent instruction that decodes to zero "
539 "opcodes and that consumes scheduler resources.";
540 return make_error<InstructionError>(std::string(Message), MCI);
541}
542
543Expected InstrBuilder::getVariantSchedClassID(const MCInst &MCI,
544 unsigned SchedClassID) {
547 while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant())
548 SchedClassID =
550
551 if (!SchedClassID) {
552 return make_error<InstructionError>(
553 "unable to resolve scheduling class for write variant.", MCI);
554 }
555
556 return SchedClassID;
557}
558
559Expected<const InstrDesc &>
560InstrBuilder::createInstrDescImpl(const MCInst &MCI,
561 const SmallVector<Instrument *> &IVec) {
563 "Itineraries are not yet supported!");
564
565
566 unsigned short Opcode = MCI.getOpcode();
567 const MCInstrDesc &MCDesc = MCII.get(Opcode);
569
570
571
572 unsigned SchedClassID = IM.getSchedClassID(MCII, MCI, IVec);
573 bool IsVariant = SM.getSchedClassDesc(SchedClassID)->isVariant();
574
575
576 if (IsVariant) {
577 Expected VariantSchedClassIDOrErr =
578 getVariantSchedClassID(MCI, SchedClassID);
579 if (!VariantSchedClassIDOrErr) {
580 return VariantSchedClassIDOrErr.takeError();
581 }
582
583 SchedClassID = *VariantSchedClassIDOrErr;
584 }
585
586
587 const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
589 return make_error<InstructionError>(
590 "found an unsupported instruction in the input assembly sequence", MCI);
591 }
592
594 LLVM_DEBUG(dbgs() << "\t\tSchedClassID=" << SchedClassID << '\n');
595 LLVM_DEBUG(dbgs() << "\t\tOpcode=" << Opcode << '\n');
596
597
598 std::unique_ptr ID = std::make_unique();
599 ID->NumMicroOps = SCDesc.NumMicroOps;
600 ID->SchedClassID = SchedClassID;
601
602 if (MCDesc.isCall() && FirstCallInst) {
603
604 WithColor::warning() << "found a call in the input assembly sequence.\n";
605 WithColor::note() << "call instructions are not correctly modeled. "
606 << "Assume a latency of " << CallLatency << "cy.\n";
607 FirstCallInst = false;
608 }
609
610 if (MCDesc.isReturn() && FirstReturnInst) {
612 << " assembly sequence.\n";
613 WithColor::note() << "program counter updates are ignored.\n";
614 FirstReturnInst = false;
615 }
616
619
621 return std::move(Err);
622
623 populateWrites(*ID, MCI, SchedClassID);
624 populateReads(*ID, MCI, SchedClassID);
625
626 LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
627 LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');
628
629
630 if (Error Err = verifyInstrDesc(*ID, MCI))
631 return std::move(Err);
632
633
634 bool IsVariadic = MCDesc.isVariadic();
635 if ((ID->IsRecyclable = !IsVariadic && !IsVariant)) {
636 auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID);
637 Descriptors[DKey] = std::move(ID);
638 return *Descriptors[DKey];
639 }
640
641 auto VDKey = std::make_pair(hashMCInst(MCI), SchedClassID);
643 !VariantDescriptors.contains(VDKey) &&
644 "Expected VariantDescriptors to not already have a value for this key.");
645 VariantDescriptors[VDKey] = std::move(ID);
646 return *VariantDescriptors[VDKey];
647}
648
649Expected<const InstrDesc &>
650InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI,
651 const SmallVector<Instrument *> &IVec) {
652
653 unsigned SchedClassID = IM.getSchedClassID(MCII, MCI, IVec);
654
655 auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID);
656 if (Descriptors.find_as(DKey) != Descriptors.end())
657 return *Descriptors[DKey];
658
659 Expected VariantSchedClassIDOrErr =
660 getVariantSchedClassID(MCI, SchedClassID);
661 if (!VariantSchedClassIDOrErr) {
662 return VariantSchedClassIDOrErr.takeError();
663 }
664
665 SchedClassID = *VariantSchedClassIDOrErr;
666
667 auto VDKey = std::make_pair(hashMCInst(MCI), SchedClassID);
668 auto It = VariantDescriptors.find(VDKey);
669 if (It != VariantDescriptors.end())
670 return *It->second;
671
672 return createInstrDescImpl(MCI, IVec);
673}
674
675STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc");
676
681 if (!DescOrErr)
685 std::unique_ptr CreatedIS;
686 bool IsInstRecycled = false;
687
688 if (.IsRecyclable)
689 ++NumVariantInst;
690
691 if (D.IsRecyclable && InstRecycleCB) {
692 if (auto *I = InstRecycleCB(D)) {
693 NewIS = I;
695 IsInstRecycled = true;
696 }
697 }
698 if (!IsInstRecycled) {
699 CreatedIS = std::make_unique(D, MCI.getOpcode());
700 NewIS = CreatedIS.get();
701 }
702
706
713
714
716
717 bool IsZeroIdiom = false;
718 bool IsDepBreaking = false;
719 if (MCIA) {
721 IsZeroIdiom = MCIA->isZeroIdiom(MCI, Mask, ProcID);
722 IsDepBreaking =
726 }
727
728
730 size_t Idx = 0U;
733
735
736 if (.isReg())
737 continue;
738 RegID = Op.getReg();
739 } else {
740
742 }
743
744
745 if (!RegID)
746 continue;
747
748
750 if (IsInstRecycled && Idx < NewIS->getUses().size()) {
753 } else {
754 NewIS->getUses().emplace_back(RD, RegID);
755 RS = &NewIS->getUses().back();
757 }
758
759 if (IsDepBreaking) {
760
761
762 if (Mask.isZero()) {
765 } else {
766
767
768
769
770
771 if (Mask.getBitWidth() > RD.UseIndex) {
772
775 }
776 }
777 }
778 }
779 if (IsInstRecycled && Idx < NewIS->getUses().size())
781
782
783 if (D.Writes.empty()) {
784 if (IsInstRecycled)
785 return llvm::make_error(NewIS);
786 else
787 return std::move(CreatedIS);
788 }
789
790
791
792 APInt WriteMask(D.Writes.size(), 0);
793
794
795
796 if (MCIA)
798
799
800 unsigned WriteIndex = 0;
801 Idx = 0U;
805
806
808 ++WriteIndex;
809 continue;
810 }
811
812 assert(RegID && "Expected a valid register ID!");
813 if (IsInstRecycled && Idx < NewIS->getDefs().size()) {
816 WriteMask[WriteIndex],
817 IsZeroIdiom);
818 } else {
819 NewIS->getDefs().emplace_back(WD, RegID,
820 WriteMask[WriteIndex],
821 IsZeroIdiom);
823 }
824 ++WriteIndex;
825 }
826 if (IsInstRecycled && Idx < NewIS->getDefs().size())
828
829 if (IsInstRecycled)
830 return llvm::make_error(NewIS);
831 else
832 return std::move(CreatedIS);
833}
834}
835}
unsigned const MachineRegisterInfo * MRI
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
A builder class for instructions that are statically analyzed by llvm-mca.
while(!ToSimplify.empty())
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class represents an Operation in the Expression.
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getFlags() const
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
virtual bool isOptimizableRegisterMove(const MCInst &MI, unsigned CPUID) const
Returns true if MI is a candidate for move elimination.
virtual bool isDependencyBreaking(const MCInst &MI, APInt &Mask, unsigned CPUID) const
Returns true if MI is a dependency breaking instruction for the subtarget associated with CPUID .
virtual bool isZeroIdiom(const MCInst &MI, APInt &Mask, unsigned CPUID) const
Returns true if MI is a dependency breaking zero-idiom for the given subtarget.
virtual bool clearsSuperRegisters(const MCRegisterInfo &MRI, const MCInst &Inst, APInt &Writes) const
Returns true if at least one of the register writes performed by.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool variadicOpsAreDefs() const
Return true if variadic operands of this instruction are definitions.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by other flags.
bool isCall() const
Return true if the instruction is a call.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Instances of this class represent operands of the MCInst class.
MCRegister getReg() const
Returns the register number.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
const char * getName(MCRegister RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register.
bool isConstant(MCRegister RegNo) const
Returns true if the given register is constant.
Wrapper class representing physical registers. Should be passed by value.
Generic base class for all target subtargets.
virtual unsigned resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID) const
Resolve a variant scheduling class for the given MCInst and CPU.
const MCWriteLatencyEntry * getWriteLatencyEntry(const MCSchedClassDesc *SC, unsigned DefIdx) const
const MCWriteProcResEntry * getWriteProcResBegin(const MCSchedClassDesc *SC) const
Return an iterator at the first process resource consumed by the given scheduling class.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
An opaque object representing a hash code.
Expected< std::unique_ptr< Instruction > > createInstruction(const MCInst &MCI, const SmallVector< Instrument * > &IVec)
void setEndGroup(bool newVal)
void setRetireOOO(bool newVal)
SmallVectorImpl< WriteState > & getDefs()
void setBeginGroup(bool newVal)
SmallVectorImpl< ReadState > & getUses()
void setHasSideEffects(bool newVal)
void setMayStore(bool newVal)
void setOptimizableMove()
void setMayLoad(bool newVal)
An instruction propagated through the simulated instruction pipeline.
This class allows targets to optionally customize the logic that resolves scheduling class IDs.
virtual unsigned getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI, const SmallVector< Instrument * > &IVec) const
Given an MCInst and a vector of Instrument, a target can return a SchedClassID.
Tracks register operand latency in cycles.
void setIndependentFromDef()
Tracks uses of a register definition (e.g.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
hash_code hashMCInst(const MCInst &MCI)
static void initializeUsedResources(InstrDesc &ID, const MCSchedClassDesc &SCDesc, const MCSubtargetInfo &STI, ArrayRef< uint64_t > ProcResourceMasks)
hash_code hashMCOperand(const MCOperand &MCO)
static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc, const MCSchedClassDesc &SCDesc, const MCSubtargetInfo &STI, unsigned CallLatency)
void computeProcResourceMasks(const MCSchedModel &SM, MutableArrayRef< uint64_t > Masks)
Populates vector Masks with processor resource masks.
unsigned getResourceStateIndex(uint64_t Mask)
static Error verifyOperands(const MCInstrDesc &MCDesc, const MCInst &MCI)
This is an optimization pass for GlobalISel generic memory operations.
int popcount(T Value) noexcept
Count the number of set bits in a value.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
DWARFExpression::Operation Op
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Define a kind of processor resource that will be modeled by the scheduler.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
static const unsigned short InvalidNumMicroOps
uint16_t NumWriteLatencyEntries
uint16_t NumWriteProcResEntries
Machine model for scheduling, bundling, and heuristics.
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
unsigned getProcessorID() const
unsigned getNumProcResourceKinds() const
bool hasInstrSchedModel() const
Does this machine model include instruction-level scheduling.
static int computeInstrLatency(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the latency value for the scheduling class.
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
uint16_t ReleaseAtCycle
Cycle at which the resource will be released by an instruction, relatively to the cycle in which the ...
An instruction descriptor.
A register read descriptor.
bool isImplicitRead() const
Helper used by class InstrDesc to describe how hardware resources are used.
A register write descriptor.
bool isImplicitWrite() const