80#define DEBUG_TYPE "aarch64-mi-peephole-opt"
84class AArch64MIPeepholeOptImpl {
96 using OpcodePair = std::pair<unsigned, unsigned>;
98 using SplitAndOpcFunc =
99 std::function<std::optional<OpcodePair>(
T,
unsigned,
T &,
T &)>;
101 std::function<void(
MachineInstr &, OpcodePair,
unsigned,
unsigned,
118 template <
typename T>
120 SplitAndOpcFunc<T> SplitAndOpc, BuildMIFunc BuildInstr);
125 template <
typename T>
126 bool visitADDSUB(
unsigned PosOpc,
unsigned NegOpc,
MachineInstr &
MI);
127 template <
typename T>
128 bool visitADDSSUBS(OpcodePair PosOpcs, OpcodePair NegOpcs,
MachineInstr &
MI);
131 enum class SplitStrategy {
135 template <
typename T>
137 SplitStrategy Strategy,
unsigned OtherOpc = 0);
156 return "AArch64 MI Peephole Optimization pass";
166char AArch64MIPeepholeOptLegacy::ID = 0;
171 "AArch64 MI Peephole Optimization",
false,
false)
175 T UImm =
static_cast<T>(
Imm);
176 assert(UImm && (UImm != ~
static_cast<T>(0)) &&
"Invalid immediate!");
207 assert(
Imm && (
Imm != ~
static_cast<T>(0)) &&
"Invalid immediate!");
214 unsigned LowestGapBitUnset =
218 assert(LowestGapBitUnset <
sizeof(
T) * CHAR_BIT &&
"Undefined behaviour!");
219 T NewImm1 = (
static_cast<T>(1) << LowestGapBitUnset) -
234bool AArch64MIPeepholeOptImpl::trySplitLogicalImm(
unsigned Opc,
236 SplitStrategy Strategy,
248 return splitTwoPartImm<T>(
251 T &Imm1) -> std::optional<OpcodePair> {
260 if (Insn.
size() == 1)
263 bool SplitSucc =
false;
265 case SplitStrategy::Intersect:
266 SplitSucc = splitBitmaskImm(
Imm,
RegSize, Imm0, Imm1);
268 case SplitStrategy::Disjoint:
273 return std::make_pair(
Opc, !OtherOpc ?
Opc : OtherOpc);
276 [&
TII =
TII](MachineInstr &
MI, OpcodePair Opcode,
unsigned Imm0,
290bool AArch64MIPeepholeOptImpl::visitORR(MachineInstr &
MI) {
295 if (
MI.getOperand(3).getImm() != 0)
298 if (
MI.getOperand(1).getReg() != AArch64::WZR)
301 if (
MI.getOperand(2).getSubReg())
323 if (SrcMI->
getOpcode() == TargetOpcode::COPY &&
330 if (RC != &AArch64::FPR32RegClass &&
331 ((RC != &AArch64::FPR64RegClass && RC != &AArch64::FPR128RegClass &&
332 RC != &AArch64::ZPRRegClass) ||
339 TII->get(TargetOpcode::COPY), CpySrc)
349 else if (SrcMI->
getOpcode() <= TargetOpcode::GENERIC_OP_END)
354 MI.eraseFromParent();
359bool AArch64MIPeepholeOptImpl::visitCSEL(MachineInstr &
MI) {
361 if (
MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg())
365 MI.getOpcode() == AArch64::CSELXr ? AArch64::XZR : AArch64::WZR;
367 MI.getOpcode() == AArch64::CSELXr ? AArch64::ORRXrs : AArch64::ORRWrs;
370 .
addReg(
MI.getOperand(0).getReg(), RegState::Define)
375 MI.eraseFromParent();
379bool AArch64MIPeepholeOptImpl::visitINSERT(MachineInstr &
MI) {
387 if (!
MI.isRegTiedToDefOperand(1))
406 if ((SrcMI->
getOpcode() <= TargetOpcode::GENERIC_OP_END) ||
407 !AArch64::GPR64allRegClass.hasSubClassEq(RC))
411 MachineInstr *SubregMI =
413 TII->get(TargetOpcode::SUBREG_TO_REG), DstReg)
414 .
add(
MI.getOperand(2))
415 .
add(
MI.getOperand(3));
418 MI.eraseFromParent();
427 if ((
Imm & 0xfff000) == 0 || (
Imm & 0xfff) == 0 ||
428 (
Imm & ~
static_cast<T>(0xffffff)) != 0)
434 if (Insn.
size() == 1)
438 Imm0 = (
Imm >> 12) & 0xfff;
444bool AArch64MIPeepholeOptImpl::visitADDSUB(
unsigned PosOpc,
unsigned NegOpc,
462 if (
MI.getOperand(1).getReg() == AArch64::XZR ||
463 MI.getOperand(1).getReg() == AArch64::WZR)
466 return splitTwoPartImm<T>(
469 T &Imm1) -> std::optional<OpcodePair> {
471 return std::make_pair(PosOpc, PosOpc);
473 return std::make_pair(NegOpc, NegOpc);
476 [&
TII =
TII](MachineInstr &
MI, OpcodePair Opcode,
unsigned Imm0,
493bool AArch64MIPeepholeOptImpl::visitADDSSUBS(OpcodePair PosOpcs,
499 if (
MI.getOperand(1).getReg() == AArch64::XZR ||
500 MI.getOperand(1).getReg() == AArch64::WZR)
503 return splitTwoPartImm<T>(
507 T &Imm1) -> std::optional<OpcodePair> {
521 if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
525 [&
TII =
TII](MachineInstr &
MI, OpcodePair Opcode,
unsigned Imm0,
543bool AArch64MIPeepholeOptImpl::checkMovImmInstr(MachineInstr &
MI,
544 MachineInstr *&MovMI,
545 MachineInstr *&SubregToRegMI) {
549 if (L && !
L->isLoopInvariant(
MI))
558 SubregToRegMI =
nullptr;
559 if (MovMI->
getOpcode() == TargetOpcode::SUBREG_TO_REG) {
560 SubregToRegMI = MovMI;
566 if (MovMI->
getOpcode() != AArch64::MOVi32imm &&
567 MovMI->
getOpcode() != AArch64::MOVi64imm)
583bool AArch64MIPeepholeOptImpl::splitTwoPartImm(MachineInstr &
MI,
584 SplitAndOpcFunc<T> SplitAndOpc,
585 BuildMIFunc BuildInstr) {
588 "Invalid RegSize for legal immediate peephole optimization");
591 MachineInstr *MovMI, *SubregToRegMI;
592 if (!checkMovImmInstr(
MI, MovMI, SubregToRegMI))
604 if (
auto R = SplitAndOpc(
Imm,
RegSize, Imm0, Imm1))
616 TII->getRegClass(
TII->get(Opcode.first), 0);
618 TII->getRegClass(
TII->get(Opcode.first), 1);
620 (Opcode.first == Opcode.second)
624 (Opcode.first == Opcode.second)
625 ? FirstInstrOperandRC
626 :
TII->getRegClass(
TII->get(Opcode.second), 1);
641 if (DstReg != NewDstReg)
645 BuildInstr(
MI, Opcode, Imm0, Imm1, SrcReg, NewTmpReg, NewDstReg);
649 if (DstReg != NewDstReg) {
651 MI.getOperand(0).setReg(DstReg);
654 auto SalvageDebugUses = [&](
Register Reg, int64_t Val) {
656 MachineInstr &DbgMI = *MO.getParent();
663 MO.ChangeToImmediate(Val);
668 MI.eraseFromParent();
680bool AArch64MIPeepholeOptImpl::visitINSviGPR(MachineInstr &
MI,
unsigned Opc) {
697 if (!SrcMI || SrcMI->
getOpcode() != TargetOpcode::COPY)
704 &AArch64::FPR128RegClass) {
712 MachineInstr *INSvilaneMI =
714 .
add(
MI.getOperand(1))
715 .
add(
MI.getOperand(2))
721 MI.eraseFromParent();
731 if (!
MI->getOperand(0).isReg() || !
MI->getOperand(0).isDef())
734 if (RC != &AArch64::FPR64RegClass)
736 if (
MI->getOpcode() == TargetOpcode::COPY) {
741 if (
SrcOp.getSubReg()) {
749 if (!SrcDef || SrcDef->
getOpcode() <= TargetOpcode::GENERIC_OP_END ||
754 return RC == &AArch64::DDRegClass || RC == &AArch64::DDDRegClass ||
755 RC == &AArch64::DDDDRegClass;
757 auto IsGPR64Like = [&]() ->
bool {
759 return AArch64::GPR64allRegClass.hasSubClassEq(
760 MRI->getRegClass(SrcReg));
761 return AArch64::GPR64allRegClass.contains(SrcReg);
765 assert(
TII &&
"Expected InstrInfo when materializing COPYs");
768 bool SrcKill = SrcMO.
isKill();
770 if (
MRI->getRegClass(SrcReg) != &AArch64::GPR64RegClass) {
773 Register NewSrc =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
775 TII->get(TargetOpcode::COPY), NewSrc)
779 }
else if (!AArch64::GPR64RegClass.
contains(SrcReg)) {
787 MI->setDesc(
TII->get(AArch64::FMOVXDr));
790 return MI->getOpcode() > TargetOpcode::GENERIC_OP_END;
793bool AArch64MIPeepholeOptImpl::visitINSvi64lane(MachineInstr &
MI) {
801 if (
MI.getOperand(2).getImm() != 1)
804 if (!Low64MI || Low64MI->
getOpcode() != AArch64::INSERT_SUBREG)
824 if (!High64MI || High64MI->
getOpcode() != AArch64::INSERT_SUBREG)
827 if (High64MI && High64MI->
getOpcode() == TargetOpcode::COPY)
829 if (!High64MI || (High64MI->
getOpcode() != AArch64::MOVID &&
830 High64MI->
getOpcode() != AArch64::MOVIv2d_ns))
841 MI.eraseFromParent();
846bool AArch64MIPeepholeOptImpl::visitFMOVDr(MachineInstr &
MI) {
858 MI.eraseFromParent();
863bool AArch64MIPeepholeOptImpl::visitUBFMXri(MachineInstr &
MI) {
866 int64_t Immr =
MI.getOperand(2).getImm();
867 int64_t Imms =
MI.getOperand(3).getImm();
869 bool IsLSR = Imms == 31 && Immr <= Imms;
870 bool IsLSL = Immr == Imms + 33;
871 if (!IsLSR && !IsLSL)
879 TII->getRegClass(
TII->get(
MI.getOpcode()), 0);
881 TRI->getSubRegisterClass(DstRC64, AArch64::sub_32);
882 assert(DstRC32 &&
"Destination register class of UBFMXri doesn't have a "
883 "sub_32 subregister class");
886 TII->getRegClass(
TII->get(
MI.getOpcode()), 1);
888 TRI->getSubRegisterClass(SrcRC64, AArch64::sub_32);
889 assert(SrcRC32 &&
"Source register class of UBFMXri doesn't have a sub_32 "
890 "subregister class");
892 Register DstReg64 =
MI.getOperand(0).getReg();
894 Register SrcReg64 =
MI.getOperand(1).getReg();
899 .
addReg(SrcReg64, {}, AArch64::sub_32);
906 TII->get(AArch64::SUBREG_TO_REG), DstReg64)
909 MI.eraseFromParent();
916bool AArch64MIPeepholeOptImpl::visitCopy(MachineInstr &
MI) {
917 Register InputReg =
MI.getOperand(1).getReg();
918 if (
MI.getOperand(1).getSubReg() != AArch64::sub_32 ||
923 SmallPtrSet<MachineInstr *, 4> DeadInstrs;
935 auto getSXTWSrcReg = [](MachineInstr *SrcMI) ->
Register {
936 if (SrcMI->
getOpcode() != AArch64::SBFMXri ||
943 auto getUXTWSrcReg = [&](MachineInstr *SrcMI) ->
Register {
944 if (SrcMI->
getOpcode() != AArch64::SUBREG_TO_REG ||
949 if (!Orr || Orr->
getOpcode() != AArch64::ORRWrr ||
954 if (!Cpy || Cpy->
getOpcode() != AArch64::COPY ||
961 Register SrcReg = getSXTWSrcReg(SrcMI);
963 SrcReg = getUXTWSrcReg(SrcMI);
969 MI.getOperand(1).setReg(SrcReg);
971 for (
auto *DeadMI : DeadInstrs) {
973 DeadMI->eraseFromParent();
979 TII =
static_cast<const AArch64InstrInfo *
>(MF.
getSubtarget().getInstrInfo());
980 TRI =
static_cast<const AArch64RegisterInfo *
>(
988 for (MachineBasicBlock &
MBB : MF) {
990 switch (
MI.getOpcode()) {
993 case AArch64::INSERT_SUBREG:
996 case AArch64::ANDWrr:
997 Changed |= trySplitLogicalImm<uint32_t>(AArch64::ANDWri,
MI,
998 SplitStrategy::Intersect);
1000 case AArch64::ANDXrr:
1001 Changed |= trySplitLogicalImm<uint64_t>(AArch64::ANDXri,
MI,
1002 SplitStrategy::Intersect);
1004 case AArch64::ANDSWrr:
1005 Changed |= trySplitLogicalImm<uint32_t>(
1006 AArch64::ANDWri,
MI, SplitStrategy::Intersect, AArch64::ANDSWri);
1008 case AArch64::ANDSXrr:
1009 Changed |= trySplitLogicalImm<uint64_t>(
1010 AArch64::ANDXri,
MI, SplitStrategy::Intersect, AArch64::ANDSXri);
1012 case AArch64::EORWrr:
1013 Changed |= trySplitLogicalImm<uint32_t>(AArch64::EORWri,
MI,
1014 SplitStrategy::Disjoint);
1016 case AArch64::EORXrr:
1017 Changed |= trySplitLogicalImm<uint64_t>(AArch64::EORXri,
MI,
1018 SplitStrategy::Disjoint);
1020 case AArch64::ORRWrr:
1021 Changed |= trySplitLogicalImm<uint32_t>(AArch64::ORRWri,
MI,
1022 SplitStrategy::Disjoint);
1024 case AArch64::ORRXrr:
1025 Changed |= trySplitLogicalImm<uint64_t>(AArch64::ORRXri,
MI,
1026 SplitStrategy::Disjoint);
1028 case AArch64::ORRWrs:
1031 case AArch64::ADDWrr:
1032 Changed |= visitADDSUB<uint32_t>(AArch64::ADDWri, AArch64::SUBWri,
MI);
1034 case AArch64::SUBWrr:
1035 Changed |= visitADDSUB<uint32_t>(AArch64::SUBWri, AArch64::ADDWri,
MI);
1037 case AArch64::ADDXrr:
1038 Changed |= visitADDSUB<uint64_t>(AArch64::ADDXri, AArch64::SUBXri,
MI);
1040 case AArch64::SUBXrr:
1041 Changed |= visitADDSUB<uint64_t>(AArch64::SUBXri, AArch64::ADDXri,
MI);
1043 case AArch64::ADDSWrr:
1045 visitADDSSUBS<uint32_t>({AArch64::ADDWri, AArch64::ADDSWri},
1046 {AArch64::SUBWri, AArch64::SUBSWri},
MI);
1048 case AArch64::SUBSWrr:
1050 visitADDSSUBS<uint32_t>({AArch64::SUBWri, AArch64::SUBSWri},
1051 {AArch64::ADDWri, AArch64::ADDSWri},
MI);
1053 case AArch64::ADDSXrr:
1055 visitADDSSUBS<uint64_t>({AArch64::ADDXri, AArch64::ADDSXri},
1056 {AArch64::SUBXri, AArch64::SUBSXri},
MI);
1058 case AArch64::SUBSXrr:
1060 visitADDSSUBS<uint64_t>({AArch64::SUBXri, AArch64::SUBSXri},
1061 {AArch64::ADDXri, AArch64::ADDSXri},
MI);
1063 case AArch64::CSELWr:
1064 case AArch64::CSELXr:
1067 case AArch64::INSvi64gpr:
1068 Changed |= visitINSviGPR(
MI, AArch64::INSvi64lane);
1070 case AArch64::INSvi32gpr:
1071 Changed |= visitINSviGPR(
MI, AArch64::INSvi32lane);
1073 case AArch64::INSvi16gpr:
1074 Changed |= visitINSviGPR(
MI, AArch64::INSvi16lane);
1076 case AArch64::INSvi8gpr:
1077 Changed |= visitINSviGPR(
MI, AArch64::INSvi8lane);
1079 case AArch64::INSvi64lane:
1082 case AArch64::FMOVDr:
1085 case AArch64::UBFMXri:
1098bool AArch64MIPeepholeOptLegacy::runOnMachineFunction(
MachineFunction &MF) {
1102 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1103 return AArch64MIPeepholeOptImpl(MLI).run(MF);
1107 return new AArch64MIPeepholeOptLegacy();
1114 const bool Changed = AArch64MIPeepholeOptImpl(MLI).run(MF);
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool is64bitDefwithZeroHigh64bit(MachineInstr *MI, MachineRegisterInfo *MRI, const AArch64InstrInfo *TII)
static bool splitDisjointBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc)
static bool splitAddSubImm(T Imm, unsigned RegSize, T &Imm0, T &Imm1)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
bool isPseudo() const
Return true if this is a pseudo instruction that doesn't correspond to a real machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void setDebugValueUndef()
Sets all register debug operands in this debug value instruction to be undef.
const MachineBasicBlock * getParent() const
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool isNonListDebugValue() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isDebugValue() const
const MachineOperand & getOperand(unsigned i) const
bool isIndirectDebugValue() const
A DBG_VALUE is indirect iff the location operand is a register and the offset operand is an immediate...
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr RegState getKillRegState(bool B)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64MIPeepholeOptLegacyPass()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
MCRegisterClass TargetRegisterClass