diff options
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel/Utils.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/Utils.cpp | 403 |
1 files changed, 313 insertions, 90 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index f64e41b9dccc..1a440c064a59 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -15,7 +15,9 @@ #include "llvm/ADT/Optional.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -60,6 +62,8 @@ Register llvm::constrainOperandRegClass( if (ConstrainedReg != Reg) { MachineBasicBlock::iterator InsertIt(&InsertPt); MachineBasicBlock &MBB = *InsertPt.getParent(); + // FIXME: The copy needs to have the classes constrained for its operands. + // Use operand's regbank to get the class for old register (Reg). if (RegMO.isUse()) { BuildMI(MBB, InsertIt, InsertPt.getDebugLoc(), TII.get(TargetOpcode::COPY), ConstrainedReg) @@ -99,19 +103,25 @@ Register llvm::constrainOperandRegClass( // Assume physical registers are properly constrained. assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented"); - const TargetRegisterClass *RegClass = TII.getRegClass(II, OpIdx, &TRI, MF); + const TargetRegisterClass *OpRC = TII.getRegClass(II, OpIdx, &TRI, MF); // Some of the target independent instructions, like COPY, may not impose any // register class constraints on some of their operands: If it's a use, we can // skip constraining as the instruction defining the register would constrain // it. - // We can't constrain unallocatable register classes, because we can't create - // virtual registers for these classes, so we need to let targets handled this - // case. - if (RegClass && !RegClass->isAllocatable()) - RegClass = TRI.getConstrainedRegClassForOperand(RegMO, MRI); + if (OpRC) { + // Obtain the RC from incoming regbank if it is a proper sub-class. Operands + // can have multiple regbanks for a superclass that combine different + // register types (E.g., AMDGPU's VGPR and AGPR). The regbank ambiguity + // resolved by targets during regbankselect should not be overridden. + if (const auto *SubRC = TRI.getCommonSubClass( + OpRC, TRI.getConstrainedRegClassForOperand(RegMO, MRI))) + OpRC = SubRC; - if (!RegClass) { + OpRC = TRI.getAllocatableClass(OpRC); + } + + if (!OpRC) { assert((!isTargetSpecificOpcode(II.getOpcode()) || RegMO.isUse()) && "Register class constraint is required unless either the " "instruction is target independent or the operand is a use"); @@ -127,7 +137,7 @@ Register llvm::constrainOperandRegClass( // and they never reach this function. return Reg; } - return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, *RegClass, + return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, *OpRC, RegMO); } @@ -236,7 +246,7 @@ static void reportGISelDiagnostic(DiagnosticSeverity Severity, R << (" (in function: " + MF.getName() + ")").str(); if (IsFatal) - report_fatal_error(R.getMsg()); + report_fatal_error(Twine(R.getMsg())); else MORE.emit(R); } @@ -267,10 +277,10 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, reportGISelFailure(MF, TPC, MORE, R); } -Optional<APInt> llvm::getConstantVRegVal(Register VReg, - const MachineRegisterInfo &MRI) { - Optional<ValueAndVReg> ValAndVReg = - getConstantVRegValWithLookThrough(VReg, MRI, /*LookThroughInstrs*/ false); +Optional<APInt> llvm::getIConstantVRegVal(Register VReg, + const MachineRegisterInfo &MRI) { + Optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough( + VReg, MRI, /*LookThroughInstrs*/ false); assert((!ValAndVReg || ValAndVReg->VReg == VReg) && "Value found while looking through instrs"); if (!ValAndVReg) @@ -278,41 +288,27 @@ Optional<APInt> llvm::getConstantVRegVal(Register VReg, return ValAndVReg->Value; } -Optional<int64_t> llvm::getConstantVRegSExtVal(Register VReg, - const MachineRegisterInfo &MRI) { - Optional<APInt> Val = getConstantVRegVal(VReg, MRI); +Optional<int64_t> +llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) { + Optional<APInt> Val = getIConstantVRegVal(VReg, MRI); if (Val && Val->getBitWidth() <= 64) return Val->getSExtValue(); return None; } -Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough( - Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs, - bool HandleFConstant, bool LookThroughAnyExt) { +namespace { + +typedef std::function<bool(const MachineInstr *)> IsOpcodeFn; +typedef std::function<Optional<APInt>(const MachineInstr *MI)> GetAPCstFn; + +Optional<ValueAndVReg> getConstantVRegValWithLookThrough( + Register VReg, const MachineRegisterInfo &MRI, IsOpcodeFn IsConstantOpcode, + GetAPCstFn getAPCstValue, bool LookThroughInstrs = true, + bool LookThroughAnyExt = false) { SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes; MachineInstr *MI; - auto IsConstantOpcode = [HandleFConstant](unsigned Opcode) { - return Opcode == TargetOpcode::G_CONSTANT || - (HandleFConstant && Opcode == TargetOpcode::G_FCONSTANT); - }; - auto GetImmediateValue = [HandleFConstant, - &MRI](const MachineInstr &MI) -> Optional<APInt> { - const MachineOperand &CstVal = MI.getOperand(1); - if (!CstVal.isImm() && !CstVal.isCImm() && - (!HandleFConstant || !CstVal.isFPImm())) - return None; - if (!CstVal.isFPImm()) { - unsigned BitWidth = - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - APInt Val = CstVal.isImm() ? APInt(BitWidth, CstVal.getImm()) - : CstVal.getCImm()->getValue(); - assert(Val.getBitWidth() == BitWidth && - "Value bitwidth doesn't match definition type"); - return Val; - } - return CstVal.getFPImm()->getValueAPF().bitcastToAPInt(); - }; - while ((MI = MRI.getVRegDef(VReg)) && !IsConstantOpcode(MI->getOpcode()) && + + while ((MI = MRI.getVRegDef(VReg)) && !IsConstantOpcode(MI) && LookThroughInstrs) { switch (MI->getOpcode()) { case TargetOpcode::G_ANYEXT: @@ -339,10 +335,10 @@ Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough( return None; } } - if (!MI || !IsConstantOpcode(MI->getOpcode())) + if (!MI || !IsConstantOpcode(MI)) return None; - Optional<APInt> MaybeVal = GetImmediateValue(*MI); + Optional<APInt> MaybeVal = getAPCstValue(MI); if (!MaybeVal) return None; APInt &Val = *MaybeVal; @@ -365,12 +361,65 @@ Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough( return ValueAndVReg{Val, VReg}; } -const ConstantInt *llvm::getConstantIntVRegVal(Register VReg, - const MachineRegisterInfo &MRI) { - MachineInstr *MI = MRI.getVRegDef(VReg); - if (MI->getOpcode() != TargetOpcode::G_CONSTANT) - return nullptr; - return MI->getOperand(1).getCImm(); +bool isIConstant(const MachineInstr *MI) { + if (!MI) + return false; + return MI->getOpcode() == TargetOpcode::G_CONSTANT; +} + +bool isFConstant(const MachineInstr *MI) { + if (!MI) + return false; + return MI->getOpcode() == TargetOpcode::G_FCONSTANT; +} + +bool isAnyConstant(const MachineInstr *MI) { + if (!MI) + return false; + unsigned Opc = MI->getOpcode(); + return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_FCONSTANT; +} + +Optional<APInt> getCImmAsAPInt(const MachineInstr *MI) { + const MachineOperand &CstVal = MI->getOperand(1); + if (CstVal.isCImm()) + return CstVal.getCImm()->getValue(); + return None; +} + +Optional<APInt> getCImmOrFPImmAsAPInt(const MachineInstr *MI) { + const MachineOperand &CstVal = MI->getOperand(1); + if (CstVal.isCImm()) + return CstVal.getCImm()->getValue(); + if (CstVal.isFPImm()) + return CstVal.getFPImm()->getValueAPF().bitcastToAPInt(); + return None; +} + +} // end anonymous namespace + +Optional<ValueAndVReg> llvm::getIConstantVRegValWithLookThrough( + Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) { + return getConstantVRegValWithLookThrough(VReg, MRI, isIConstant, + getCImmAsAPInt, LookThroughInstrs); +} + +Optional<ValueAndVReg> llvm::getAnyConstantVRegValWithLookThrough( + Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs, + bool LookThroughAnyExt) { + return getConstantVRegValWithLookThrough( + VReg, MRI, isAnyConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs, + LookThroughAnyExt); +} + +Optional<FPValueAndVReg> llvm::getFConstantVRegValWithLookThrough( + Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) { + auto Reg = getConstantVRegValWithLookThrough( + VReg, MRI, isFConstant, getCImmOrFPImmAsAPInt, LookThroughInstrs); + if (!Reg) + return None; + return FPValueAndVReg{getConstantFPVRegVal(Reg->VReg, MRI)->getValueAPF(), + Reg->VReg}; } const ConstantFP * @@ -437,16 +486,16 @@ APFloat llvm::getAPFloatFromSize(double Val, unsigned Size) { Optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI) { - auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI); + auto MaybeOp2Cst = getAnyConstantVRegValWithLookThrough(Op2, MRI, false); if (!MaybeOp2Cst) return None; - auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI); + auto MaybeOp1Cst = getAnyConstantVRegValWithLookThrough(Op1, MRI, false); if (!MaybeOp1Cst) return None; - const APInt &C1 = *MaybeOp1Cst; - const APInt &C2 = *MaybeOp2Cst; + const APInt &C1 = MaybeOp1Cst->Value; + const APInt &C2 = MaybeOp2Cst->Value; switch (Opcode) { default: break; @@ -543,6 +592,35 @@ Optional<APFloat> llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, return None; } +Optional<MachineInstr *> +llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1, + const Register Op2, + const MachineRegisterInfo &MRI, + MachineIRBuilder &MIB) { + auto *SrcVec1 = getOpcodeDef<GBuildVector>(Op1, MRI); + if (!SrcVec1) + return None; + auto *SrcVec2 = getOpcodeDef<GBuildVector>(Op2, MRI); + if (!SrcVec2) + return None; + + const LLT EltTy = MRI.getType(SrcVec1->getSourceReg(0)); + + SmallVector<Register, 16> FoldedElements; + for (unsigned Idx = 0, E = SrcVec1->getNumSources(); Idx < E; ++Idx) { + auto MaybeCst = ConstantFoldBinOp(Opcode, SrcVec1->getSourceReg(Idx), + SrcVec2->getSourceReg(Idx), MRI); + if (!MaybeCst) + return None; + auto FoldedCstReg = MIB.buildConstant(EltTy, *MaybeCst).getReg(0); + FoldedElements.emplace_back(FoldedCstReg); + } + // Create the new vector constant. + auto CstVec = + MIB.buildBuildVector(MRI.getType(SrcVec1->getReg(0)), FoldedElements); + return &*CstVec; +} + bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, bool SNaN) { const MachineInstr *DefMI = MRI.getVRegDef(Val); @@ -659,7 +737,7 @@ Register llvm::getFunctionLiveInPhysReg(MachineFunction &MF, Optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode, const Register Op1, uint64_t Imm, const MachineRegisterInfo &MRI) { - auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI); + auto MaybeOp1Cst = getIConstantVRegVal(Op1, MRI); if (MaybeOp1Cst) { switch (Opcode) { default: @@ -677,7 +755,7 @@ Optional<APFloat> llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI) { assert(Opcode == TargetOpcode::G_SITOFP || Opcode == TargetOpcode::G_UITOFP); - if (auto MaybeSrcVal = getConstantVRegVal(Src, MRI)) { + if (auto MaybeSrcVal = getIConstantVRegVal(Src, MRI)) { APFloat DstVal(getFltSemanticForLLT(DstTy)); DstVal.convertFromAPInt(*MaybeSrcVal, Opcode == TargetOpcode::G_SITOFP, APFloat::rmNearestTiesToEven); @@ -686,6 +764,37 @@ Optional<APFloat> llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, return None; } +Optional<SmallVector<unsigned>> +llvm::ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI) { + LLT Ty = MRI.getType(Src); + SmallVector<unsigned> FoldedCTLZs; + auto tryFoldScalar = [&](Register R) -> Optional<unsigned> { + auto MaybeCst = getIConstantVRegVal(R, MRI); + if (!MaybeCst) + return None; + return MaybeCst->countLeadingZeros(); + }; + if (Ty.isVector()) { + // Try to constant fold each element. + auto *BV = getOpcodeDef<GBuildVector>(Src, MRI); + if (!BV) + return None; + for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) { + if (auto MaybeFold = tryFoldScalar(BV->getSourceReg(SrcIdx))) { + FoldedCTLZs.emplace_back(*MaybeFold); + continue; + } + return None; + } + return FoldedCTLZs; + } + if (auto MaybeCst = tryFoldScalar(Src)) { + FoldedCTLZs.emplace_back(*MaybeCst); + return FoldedCTLZs; + } + return None; +} + bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI, GISelKnownBits *KB) { Optional<DefinitionAndSourceRegister> DefSrcReg = @@ -707,7 +816,7 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI, // shifting the bit off the end is undefined. // TODO: Constant splat - if (auto ConstLHS = getConstantVRegVal(MI.getOperand(1).getReg(), MRI)) { + if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) { if (*ConstLHS == 1) return true; } @@ -715,7 +824,7 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI, break; } case TargetOpcode::G_LSHR: { - if (auto ConstLHS = getConstantVRegVal(MI.getOperand(1).getReg(), MRI)) { + if (auto ConstLHS = getIConstantVRegVal(MI.getOperand(1).getReg(), MRI)) { if (ConstLHS->isSignMask()) return true; } @@ -737,7 +846,7 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI, // zeros is greater than the truncation amount. const unsigned BitWidth = Ty.getScalarSizeInBits(); for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { - auto Const = getConstantVRegVal(MI.getOperand(I).getReg(), MRI); + auto Const = getIConstantVRegVal(MI.getOperand(I).getReg(), MRI); if (!Const || !Const->zextOrTrunc(BitWidth).isPowerOf2()) return false; } @@ -885,53 +994,81 @@ static bool isBuildVectorOp(unsigned Opcode) { Opcode == TargetOpcode::G_BUILD_VECTOR_TRUNC; } -// TODO: Handle mixed undef elements. -static bool isBuildVectorConstantSplat(const MachineInstr &MI, - const MachineRegisterInfo &MRI, - int64_t SplatValue) { - if (!isBuildVectorOp(MI.getOpcode())) - return false; +namespace { - const unsigned NumOps = MI.getNumOperands(); - for (unsigned I = 1; I != NumOps; ++I) { - Register Element = MI.getOperand(I).getReg(); - if (!mi_match(Element, MRI, m_SpecificICst(SplatValue))) - return false; +Optional<ValueAndVReg> getAnyConstantSplat(Register VReg, + const MachineRegisterInfo &MRI, + bool AllowUndef) { + MachineInstr *MI = getDefIgnoringCopies(VReg, MRI); + if (!MI) + return None; + + if (!isBuildVectorOp(MI->getOpcode())) + return None; + + Optional<ValueAndVReg> SplatValAndReg = None; + for (MachineOperand &Op : MI->uses()) { + Register Element = Op.getReg(); + auto ElementValAndReg = + getAnyConstantVRegValWithLookThrough(Element, MRI, true, true); + + // If AllowUndef, treat undef as value that will result in a constant splat. + if (!ElementValAndReg) { + if (AllowUndef && isa<GImplicitDef>(MRI.getVRegDef(Element))) + continue; + return None; + } + + // Record splat value + if (!SplatValAndReg) + SplatValAndReg = ElementValAndReg; + + // Different constant then the one already recorded, not a constant splat. + if (SplatValAndReg->Value != ElementValAndReg->Value) + return None; } - return true; + return SplatValAndReg; } +bool isBuildVectorConstantSplat(const MachineInstr &MI, + const MachineRegisterInfo &MRI, + int64_t SplatValue, bool AllowUndef) { + if (auto SplatValAndReg = + getAnyConstantSplat(MI.getOperand(0).getReg(), MRI, AllowUndef)) + return mi_match(SplatValAndReg->VReg, MRI, m_SpecificICst(SplatValue)); + return false; +} + +} // end anonymous namespace + Optional<int64_t> llvm::getBuildVectorConstantSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI) { - if (!isBuildVectorOp(MI.getOpcode())) - return None; - - const unsigned NumOps = MI.getNumOperands(); - Optional<int64_t> Scalar; - for (unsigned I = 1; I != NumOps; ++I) { - Register Element = MI.getOperand(I).getReg(); - int64_t ElementValue; - if (!mi_match(Element, MRI, m_ICst(ElementValue))) - return None; - if (!Scalar) - Scalar = ElementValue; - else if (*Scalar != ElementValue) - return None; - } + if (auto SplatValAndReg = + getAnyConstantSplat(MI.getOperand(0).getReg(), MRI, false)) + return getIConstantVRegSExtVal(SplatValAndReg->VReg, MRI); + return None; +} - return Scalar; +Optional<FPValueAndVReg> llvm::getFConstantSplat(Register VReg, + const MachineRegisterInfo &MRI, + bool AllowUndef) { + if (auto SplatValAndReg = getAnyConstantSplat(VReg, MRI, AllowUndef)) + return getFConstantVRegValWithLookThrough(SplatValAndReg->VReg, MRI); + return None; } bool llvm::isBuildVectorAllZeros(const MachineInstr &MI, - const MachineRegisterInfo &MRI) { - return isBuildVectorConstantSplat(MI, MRI, 0); + const MachineRegisterInfo &MRI, + bool AllowUndef) { + return isBuildVectorConstantSplat(MI, MRI, 0, AllowUndef); } bool llvm::isBuildVectorAllOnes(const MachineInstr &MI, - const MachineRegisterInfo &MRI) { - return isBuildVectorConstantSplat(MI, MRI, -1); + const MachineRegisterInfo &MRI, + bool AllowUndef) { + return isBuildVectorConstantSplat(MI, MRI, -1, AllowUndef); } Optional<RegOrConstant> llvm::getVectorSplat(const MachineInstr &MI, @@ -948,6 +1085,36 @@ Optional<RegOrConstant> llvm::getVectorSplat(const MachineInstr &MI, return RegOrConstant(Reg); } +bool llvm::isConstantOrConstantVector(MachineInstr &MI, + const MachineRegisterInfo &MRI) { + Register Def = MI.getOperand(0).getReg(); + if (auto C = getIConstantVRegValWithLookThrough(Def, MRI)) + return true; + GBuildVector *BV = dyn_cast<GBuildVector>(&MI); + if (!BV) + return false; + for (unsigned SrcIdx = 0; SrcIdx < BV->getNumSources(); ++SrcIdx) { + if (getIConstantVRegValWithLookThrough(BV->getSourceReg(SrcIdx), MRI) || + getOpcodeDef<GImplicitDef>(BV->getSourceReg(SrcIdx), MRI)) + continue; + return false; + } + return true; +} + +Optional<APInt> +llvm::isConstantOrConstantSplatVector(MachineInstr &MI, + const MachineRegisterInfo &MRI) { + Register Def = MI.getOperand(0).getReg(); + if (auto C = getIConstantVRegValWithLookThrough(Def, MRI)) + return C->Value; + auto MaybeCst = getBuildVectorConstantSplat(MI, MRI); + if (!MaybeCst) + return None; + const unsigned ScalarSize = MRI.getType(Def).getScalarSizeInBits(); + return APInt(ScalarSize, *MaybeCst, true); +} + bool llvm::matchUnaryPredicate( const MachineRegisterInfo &MRI, Register Reg, std::function<bool(const Constant *ConstVal)> Match, bool AllowUndefs) { @@ -1011,3 +1178,59 @@ bool llvm::shouldOptForSize(const MachineBasicBlock &MBB, return F.hasOptSize() || F.hasMinSize() || llvm::shouldOptimizeForSize(MBB.getBasicBlock(), PSI, BFI); } + +/// These artifacts generally don't have any debug users because they don't +/// directly originate from IR instructions, but instead usually from +/// legalization. Avoiding checking for debug users improves compile time. +/// Note that truncates or extends aren't included because they have IR +/// counterparts which can have debug users after translation. +static bool shouldSkipDbgValueFor(MachineInstr &MI) { + switch (MI.getOpcode()) { + case TargetOpcode::G_UNMERGE_VALUES: + case TargetOpcode::G_MERGE_VALUES: + case TargetOpcode::G_CONCAT_VECTORS: + case TargetOpcode::G_BUILD_VECTOR: + case TargetOpcode::G_EXTRACT: + case TargetOpcode::G_INSERT: + return true; + default: + return false; + } +} + +void llvm::saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI, + LostDebugLocObserver *LocObserver, + SmallInstListTy &DeadInstChain) { + for (MachineOperand &Op : MI.uses()) { + if (Op.isReg() && Op.getReg().isVirtual()) + DeadInstChain.insert(MRI.getVRegDef(Op.getReg())); + } + LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n"); + DeadInstChain.remove(&MI); + if (shouldSkipDbgValueFor(MI)) + MI.eraseFromParent(); + else + MI.eraseFromParentAndMarkDBGValuesForRemoval(); + if (LocObserver) + LocObserver->checkpoint(false); +} + +void llvm::eraseInstrs(ArrayRef<MachineInstr *> DeadInstrs, + MachineRegisterInfo &MRI, + LostDebugLocObserver *LocObserver) { + SmallInstListTy DeadInstChain; + for (MachineInstr *MI : DeadInstrs) + saveUsesAndErase(*MI, MRI, LocObserver, DeadInstChain); + + while (!DeadInstChain.empty()) { + MachineInstr *Inst = DeadInstChain.pop_back_val(); + if (!isTriviallyDead(*Inst, MRI)) + continue; + saveUsesAndErase(*Inst, MRI, LocObserver, DeadInstChain); + } +} + +void llvm::eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, + LostDebugLocObserver *LocObserver) { + return eraseInstrs({&MI}, MRI, LocObserver); +} |
