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>(
250 [
Opc, Strategy, OtherOpc](
T Imm,
unsigned RegSize,
T &Imm0,
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,
280 MachineBasicBlock *
MBB =
MI.getParent();
290bool AArch64MIPeepholeOptImpl::visitORR(MachineInstr &
MI) {
295 if (
MI.getOperand(3).getImm() != 0)
298 if (
MI.getOperand(1).getReg() != AArch64::WZR)
315 if (SrcMI->
getOpcode() == TargetOpcode::COPY &&
317 const TargetRegisterClass *RC =
322 if (RC != &AArch64::FPR32RegClass &&
323 ((RC != &AArch64::FPR64RegClass && RC != &AArch64::FPR128RegClass &&
324 RC != &AArch64::ZPRRegClass) ||
331 TII->get(TargetOpcode::COPY), CpySrc)
341 else if (SrcMI->
getOpcode() <= TargetOpcode::GENERIC_OP_END)
349 MI.eraseFromParent();
354bool AArch64MIPeepholeOptImpl::visitCSEL(MachineInstr &
MI) {
356 if (
MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg())
360 MI.getOpcode() == AArch64::CSELXr ? AArch64::XZR : AArch64::WZR;
362 MI.getOpcode() == AArch64::CSELXr ? AArch64::ORRXrs : AArch64::ORRWrs;
365 .
addReg(
MI.getOperand(0).getReg(), RegState::Define)
370 MI.eraseFromParent();
374bool AArch64MIPeepholeOptImpl::visitINSERT(MachineInstr &
MI) {
382 if (!
MI.isRegTiedToDefOperand(1))
386 const TargetRegisterClass *RC = MRI->
getRegClass(DstReg);
401 if ((SrcMI->
getOpcode() <= TargetOpcode::GENERIC_OP_END) ||
402 !AArch64::GPR64allRegClass.hasSubClassEq(RC))
406 MachineInstr *SubregMI =
408 TII->get(TargetOpcode::SUBREG_TO_REG), DstReg)
409 .
add(
MI.getOperand(2))
410 .
add(
MI.getOperand(3));
413 MI.eraseFromParent();
422 if ((Imm & 0xfff000) == 0 || (Imm & 0xfff) == 0 ||
423 (Imm & ~
static_cast<T>(0xffffff)) != 0)
429 if (Insn.
size() == 1)
433 Imm0 = (Imm >> 12) & 0xfff;
439bool AArch64MIPeepholeOptImpl::visitADDSUB(
unsigned PosOpc,
unsigned NegOpc,
457 if (
MI.getOperand(1).getReg() == AArch64::XZR ||
458 MI.getOperand(1).getReg() == AArch64::WZR)
461 return splitTwoPartImm<T>(
463 [PosOpc, NegOpc](
T Imm,
unsigned RegSize,
T &Imm0,
464 T &Imm1) -> std::optional<OpcodePair> {
466 return std::make_pair(PosOpc, PosOpc);
468 return std::make_pair(NegOpc, NegOpc);
471 [&
TII =
TII](MachineInstr &
MI, OpcodePair Opcode,
unsigned Imm0,
475 MachineBasicBlock *
MBB =
MI.getParent();
488bool AArch64MIPeepholeOptImpl::visitADDSSUBS(OpcodePair PosOpcs,
494 if (
MI.getOperand(1).getReg() == AArch64::XZR ||
495 MI.getOperand(1).getReg() == AArch64::WZR)
498 return splitTwoPartImm<T>(
501 &MRI = MRI](
T Imm,
unsigned RegSize,
T &Imm0,
502 T &Imm1) -> std::optional<OpcodePair> {
514 if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
518 [&
TII =
TII](MachineInstr &
MI, OpcodePair Opcode,
unsigned Imm0,
522 MachineBasicBlock *
MBB =
MI.getParent();
536bool AArch64MIPeepholeOptImpl::checkMovImmInstr(MachineInstr &
MI,
537 MachineInstr *&MovMI,
538 MachineInstr *&SubregToRegMI) {
540 MachineBasicBlock *
MBB =
MI.getParent();
542 if (L && !
L->isLoopInvariant(
MI))
551 SubregToRegMI =
nullptr;
552 if (MovMI->
getOpcode() == TargetOpcode::SUBREG_TO_REG) {
553 SubregToRegMI = MovMI;
559 if (MovMI->
getOpcode() != AArch64::MOVi32imm &&
560 MovMI->
getOpcode() != AArch64::MOVi64imm)
575bool AArch64MIPeepholeOptImpl::splitTwoPartImm(MachineInstr &
MI,
576 SplitAndOpcFunc<T> SplitAndOpc,
577 BuildMIFunc BuildInstr) {
580 "Invalid RegSize for legal immediate peephole optimization");
583 MachineInstr *MovMI, *SubregToRegMI;
584 if (!checkMovImmInstr(
MI, MovMI, SubregToRegMI))
596 if (
auto R = SplitAndOpc(Imm,
RegSize, Imm0, Imm1))
607 const TargetRegisterClass *FirstInstrDstRC =
608 TII->getRegClass(
TII->get(Opcode.first), 0);
609 const TargetRegisterClass *FirstInstrOperandRC =
610 TII->getRegClass(
TII->get(Opcode.first), 1);
611 const TargetRegisterClass *SecondInstrDstRC =
612 (Opcode.first == Opcode.second)
615 const TargetRegisterClass *SecondInstrOperandRC =
616 (Opcode.first == Opcode.second)
617 ? FirstInstrOperandRC
618 :
TII->getRegClass(
TII->get(Opcode.second), 1);
633 if (DstReg != NewDstReg)
637 BuildInstr(
MI, Opcode, Imm0, Imm1, SrcReg, NewTmpReg, NewDstReg);
641 if (DstReg != NewDstReg) {
643 MI.getOperand(0).setReg(DstReg);
647 MI.eraseFromParent();
655bool AArch64MIPeepholeOptImpl::visitINSviGPR(MachineInstr &
MI,
unsigned Opc) {
672 if (!SrcMI || SrcMI->
getOpcode() != TargetOpcode::COPY)
679 &AArch64::FPR128RegClass) {
687 MachineInstr *INSvilaneMI =
689 .
add(
MI.getOperand(1))
690 .
add(
MI.getOperand(2))
696 MI.eraseFromParent();
706 if (!
MI->getOperand(0).isReg() || !
MI->getOperand(0).isDef())
709 if (RC != &AArch64::FPR64RegClass)
711 if (
MI->getOpcode() == TargetOpcode::COPY) {
715 if (
SrcOp.getSubReg())
718 auto IsGPR64Like = [&]() ->
bool {
720 return AArch64::GPR64allRegClass.hasSubClassEq(
722 return AArch64::GPR64allRegClass.contains(SrcReg);
726 assert(
TII &&
"Expected InstrInfo when materializing COPYs");
729 bool SrcKill = SrcMO.
isKill();
731 if (MRI->
getRegClass(SrcReg) != &AArch64::GPR64RegClass) {
736 TII->get(TargetOpcode::COPY), NewSrc)
741 }
else if (!AArch64::GPR64RegClass.
contains(SrcReg)) {
749 MI->setDesc(
TII->get(AArch64::FMOVXDr));
752 return MI->getOpcode() > TargetOpcode::GENERIC_OP_END;
755bool AArch64MIPeepholeOptImpl::visitINSvi64lane(MachineInstr &
MI) {
764 if (Low64MI->
getOpcode() != AArch64::INSERT_SUBREG)
784 if (!High64MI || High64MI->
getOpcode() != AArch64::INSERT_SUBREG)
787 if (High64MI && High64MI->
getOpcode() == TargetOpcode::COPY)
789 if (!High64MI || (High64MI->
getOpcode() != AArch64::MOVID &&
790 High64MI->
getOpcode() != AArch64::MOVIv2d_ns))
800 MI.eraseFromParent();
805bool AArch64MIPeepholeOptImpl::visitFMOVDr(MachineInstr &
MI) {
819 MI.eraseFromParent();
824bool AArch64MIPeepholeOptImpl::visitUBFMXri(MachineInstr &
MI) {
827 int64_t Immr =
MI.getOperand(2).getImm();
828 int64_t Imms =
MI.getOperand(3).getImm();
830 bool IsLSR = Imms == 31 && Immr <= Imms;
831 bool IsLSL = Immr == Imms + 33;
832 if (!IsLSR && !IsLSL)
839 const TargetRegisterClass *DstRC64 =
840 TII->getRegClass(
TII->get(
MI.getOpcode()), 0);
841 const TargetRegisterClass *DstRC32 =
842 TRI->getSubRegisterClass(DstRC64, AArch64::sub_32);
843 assert(DstRC32 &&
"Destination register class of UBFMXri doesn't have a "
844 "sub_32 subregister class");
846 const TargetRegisterClass *SrcRC64 =
847 TII->getRegClass(
TII->get(
MI.getOpcode()), 1);
848 const TargetRegisterClass *SrcRC32 =
849 TRI->getSubRegisterClass(SrcRC64, AArch64::sub_32);
850 assert(SrcRC32 &&
"Source register class of UBFMXri doesn't have a sub_32 "
851 "subregister class");
853 Register DstReg64 =
MI.getOperand(0).getReg();
855 Register SrcReg64 =
MI.getOperand(1).getReg();
860 .
addReg(SrcReg64, {}, AArch64::sub_32);
867 TII->get(AArch64::SUBREG_TO_REG), DstReg64)
870 MI.eraseFromParent();
877bool AArch64MIPeepholeOptImpl::visitCopy(MachineInstr &
MI) {
878 Register InputReg =
MI.getOperand(1).getReg();
879 if (
MI.getOperand(1).getSubReg() != AArch64::sub_32 ||
884 SmallPtrSet<MachineInstr *, 4> DeadInstrs;
896 auto getSXTWSrcReg = [](MachineInstr *SrcMI) ->
Register {
897 if (SrcMI->
getOpcode() != AArch64::SBFMXri ||
900 return AArch64::NoRegister;
904 auto getUXTWSrcReg = [&](MachineInstr *SrcMI) ->
Register {
905 if (SrcMI->
getOpcode() != AArch64::SUBREG_TO_REG ||
908 return AArch64::NoRegister;
910 if (!Orr || Orr->
getOpcode() != AArch64::ORRWrr ||
913 return AArch64::NoRegister;
915 if (!Cpy || Cpy->
getOpcode() != AArch64::COPY ||
917 return AArch64::NoRegister;
922 Register SrcReg = getSXTWSrcReg(SrcMI);
924 SrcReg = getUXTWSrcReg(SrcMI);
930 MI.getOperand(1).setReg(SrcReg);
932 for (
auto *DeadMI : DeadInstrs) {
934 DeadMI->eraseFromParent();
939bool AArch64MIPeepholeOptImpl::run(MachineFunction &MF) {
940 TII =
static_cast<const AArch64InstrInfo *
>(MF.
getSubtarget().getInstrInfo());
941 TRI =
static_cast<const AArch64RegisterInfo *
>(
945 assert(MRI->
isSSA() &&
"Expected to be run on SSA form!");
949 for (MachineBasicBlock &
MBB : MF) {
951 switch (
MI.getOpcode()) {
954 case AArch64::INSERT_SUBREG:
957 case AArch64::ANDWrr:
958 Changed |= trySplitLogicalImm<uint32_t>(AArch64::ANDWri,
MI,
959 SplitStrategy::Intersect);
961 case AArch64::ANDXrr:
962 Changed |= trySplitLogicalImm<uint64_t>(AArch64::ANDXri,
MI,
963 SplitStrategy::Intersect);
965 case AArch64::ANDSWrr:
966 Changed |= trySplitLogicalImm<uint32_t>(
967 AArch64::ANDWri,
MI, SplitStrategy::Intersect, AArch64::ANDSWri);
969 case AArch64::ANDSXrr:
970 Changed |= trySplitLogicalImm<uint64_t>(
971 AArch64::ANDXri,
MI, SplitStrategy::Intersect, AArch64::ANDSXri);
973 case AArch64::EORWrr:
974 Changed |= trySplitLogicalImm<uint32_t>(AArch64::EORWri,
MI,
975 SplitStrategy::Disjoint);
977 case AArch64::EORXrr:
978 Changed |= trySplitLogicalImm<uint64_t>(AArch64::EORXri,
MI,
979 SplitStrategy::Disjoint);
981 case AArch64::ORRWrr:
982 Changed |= trySplitLogicalImm<uint32_t>(AArch64::ORRWri,
MI,
983 SplitStrategy::Disjoint);
985 case AArch64::ORRXrr:
986 Changed |= trySplitLogicalImm<uint64_t>(AArch64::ORRXri,
MI,
987 SplitStrategy::Disjoint);
989 case AArch64::ORRWrs:
992 case AArch64::ADDWrr:
993 Changed |= visitADDSUB<uint32_t>(AArch64::ADDWri, AArch64::SUBWri,
MI);
995 case AArch64::SUBWrr:
996 Changed |= visitADDSUB<uint32_t>(AArch64::SUBWri, AArch64::ADDWri,
MI);
998 case AArch64::ADDXrr:
999 Changed |= visitADDSUB<uint64_t>(AArch64::ADDXri, AArch64::SUBXri,
MI);
1001 case AArch64::SUBXrr:
1002 Changed |= visitADDSUB<uint64_t>(AArch64::SUBXri, AArch64::ADDXri,
MI);
1004 case AArch64::ADDSWrr:
1006 visitADDSSUBS<uint32_t>({AArch64::ADDWri, AArch64::ADDSWri},
1007 {AArch64::SUBWri, AArch64::SUBSWri},
MI);
1009 case AArch64::SUBSWrr:
1011 visitADDSSUBS<uint32_t>({AArch64::SUBWri, AArch64::SUBSWri},
1012 {AArch64::ADDWri, AArch64::ADDSWri},
MI);
1014 case AArch64::ADDSXrr:
1016 visitADDSSUBS<uint64_t>({AArch64::ADDXri, AArch64::ADDSXri},
1017 {AArch64::SUBXri, AArch64::SUBSXri},
MI);
1019 case AArch64::SUBSXrr:
1021 visitADDSSUBS<uint64_t>({AArch64::SUBXri, AArch64::SUBSXri},
1022 {AArch64::ADDXri, AArch64::ADDSXri},
MI);
1024 case AArch64::CSELWr:
1025 case AArch64::CSELXr:
1028 case AArch64::INSvi64gpr:
1029 Changed |= visitINSviGPR(
MI, AArch64::INSvi64lane);
1031 case AArch64::INSvi32gpr:
1032 Changed |= visitINSviGPR(
MI, AArch64::INSvi32lane);
1034 case AArch64::INSvi16gpr:
1035 Changed |= visitINSviGPR(
MI, AArch64::INSvi16lane);
1037 case AArch64::INSvi8gpr:
1038 Changed |= visitINSviGPR(
MI, AArch64::INSvi8lane);
1040 case AArch64::INSvi64lane:
1043 case AArch64::FMOVDr:
1046 case AArch64::UBFMXri:
1059bool AArch64MIPeepholeOptLegacy::runOnMachineFunction(MachineFunction &MF) {
1063 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1064 return AArch64MIPeepholeOptImpl(MLI).run(MF);
1068 return new AArch64MIPeepholeOptLegacy();
1075 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)
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.
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.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
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 void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
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...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI 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.
StringRef - 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...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.