LLVM: lib/CodeGen/StackMaps.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
31#include
32#include
33#include
34#include
35#include
36
37using namespace llvm;
38
39#define DEBUG_TYPE "stackmaps"
40
43 cl::desc("Specify the stackmap encoding version (default = 3)"));
44
45const char *StackMaps::WSMP = "Stack Maps: ";
46
49 MI.getOperand(Idx).getImm() == StackMaps::ConstantOp);
50 const auto &MO = MI.getOperand(Idx + 1);
52 return MO.getImm();
53}
54
58 "invalid stackmap definition");
59}
60
62 : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
63 ->getOperand(0).isImplicit()) {
64#ifndef NDEBUG
65 unsigned CheckStartIdx = 0, e = MI->getNumOperands();
66 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
67 MI->getOperand(CheckStartIdx).isDef() &&
68 ->getOperand(CheckStartIdx).isImplicit())
69 ++CheckStartIdx;
70
71 assert(getMetaIdx() == CheckStartIdx &&
72 "Unexpected additional definition in Patchpoint intrinsic.");
73#endif
74}
75
77 if (!StartIdx)
79
80
81 unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
82 while (ScratchIdx < e &&
87 ++ScratchIdx;
88
89 assert(ScratchIdx != e && "No scratch register available");
90 return ScratchIdx;
91}
92
94
97 CurIdx++;
98 while (NumAllocas--)
100 return CurIdx + 1;
101}
102
104
107 CurIdx++;
108 while (NumGCPtrs--)
110 return CurIdx + 1;
111}
112
114
116 unsigned NumDeoptArgs = getConstMetaVal(*MI, CurIdx - 1);
117 CurIdx++;
118 while (NumDeoptArgs--) {
120 }
121 return CurIdx + 1;
122}
123
126 unsigned NumGCPtrs = getConstMetaVal(*MI, NumGCPtrsIdx - 1);
127 if (NumGCPtrs == 0)
128 return -1;
129 ++NumGCPtrsIdx;
130 assert(NumGCPtrsIdx < MI->getNumOperands());
131 return (int)NumGCPtrsIdx;
132}
133
138 CurIdx++;
139 for (unsigned N = 0; N < GCMapSize; ++N) {
142 GCMap.push_back(std::make_pair(B, D));
143 }
144
145 return GCMapSize;
146}
147
149 unsigned FoldableAreaStart = getVarIdx();
151 if (MO.getOperandNo() >= FoldableAreaStart)
152 break;
153 if (MO.isReg() && MO.getReg() == Reg)
154 return false;
155 }
156 return true;
157}
158
160 if (MI->getOpcode() != TargetOpcode::STATEPOINT)
161 return false;
163}
164
168}
169
171 assert(CurIdx < MI->getNumOperands() && "Bad meta arg index");
172 const auto &MO = MI->getOperand(CurIdx);
173 if (MO.isImm()) {
174 switch (MO.getImm()) {
175 default:
177 case StackMaps::DirectMemRefOp:
178 CurIdx += 2;
179 break;
180 case StackMaps::IndirectMemRefOp:
181 CurIdx += 3;
182 break;
183 case StackMaps::ConstantOp:
184 ++CurIdx;
185 break;
186 }
187 }
188 ++CurIdx;
189 assert(CurIdx < MI->getNumOperands() && "points past operand list");
190 return CurIdx;
191}
192
193
195 int RegNum;
196 for (MCPhysReg SR : TRI->superregs_inclusive(Reg)) {
197 RegNum = TRI->getDwarfRegNum(SR, false);
198 if (RegNum >= 0)
199 break;
200 }
201
202 assert(RegNum >= 0 && isUInt<16>(RegNum) && "Invalid Dwarf register number.");
203 return (unsigned)RegNum;
204}
205
209 LiveOutVec &LiveOuts) {
211 if (MOI->isImm()) {
212 switch (MOI->getImm()) {
213 default:
215 case StackMaps::DirectMemRefOp: {
217
218 unsigned Size = DL.getPointerSizeInBits();
219 assert((Size % 8) == 0 && "Need pointer size in bytes.");
222 int64_t Imm = (++MOI)->getImm();
225 break;
226 }
227 case StackMaps::IndirectMemRefOp: {
228 int64_t Size = (++MOI)->getImm();
229 assert(Size > 0 && "Need a valid size for indirect memory locations.");
231 int64_t Imm = (++MOI)->getImm();
234 break;
235 }
236 case StackMaps::ConstantOp: {
237 ++MOI;
238 assert(MOI->isImm() && "Expected constant operand.");
240 if (isInt<32>(Imm)) {
242 } else {
243
244
245
246
247
248
251 "empty and tombstone keys should fit in 32 bits!");
252 auto Result = ConstPool.insert(std::make_pair(Imm, Imm));
255 }
256 break;
257 }
258 }
259 return ++MOI;
260 }
261
262
263
264
265
266 if (MOI->isReg()) {
267
269 return ++MOI;
270
272 "Virtreg operands should have been rewritten before now.");
274 assert(!MOI->getSubReg() && "Physical subreg still around.");
275
278 MCRegister LLVMRegNum = *TRI->getLLVMRegNum(DwarfRegNum, false);
279 unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNum, MOI->getReg());
280 if (SubRegIdx)
281 Offset = TRI->getSubRegIdxOffset(SubRegIdx);
282
284 DwarfRegNum, Offset);
285 return ++MOI;
286 }
287
289 LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
290
291 return ++MOI;
292}
293
297 OS << WSMP << "callsites:\n";
298 for (const auto &CSI : CSInfos) {
299 const LocationVec &CSLocs = CSI.Locations;
300 const LiveOutVec &LiveOuts = CSI.LiveOuts;
301
302 OS << WSMP << "callsite " << CSI.ID << "\n";
303 OS << WSMP << " has " << CSLocs.size() << " locations\n";
304
305 unsigned Idx = 0;
306 for (const auto &Loc : CSLocs) {
307 OS << WSMP << "\t\tLoc " << Idx << ": ";
308 switch (Loc.Type) {
310 OS << "";
311 break;
313 OS << "Register ";
316 else
317 OS << Loc.Reg;
318 break;
320 OS << "Direct ";
323 else
324 OS << Loc.Reg;
325 if (Loc.Offset)
326 OS << " + " << Loc.Offset;
327 break;
329 OS << "Indirect ";
332 else
333 OS << Loc.Reg;
334 OS << "+" << Loc.Offset;
335 break;
337 OS << "Constant " << Loc.Offset;
338 break;
340 OS << "Constant Index " << Loc.Offset;
341 break;
342 }
343 OS << "\t[encoding: .byte " << Loc.Type << ", .byte 0"
344 << ", .short " << Loc.Size << ", .short " << Loc.Reg << ", .short 0"
345 << ", .int " << Loc.Offset << "]\n";
347 }
348
349 OS << WSMP << "\thas " << LiveOuts.size() << " live-out registers\n";
350
352 for (const auto &LO : LiveOuts) {
353 OS << WSMP << "\t\tLO " << Idx << ": ";
356 else
358 OS << "\t[encoding: .short " << LO.DwarfRegNum << ", .byte 0, .byte "
359 << LO.Size << "]\n";
361 }
362 }
363}
364
365
369 unsigned Size = TRI->getSpillSize(*TRI->getMinimalPhysRegClass(Reg));
370 return LiveOutReg(Reg, DwarfRegNum, Size);
371}
372
373
374
376StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
377 assert(Mask && "No register mask specified");
380
381
382 for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
383 if ((Mask[Reg / 32] >> (Reg % 32)) & 1)
384 LiveOuts.push_back(createLiveOutReg(Reg, TRI));
385
386
387
388
389
390 llvm::sort(LiveOuts, [](const LiveOutReg &LHS, const LiveOutReg &RHS) {
391
392 return LHS.DwarfRegNum < RHS.DwarfRegNum;
393 });
394
395 for (auto I = LiveOuts.begin(), E = LiveOuts.end(); I != E; ++I) {
396 for (auto *II = std::next(I); II != E; ++II) {
397 if (I->DwarfRegNum != II->DwarfRegNum) {
398
400 break;
401 }
402 I->Size = std::max(I->Size, II->Size);
403 if (I->Reg && TRI->isSuperRegister(I->Reg, II->Reg))
405 II->Reg = 0;
406 }
407 }
408
409 llvm::erase_if(LiveOuts, [](const LiveOutReg &LO) { return LO.Reg == 0; });
410
411 return LiveOuts;
412}
413
414
415
416void StackMaps::parseStatepointOpers(const MachineInstr &MI,
419 LocationVec &Locations,
420 LiveOutVec &LiveOuts) {
423 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
424 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
425 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
426
427
428 unsigned NumDeoptArgs = Locations.back().Offset;
430 assert(NumDeoptArgs == SO.getNumDeoptArgs());
431
432 while (NumDeoptArgs--)
433 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
434
435
437 ++MOI;
439 unsigned NumGCPointers = MOI->getImm();
440 ++MOI;
441 if (NumGCPointers) {
442
444 unsigned GCPtrIdx = (unsigned)SO.getFirstGCPtrIdx();
445 assert((int)GCPtrIdx != -1);
446 assert(MOI - MI.operands_begin() == GCPtrIdx + 0LL);
447 while (NumGCPointers--) {
448 GCPtrIndices.push_back(GCPtrIdx);
450 }
451
453 unsigned NumGCPairs = SO.getGCPointerMap(GCPairs);
454 (void)NumGCPairs;
455 LLVM_DEBUG(dbgs() << "NumGCPairs = " << NumGCPairs << "\n");
456
457 auto MOB = MI.operands_begin();
458 for (auto &P : GCPairs) {
459 assert(P.first < GCPtrIndices.size() && "base pointer index not found");
461 "derived pointer index not found");
462 unsigned BaseIdx = GCPtrIndices[P.first];
463 unsigned DerivedIdx = GCPtrIndices[P.second];
464 LLVM_DEBUG(dbgs() << "Base : " << BaseIdx << " Derived : " << DerivedIdx
465 << "\n");
466 (void)parseOperand(MOB + BaseIdx, MOE, Locations, LiveOuts);
467 (void)parseOperand(MOB + DerivedIdx, MOE, Locations, LiveOuts);
468 }
469
470 MOI = MOB + GCPtrIdx;
471 }
472
473
476 ++MOI;
477 unsigned NumAllocas = MOI->getImm();
478 ++MOI;
479 while (NumAllocas--) {
480 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
482 }
483}
484
485void StackMaps::recordStackMapOpers(const MCSymbol &MILabel,
489 bool recordResult) {
491
494
495 if (recordResult) {
497 parseOperand(MI.operands_begin(), std::next(MI.operands_begin()), Locations,
498 LiveOuts);
499 }
500
501
502 if (MI.getOpcode() == TargetOpcode::STATEPOINT)
503 parseStatepointOpers(MI, MOI, MOE, Locations, LiveOuts);
504 else
505 while (MOI != MOE)
506 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
507
508
509
513
514 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
515 std::move(LiveOuts));
516
517
520 bool HasDynamicFrameSize =
523
525 if (CurrentIt != FnInfos.end())
526 CurrentIt->second.RecordCount++;
527 else
528 FnInfos.insert(std::make_pair(AP.CurrentFnSym, FunctionInfo(FrameSize)));
529}
530
532 assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
533
536 recordStackMapOpers(L, MI, ID, std::next(MI.operands_begin(),
538 MI.operands_end());
539}
540
542 assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
543
545 const int64_t ID = opers.getID();
547 recordStackMapOpers(L, MI, ID, MOI, MI.operands_end(),
549
550#ifndef NDEBUG
551
552 auto &Locations = CSInfos.back().Locations;
555 for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
557 "anyreg arg must be in reg.");
558 }
559#endif
560}
561
563 assert(MI.getOpcode() == TargetOpcode::STATEPOINT && "expected statepoint");
564
566 const unsigned StartIdx = opers.getVarIdx();
567 recordStackMapOpers(L, MI, opers.getID(), MI.operands_begin() + StartIdx,
568 MI.operands_end(), false);
569}
570
571
572
573
574
575
576
577
578
579
580
581void StackMaps::emitStackmapHeader(MCStreamer &OS) {
582
584 OS.emitIntValue(0, 1);
585 OS.emitInt16(0);
586
587
588 LLVM_DEBUG(dbgs() << WSMP << "#functions = " << FnInfos.size() << '\n');
589 OS.emitInt32(FnInfos.size());
590
591 LLVM_DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
592 OS.emitInt32(ConstPool.size());
593
594 LLVM_DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
595 OS.emitInt32(CSInfos.size());
596}
597
598
599
600
601
602
603
604
605void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
606
608 for (auto const &FR : FnInfos) {
609 LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first
610 << " frame size: " << FR.second.StackSize
611 << " callsite count: " << FR.second.RecordCount << '\n');
612 OS.emitSymbolValue(FR.first, 8);
613 OS.emitIntValue(FR.second.StackSize, 8);
614 OS.emitIntValue(FR.second.RecordCount, 8);
615 }
616}
617
618
619
620
621void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
622
624 for (const auto &ConstEntry : ConstPool) {
625 LLVM_DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
626 OS.emitIntValue(ConstEntry.second, 8);
627 }
628}
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
661
662 for (const auto &CSI : CSInfos) {
663 const LocationVec &CSLocs = CSI.Locations;
664 const LiveOutVec &LiveOuts = CSI.LiveOuts;
665
666
667
668
669
670 if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
671 OS.emitIntValue(UINT64_MAX, 8);
672 OS.emitValue(CSI.CSOffsetExpr, 4);
673 OS.emitInt16(0);
674 OS.emitInt16(0);
675 OS.emitInt16(0);
676 OS.emitInt16(0);
677 OS.emitInt32(0);
678 continue;
679 }
680
681 OS.emitIntValue(CSI.ID, 8);
682 OS.emitValue(CSI.CSOffsetExpr, 4);
683
684
685 OS.emitInt16(0);
686 OS.emitInt16(CSLocs.size());
687
688 for (const auto &Loc : CSLocs) {
689 OS.emitIntValue(Loc.Type, 1);
690 OS.emitIntValue(0, 1);
691 OS.emitInt16(Loc.Size);
692 OS.emitInt16(Loc.Reg);
693 OS.emitInt16(0);
694 OS.emitInt32(Loc.Offset);
695 }
696
697
698 OS.emitValueToAlignment(Align(8));
699
700
701 OS.emitInt16(0);
702 OS.emitInt16(LiveOuts.size());
703
704 for (const auto &LO : LiveOuts) {
705 OS.emitInt16(LO.DwarfRegNum);
706 OS.emitIntValue(0, 1);
707 OS.emitIntValue(LO.Size, 1);
708 }
709
710 OS.emitValueToAlignment(Align(8));
711 }
712}
713
714
716 (void)WSMP;
717
718 assert((!CSInfos.empty() || ConstPool.empty()) &&
719 "Expected empty constant pool too!");
720 assert((!CSInfos.empty() || FnInfos.empty()) &&
721 "Expected empty function record too!");
722 if (CSInfos.empty())
723 return;
724
727
728
731 OS.switchSection(StackMapSection);
732
733
735
736
737 LLVM_DEBUG(dbgs() << "********** Stack Map Output **********\n");
738 emitStackmapHeader(OS);
739 emitFunctionFrameRecords(OS);
740 emitConstantPoolEntries(OS);
741 emitCallsiteEntries(OS);
742 OS.addBlankLine();
743
744
745 CSInfos.clear();
746 ConstPool.clear();
747}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 DenseMapInfo traits for DenseMap.
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static uint64_t getConstMetaVal(const MachineInstr &MI, unsigned Idx)
static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(3), cl::Hidden, cl::desc("Specify the stackmap encoding version (default = 3)"))
This class is intended to be used as a driving class for all asm writers.
MachineFunction * MF
The current machine function.
MCSymbol * CurrentFnSym
The symbol for the current function.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
MCSymbol * CurrentFnSymForSize
The symbol used to represent the start of the current function for the purpose of calculating its siz...
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
MCSection * getStackMapSection() const
Wrapper class representing physical registers. Should be passed by value.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Representation of each machine instruction.
iterator_range< mop_iterator > uses()
Returns a range that includes all operands which may be register uses.
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const uint32_t * getRegLiveOut() const
getRegLiveOut - Returns a bit mask of live-out registers.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isRegLiveOut() const
isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
iterator find(const KeyT &Key)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
MI-level patchpoint operands.
uint32_t getNumCallArgs() const
Return the number of call arguments.
PatchPointOpers(const MachineInstr *MI)
unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
uint64_t getID() const
Return the ID for the given patchpoint.
unsigned getStackMapStartIdx() const
Get the index at which stack map locations will be recorded.
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
MI-level stackmap operands.
StackMapOpers(const MachineInstr *MI)
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
static unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx)
Get index of next meta operand.
StackMaps(AsmPrinter &AP)
void serializeToStackMapSection()
If there is any stack map data, create a stack map section and serialize the map info into it.
SmallVector< LiveOutReg, 8 > LiveOutVec
SmallVector< Location, 8 > LocationVec
void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
MI-level Statepoint operands.
unsigned getGCPointerMap(SmallVectorImpl< std::pair< unsigned, unsigned > > &GCMap)
Get vector of base/derived pairs from statepoint.
unsigned getNumAllocaIdx()
Get index of number of gc allocas.
unsigned getNumGcMapEntriesIdx()
Get index of number of gc map entries.
int getFirstGCPtrIdx()
Get index of first GC pointer operand of -1 if there are none.
unsigned getNumDeoptArgsIdx() const
Get index of Number Deopt Arguments operand.
uint64_t getID() const
Return the ID for the given statepoint.
bool isFoldableReg(Register Reg) const
Return true if Reg is used only in operands which can be folded to stack usage.
unsigned getVarIdx() const
Get starting index of non call related arguments (calling convention, statepoint flags,...
unsigned getNumGCPtrIdx()
Get index of number of GC pointers.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
This struct is a compact representation of a valid (non-zero power of two) alignment.
An information struct used to provide DenseMap with the various necessary components for a given valu...