77#define DEBUG_TYPE "si-fix-sgpr-copies"
80 "amdgpu-enable-merge-m0",
81 cl::desc(
"Merge and hoist M0 initializations"),
99 unsigned NumReadfirstlanes;
101 bool NeedToBeConvertedToVALU =
false;
107 unsigned SiblingPenalty = 0;
109 V2SCopyInfo() : Copy(nullptr),
ID(0){};
111 :
Copy(
C), NumSVCopies(0), NumReadfirstlanes(
Width / 32),
ID(
Id){};
112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
115 <<
"\n\tSV:" << NumSVCopies <<
"\n\tSP: " << SiblingPenalty
116 <<
"\nScore: " << Score <<
"\n";
127 unsigned NextVGPRToSGPRCopyID;
143 unsigned getNextVGPRToSGPRCopyId() {
return ++NextVGPRToSGPRCopyID; }
144 bool needToBeConvertedToVALU(V2SCopyInfo *
I);
168 "SI Fix SGPR copies",
false,
false)
173char SIFixSGPRCopies::
ID = 0;
178 return new SIFixSGPRCopies();
181static std::pair<const TargetRegisterClass *, const TargetRegisterClass *>
185 Register DstReg = Copy.getOperand(0).getReg();
186 Register SrcReg = Copy.getOperand(1).getReg();
189 ?
MRI.getRegClass(SrcReg)
190 :
TRI.getPhysRegBaseClass(SrcReg);
196 ?
MRI.getRegClass(DstReg)
197 :
TRI.getPhysRegBaseClass(DstReg);
199 return std::pair(SrcRC, DstRC);
205 return SrcRC != &AMDGPU::VReg_1RegClass &&
TRI.isSGPRClass(DstRC) &&
206 TRI.hasVectorRegisters(SrcRC);
212 return DstRC != &AMDGPU::VReg_1RegClass &&
TRI.isSGPRClass(SrcRC) &&
213 TRI.hasVectorRegisters(DstRC);
220 auto &Src =
MI.getOperand(1);
226 for (
const auto &MO :
MRI.reg_nodbg_operands(DstReg)) {
227 const auto *
UseMI = MO.getParent();
234 unsigned OpIdx = MO.getOperandNo();
236 !
TII->isOperandLegal(*
UseMI, OpIdx, &Src))
240 MRI.setRegClass(DstReg,
TRI->getEquivalentSGPRClass(
MRI.getRegClass(DstReg)));
264 if (!
TRI->isSGPRClass(
MRI.getRegClass(DstReg)))
267 if (!
MRI.hasOneUse(DstReg))
289 if (
SubReg != AMDGPU::NoSubRegister)
292 MRI.setRegClass(DstReg, DstRC);
303 bool IsAGPR =
TRI->isAGPRClass(DstRC);
305 for (
unsigned I = 1,
N =
MI.getNumOperands();
I !=
N;
I += 2) {
307 TRI->getRegClassForOperandReg(
MRI,
MI.getOperand(
I));
309 "Expected SGPR REG_SEQUENCE to only have SGPR inputs");
312 Register TmpReg =
MRI.createVirtualRegister(NewSrcRC);
320 Register TmpAReg =
MRI.createVirtualRegister(NewSrcRC);
321 unsigned Opc = NewSrcRC == &AMDGPU::AGPR_32RegClass ?
322 AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::COPY;
329 MI.getOperand(
I).setReg(TmpReg);
341 if (Copy->getOpcode() != AMDGPU::COPY)
344 if (!MoveImm->isMoveImmediate())
348 TII->getNamedOperand(*MoveImm, AMDGPU::OpName::src0);
353 if (Copy->getOperand(0).getSubReg())
356 switch (MoveImm->getOpcode()) {
359 case AMDGPU::V_MOV_B32_e32:
360 SMovOp = AMDGPU::S_MOV_B32;
362 case AMDGPU::V_MOV_B64_PSEUDO:
363 SMovOp = AMDGPU::S_MOV_B64;
370template <
class UnaryPredicate>
373 UnaryPredicate Predicate) {
380 while (!Worklist.
empty()) {
420 while (
I !=
MBB->
end() &&
TII->isBasicBlockPrologue(*
I))
436 using InitListMap = std::map<unsigned, std::list<MachineInstr *>>;
443 bool Changed =
false;
445 for (
auto &
MI :
MRI.def_instructions(Reg)) {
447 for (
auto &MO :
MI.operands()) {
448 if ((MO.isReg() && ((MO.isDef() && MO.getReg() != Reg) || !MO.isDef())) ||
449 (!MO.isImm() && !MO.isReg()) || (MO.isImm() && Imm)) {
452 }
else if (MO.isImm())
456 Inits[Imm->getImm()].push_front(&
MI);
461 for (
auto &
Init : Inits) {
462 auto &Defs =
Init.second;
464 for (
auto I1 = Defs.begin(),
E = Defs.end(); I1 !=
E; ) {
467 for (
auto I2 = std::next(I1); I2 !=
E; ) {
480 bool MayClobberTo =
isReachable(Clobber, &*To, MBBTo, MDT);
481 if (!MayClobberFrom && !MayClobberTo)
483 if ((MayClobberFrom && !MayClobberTo) ||
484 (!MayClobberFrom && MayClobberTo))
490 return !((MBBFrom == MBBTo &&
498 return C.first !=
Init.first &&
504 if (!interferes(MI2, MI1)) {
514 if (!interferes(MI1, MI2)) {
532 if (!interferes(MI1,
I) && !interferes(MI2,
I)) {
536 <<
"and moving from "
553 for (
auto &
Init : Inits) {
554 auto &Defs =
Init.second;
555 auto I = Defs.begin();
556 while (
I != Defs.end()) {
557 if (MergedInstrs.
count(*
I)) {
558 (*I)->eraseFromParent();
566 for (
auto &
Init : Inits) {
567 auto &Defs =
Init.second;
568 for (
auto *
MI : Defs) {
569 auto MBB =
MI->getParent();
574 if (!
TII->isBasicBlockPrologue(*
B))
577 auto R = std::next(
MI->getReverseIterator());
578 const unsigned Threshold = 50;
580 for (
unsigned I = 0; R !=
B &&
I < Threshold; ++R, ++
I)
581 if (R->readsRegister(Reg,
TRI) || R->definesRegister(Reg,
TRI) ||
592 MRI.clearKillFlags(Reg);
600 MachineFunctionProperties::Property::Selected))
605 TRI =
ST.getRegisterInfo();
606 TII =
ST.getInstrInfo();
607 MDT = &getAnalysis<MachineDominatorTree>();
617 switch (
MI.getOpcode()) {
622 case AMDGPU::STRICT_WQM:
623 case AMDGPU::SOFT_WQM:
624 case AMDGPU::STRICT_WWM: {
637 S2VCopies.push_back(&
MI);
641 if (lowerSpecialCase(
MI,
I))
644 analyzeVGPRToSGPRCopy(&
MI);
648 case AMDGPU::INSERT_SUBREG:
650 case AMDGPU::REG_SEQUENCE: {
651 if (
TRI->isSGPRClass(
TII->getOpRegClass(
MI, 0))) {
653 if (!MO.isReg() || !MO.getReg().isVirtual())
656 if (
TRI->hasVectorRegisters(SrcRC)) {
658 TRI->getEquivalentSGPRClass(SrcRC);
659 Register NewDst =
MRI->createVirtualRegister(DestRC);
661 MI.isPHI() ?
MI.getOperand(MO.getOperandNo() + 1).getMBB()
666 BuildMI(*BlockToInsertCopy, PointToInsertCopy,
667 PointToInsertCopy->getDebugLoc(),
668 TII->get(AMDGPU::COPY), NewDst)
671 analyzeVGPRToSGPRCopy(NewCopy);
677 PHINodes.push_back(&
MI);
678 else if (
MI.isRegSequence())
679 RegSequences.push_back(&
MI);
683 case AMDGPU::V_WRITELANE_B32: {
686 if (
ST.getConstantBusLimit(
MI.getOpcode()) != 1)
704 Src0.
getReg() != AMDGPU::M0) &&
706 Src1.
getReg() != AMDGPU::M0)) {
714 if (MO->getReg().isVirtual()) {
719 MO->getReg() ==
Def.getReg() &&
720 MO->getSubReg() ==
Def.getSubReg()) {
722 if (Copied.
isImm() &&
737 TII->get(AMDGPU::COPY), AMDGPU::M0)
748 lowerVGPR2SGPRCopies(MF);
751 for (
auto MI : S2VCopies) {
760 for (
auto MI : RegSequences) {
762 if (
MI->isRegSequence())
765 for (
auto MI : PHINodes) {
771 SiblingPenalty.clear();
774 RegSequences.clear();
782 bool AllAGPRUses =
true;
789 bool HasUses =
false;
790 while (!worklist.
empty()) {
793 for (
const auto &
Use :
MRI->use_operands(Reg)) {
810 if (HasUses && AllAGPRUses && !
TRI->isAGPRClass(RC0)) {
812 MRI->setRegClass(PHIRes,
TRI->getEquivalentAGPRClass(RC0));
813 for (
unsigned I = 1,
N =
MI.getNumOperands();
I !=
N;
I += 2) {
820 if (
TRI->isVectorRegister(*
MRI, PHIRes) ||
821 RC0 == &AMDGPU::VReg_1RegClass) {
823 TII->legalizeOperands(
MI, MDT);
827 while (!PHIOperands.
empty()) {
841 if (DstReg == AMDGPU::M0 &&
842 TRI->hasVectorRegisters(
MRI->getRegClass(SrcReg))) {
844 MRI->createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
846 TII->get(AMDGPU::V_READFIRSTLANE_B32), TmpReg)
847 .
add(
MI.getOperand(1));
848 MI.getOperand(1).setReg(TmpReg);
854 if (!SrcConst.
isReg()) {
856 unsigned MoveSize =
TRI->getRegSizeInBits(*SrcRC);
858 MoveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
863 if (
MRI->hasOneUse(SrcReg))
865 MI.eraseFromParent();
874 TII->moveToVALU(worklist, MDT);
883 MI.getOperand(1).ChangeToImmediate(Imm);
884 MI.addImplicitDefUseOperands(*
MI.getParent()->getParent());
885 MI.setDesc(
TII->get(SMovOp));
895 V2SCopyInfo
Info(getNextVGPRToSGPRCopyId(),
MI,
896 TRI->getRegSizeInBits(*DstRC));
902 while (!AnalysisWorklist.
empty()) {
906 if (!Visited.
insert(Inst).second)
921 SiblingPenalty[Inst].insert(
Info.ID);
928 while (++
I !=
E && !
I->findRegisterDefOperand(AMDGPU::SCC)) {
929 if (
I->readsRegister(AMDGPU::SCC))
934 if (
TRI->isSGPRReg(*
MRI, Reg) && !
TII->isVALU(*Inst))
935 for (
auto &U :
MRI->use_instructions(Reg))
938 for (
auto U :
Users) {
940 Info.SChain.insert(U);
949bool SIFixSGPRCopies::needToBeConvertedToVALU(V2SCopyInfo *Info) {
950 if (
Info->SChain.empty()) {
954 Info->Siblings = SiblingPenalty[*std::max_element(
955 Info->SChain.begin(),
Info->SChain.end(),
957 return SiblingPenalty[A].size() < SiblingPenalty[B].size();
959 Info->Siblings.remove_if([&](
unsigned ID) {
return ID ==
Info->ID; });
966 for (
auto J :
Info->Siblings) {
967 auto InfoIt = V2SCopies.find(J);
968 if (InfoIt != V2SCopies.end()) {
978 Info->SiblingPenalty = SrcRegs.
size();
981 Info->NumSVCopies +
Info->SiblingPenalty +
Info->NumReadfirstlanes;
982 unsigned Profit =
Info->SChain.size();
983 Info->Score = Penalty > Profit ? 0 : Profit - Penalty;
984 Info->NeedToBeConvertedToVALU =
Info->Score < 3;
985 return Info->NeedToBeConvertedToVALU;
991 for (
auto &
C : V2SCopies) {
992 if (needToBeConvertedToVALU(&
C.second))
1000 while (!LoweringWorklist.
empty()) {
1002 auto CurInfoIt = V2SCopies.find(CurID);
1003 if (CurInfoIt != V2SCopies.end()) {
1004 V2SCopyInfo
C = CurInfoIt->getSecond();
1006 for (
auto S :
C.Siblings) {
1007 auto SibInfoIt = V2SCopies.find(S);
1008 if (SibInfoIt != V2SCopies.end()) {
1009 V2SCopyInfo &
SI = SibInfoIt->getSecond();
1011 if (!
SI.NeedToBeConvertedToVALU) {
1013 if (needToBeConvertedToVALU(&SI))
1016 SI.Siblings.remove_if([&](
unsigned ID) {
return ID ==
C.ID; });
1020 <<
" is being turned to VALU\n");
1021 V2SCopies.erase(
C.ID);
1030 for (
auto C : V2SCopies) {
1036 <<
" is being turned to v_readfirstlane_b32"
1037 <<
" Score: " <<
C.second.Score <<
"\n");
1038 Register DstReg =
MI->getOperand(0).getReg();
1039 Register SrcReg =
MI->getOperand(1).getReg();
1040 unsigned SubReg =
MI->getOperand(1).getSubReg();
1042 TRI->getRegClassForOperandReg(*
MRI,
MI->getOperand(1));
1043 size_t SrcSize =
TRI->getRegSizeInBits(*SrcRC);
1044 if (SrcSize == 16) {
1047 TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg);
1048 MIB.addReg(SrcReg, 0, AMDGPU::NoSubRegister);
1049 }
else if (SrcSize == 32) {
1051 TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg);
1052 MIB.addReg(SrcReg, 0,
SubReg);
1055 TII->get(AMDGPU::REG_SEQUENCE), DstReg);
1056 int N =
TRI->getRegSizeInBits(*SrcRC) / 32;
1057 for (
int i = 0; i <
N; i++) {
1059 Result, *
MRI,
MI->getOperand(1), SrcRC,
1060 TRI->getSubRegFromChannel(i), &AMDGPU::VGPR_32RegClass);
1062 MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1064 TII->get(AMDGPU::V_READFIRSTLANE_B32), PartialDst)
1066 Result.addReg(PartialDst).addImm(
TRI->getSubRegFromChannel(i));
1069 MI->eraseFromParent();
1086 if (SrcReg == AMDGPU::SCC) {
1088 TRI->getRegClass(AMDGPU::SReg_1_XEXECRegClassID));
1091 TII->get(IsWave32 ? AMDGPU::S_CSELECT_B32
1092 : AMDGPU::S_CSELECT_B64),
1096 I =
BuildMI(*
MI.getParent(), std::next(
I),
I->getDebugLoc(),
1097 TII->get(AMDGPU::COPY), DstReg)
1099 MI.eraseFromParent();
1102 if (DstReg == AMDGPU::SCC) {
1103 unsigned Opcode = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
1104 Register Exec = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
1107 MI.getDebugLoc(),
TII->get(Opcode))
1111 MI.eraseFromParent();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Provides AMDGPU specific target descriptions.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
iv Induction Variable Users
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static std::pair< const TargetRegisterClass *, const TargetRegisterClass * > getCopyRegClasses(const MachineInstr &Copy, const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI)
static cl::opt< bool > EnableM0Merge("amdgpu-enable-merge-m0", cl::desc("Merge and hoist M0 initializations"), cl::init(true))
static bool hoistAndMergeSGPRInits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo *TRI, MachineDominatorTree &MDT, const TargetInstrInfo *TII)
static bool foldVGPRCopyIntoRegSequence(MachineInstr &MI, const SIRegisterInfo *TRI, const SIInstrInfo *TII, MachineRegisterInfo &MRI)
bool searchPredecessors(const MachineBasicBlock *MBB, const MachineBasicBlock *CutOff, UnaryPredicate Predicate)
static bool isReachable(const MachineInstr *From, const MachineInstr *To, const MachineBasicBlock *CutOff, MachineDominatorTree &MDT)
static bool isVGPRToSGPRCopy(const TargetRegisterClass *SrcRC, const TargetRegisterClass *DstRC, const SIRegisterInfo &TRI)
static bool tryChangeVGPRtoSGPRinCopy(MachineInstr &MI, const SIRegisterInfo *TRI, const SIInstrInfo *TII)
static bool isSGPRToVGPRCopy(const TargetRegisterClass *SrcRC, const TargetRegisterClass *DstRC, const SIRegisterInfo &TRI)
static bool isSafeToFoldImmIntoCopy(const MachineInstr *Copy, const MachineInstr *MoveImm, const SIInstrInfo *TII, unsigned &SMovOp, int64_t &Imm)
static MachineBasicBlock::iterator getFirstNonPrologue(MachineBasicBlock *MBB, const TargetInstrInfo *TII)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines generic set operations that may be used on set's of different types,...
Class for arbitrary precision integers.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Implements a dense probed hash-table based set.
FunctionPass class - This class is used to implement most global optimizations.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
pred_iterator pred_begin()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator getFirstInstrTerminator()
Same getFirstTerminator but it ignores bundles and return an instr_iterator instead.
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineBasicBlock * findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B)
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
bool properlyDominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool hasProperty(Property P) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isImplicitDef() const
const MachineBasicBlock * getParent() const
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool isRegSequence() const
unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
A vector that has set insertion semantics.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
value_type pop_back_val()
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
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.
TargetInstrInfo - Interface to description of machine instruction set.
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
self_iterator getIterator()
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
@ Resolved
Queried, materialization begun.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void set_subtract(S1Ty &S1, const S2Ty &S2)
set_subtract(A, B) - Compute A := A - B
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getDefRegState(bool B)
FunctionPass * createSIFixSGPRCopiesPass()
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Utility to store machine instructions worklist.
void insert(MachineInstr *MI)