diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp | 412 |
1 files changed, 270 insertions, 142 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp index c1a2c4e0bc6e..0f6d9b888f47 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp @@ -86,7 +86,7 @@ namespace { struct MachineVerifier { MachineVerifier(Pass *pass, const char *b) : PASS(pass), Banner(b) {} - unsigned verify(MachineFunction &MF); + unsigned verify(const MachineFunction &MF); Pass *const PASS; const char *Banner; @@ -102,10 +102,10 @@ namespace { bool isFunctionRegBankSelected; bool isFunctionSelected; - using RegVector = SmallVector<unsigned, 16>; + using RegVector = SmallVector<Register, 16>; using RegMaskVector = SmallVector<const uint32_t *, 4>; - using RegSet = DenseSet<unsigned>; - using RegMap = DenseMap<unsigned, const MachineInstr *>; + using RegSet = DenseSet<Register>; + using RegMap = DenseMap<Register, const MachineInstr *>; using BlockSet = SmallPtrSet<const MachineBasicBlock *, 8>; const MachineInstr *FirstNonPHI; @@ -120,11 +120,10 @@ namespace { SlotIndex lastIndex; // Add Reg and any sub-registers to RV - void addRegWithSubRegs(RegVector &RV, unsigned Reg) { + void addRegWithSubRegs(RegVector &RV, Register Reg) { RV.push_back(Reg); - if (Register::isPhysicalRegister(Reg)) - for (const MCPhysReg &SubReg : TRI->subregs(Reg)) - RV.push_back(SubReg); + if (Reg.isPhysical()) + append_range(RV, TRI->subregs(Reg.asMCReg())); } struct BBInfo { @@ -132,7 +131,8 @@ namespace { bool reachable = false; // Vregs that must be live in because they are used without being - // defined. Map value is the user. + // defined. Map value is the user. vregsLiveIn doesn't include regs + // that only are used by PHI nodes. RegMap vregsLiveIn; // Regs killed in MBB. They may be defined again, and will then be in both @@ -158,8 +158,8 @@ namespace { // Add register to vregsRequired if it belongs there. Return true if // anything changed. - bool addRequired(unsigned Reg) { - if (!Register::isVirtualRegister(Reg)) + bool addRequired(Register Reg) { + if (!Reg.isVirtual()) return false; if (regsLiveOut.count(Reg)) return false; @@ -169,7 +169,7 @@ namespace { // Same for a full set. bool addRequired(const RegSet &RS) { bool Changed = false; - for (unsigned Reg : RS) + for (Register Reg : RS) Changed |= addRequired(Reg); return Changed; } @@ -183,7 +183,7 @@ namespace { } // Live-out registers are either in regsLiveOut or vregsPassed. - bool isLiveOut(unsigned Reg) const { + bool isLiveOut(Register Reg) const { return regsLiveOut.count(Reg) || vregsPassed.count(Reg); } }; @@ -191,13 +191,13 @@ namespace { // Extra register info per MBB. DenseMap<const MachineBasicBlock*, BBInfo> MBBInfoMap; - bool isReserved(unsigned Reg) { - return Reg < regsReserved.size() && regsReserved.test(Reg); + bool isReserved(Register Reg) { + return Reg.id() < regsReserved.size() && regsReserved.test(Reg.id()); } - bool isAllocatable(unsigned Reg) const { - return Reg < TRI->getNumRegs() && TRI->isInAllocatableClass(Reg) && - !regsReserved.test(Reg); + bool isAllocatable(Register Reg) const { + return Reg.id() < TRI->getNumRegs() && TRI->isInAllocatableClass(Reg) && + !regsReserved.test(Reg.id()); } // Analysis information if available @@ -225,7 +225,7 @@ namespace { LLT MOVRegType = LLT{}); void report_context(const LiveInterval &LI) const; - void report_context(const LiveRange &LR, unsigned VRegUnit, + void report_context(const LiveRange &LR, Register VRegUnit, LaneBitmask LaneMask) const; void report_context(const LiveRange::Segment &S) const; void report_context(const VNInfo &VNI) const; @@ -233,18 +233,19 @@ namespace { void report_context(MCPhysReg PhysReg) const; void report_context_liverange(const LiveRange &LR) const; void report_context_lanemask(LaneBitmask LaneMask) const; - void report_context_vreg(unsigned VReg) const; - void report_context_vreg_regunit(unsigned VRegOrUnit) const; + void report_context_vreg(Register VReg) const; + void report_context_vreg_regunit(Register VRegOrUnit) const; void verifyInlineAsm(const MachineInstr *MI); void checkLiveness(const MachineOperand *MO, unsigned MONum); void checkLivenessAtUse(const MachineOperand *MO, unsigned MONum, - SlotIndex UseIdx, const LiveRange &LR, unsigned VRegOrUnit, + SlotIndex UseIdx, const LiveRange &LR, + Register VRegOrUnit, LaneBitmask LaneMask = LaneBitmask::getNone()); void checkLivenessAtDef(const MachineOperand *MO, unsigned MONum, - SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit, - bool SubRangeCheck = false, + SlotIndex DefIdx, const LiveRange &LR, + Register VRegOrUnit, bool SubRangeCheck = false, LaneBitmask LaneMask = LaneBitmask::getNone()); void markReachable(const MachineBasicBlock *MBB); @@ -255,12 +256,12 @@ namespace { void verifyLiveVariables(); void verifyLiveIntervals(); void verifyLiveInterval(const LiveInterval&); - void verifyLiveRangeValue(const LiveRange&, const VNInfo*, unsigned, + void verifyLiveRangeValue(const LiveRange &, const VNInfo *, Register, LaneBitmask); - void verifyLiveRangeSegment(const LiveRange&, - const LiveRange::const_iterator I, unsigned, + void verifyLiveRangeSegment(const LiveRange &, + const LiveRange::const_iterator I, Register, LaneBitmask); - void verifyLiveRange(const LiveRange&, unsigned, + void verifyLiveRange(const LiveRange &, Register, LaneBitmask LaneMask = LaneBitmask::getNone()); void verifyStackFrame(); @@ -303,6 +304,19 @@ FunctionPass *llvm::createMachineVerifierPass(const std::string &Banner) { return new MachineVerifierPass(Banner); } +void llvm::verifyMachineFunction(MachineFunctionAnalysisManager *, + const std::string &Banner, + const MachineFunction &MF) { + // TODO: Use MFAM after porting below analyses. + // LiveVariables *LiveVars; + // LiveIntervals *LiveInts; + // LiveStacks *LiveStks; + // SlotIndexes *Indexes; + unsigned FoundErrors = MachineVerifier(nullptr, Banner.c_str()).verify(MF); + if (FoundErrors) + report_fatal_error("Found " + Twine(FoundErrors) + " machine code errors."); +} + bool MachineFunction::verify(Pass *p, const char *Banner, bool AbortOnErrors) const { MachineFunction &MF = const_cast<MachineFunction&>(*this); @@ -335,7 +349,7 @@ void MachineVerifier::verifyProperties(const MachineFunction &MF) { report("Function has NoVRegs property but there are VReg operands", &MF); } -unsigned MachineVerifier::verify(MachineFunction &MF) { +unsigned MachineVerifier::verify(const MachineFunction &MF) { foundErrors = 0; this->MF = &MF; @@ -474,7 +488,7 @@ void MachineVerifier::report(const char *msg, const MachineInstr *MI) { errs() << "- instruction: "; if (Indexes && Indexes->hasIndex(*MI)) errs() << Indexes->getInstructionIndex(*MI) << '\t'; - MI->print(errs(), /*SkipOpers=*/true); + MI->print(errs(), /*IsStandalone=*/true); } void MachineVerifier::report(const char *msg, const MachineOperand *MO, @@ -494,7 +508,7 @@ void MachineVerifier::report_context(const LiveInterval &LI) const { errs() << "- interval: " << LI << '\n'; } -void MachineVerifier::report_context(const LiveRange &LR, unsigned VRegUnit, +void MachineVerifier::report_context(const LiveRange &LR, Register VRegUnit, LaneBitmask LaneMask) const { report_context_liverange(LR); report_context_vreg_regunit(VRegUnit); @@ -518,11 +532,11 @@ void MachineVerifier::report_context(MCPhysReg PReg) const { errs() << "- p. register: " << printReg(PReg, TRI) << '\n'; } -void MachineVerifier::report_context_vreg(unsigned VReg) const { +void MachineVerifier::report_context_vreg(Register VReg) const { errs() << "- v. register: " << printReg(VReg, TRI) << '\n'; } -void MachineVerifier::report_context_vreg_regunit(unsigned VRegOrUnit) const { +void MachineVerifier::report_context_vreg_regunit(Register VRegOrUnit) const { if (Register::isVirtualRegister(VRegOrUnit)) { report_context_vreg(VRegOrUnit); } else { @@ -776,9 +790,7 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) { } // Ensure non-terminators don't follow terminators. - // Ignore predicated terminators formed by if conversion. - // FIXME: If conversion shouldn't need to violate this rule. - if (MI->isTerminator() && !TII->isPredicated(*MI)) { + if (MI->isTerminator()) { if (!FirstTerminator) FirstTerminator = MI; } else if (FirstTerminator) { @@ -992,16 +1004,15 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { } case TargetOpcode::G_PHI: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); - if (!DstTy.isValid() || - !std::all_of(MI->operands_begin() + 1, MI->operands_end(), - [this, &DstTy](const MachineOperand &MO) { - if (!MO.isReg()) - return true; - LLT Ty = MRI->getType(MO.getReg()); - if (!Ty.isValid() || (Ty != DstTy)) - return false; - return true; - })) + if (!DstTy.isValid() || !all_of(drop_begin(MI->operands()), + [this, &DstTy](const MachineOperand &MO) { + if (!MO.isReg()) + return true; + LLT Ty = MRI->getType(MO.getReg()); + if (!Ty.isValid() || (Ty != DstTy)) + return false; + return true; + })) report("Generic Instruction G_PHI has operands with incompatible/missing " "types", MI); @@ -1343,20 +1354,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { break; } } - switch (IntrID) { - case Intrinsic::memcpy: - if (MI->getNumOperands() != 5) - report("Expected memcpy intrinsic to have 5 operands", MI); - break; - case Intrinsic::memmove: - if (MI->getNumOperands() != 5) - report("Expected memmove intrinsic to have 5 operands", MI); - break; - case Intrinsic::memset: - if (MI->getNumOperands() != 5) - report("Expected memset intrinsic to have 5 operands", MI); - break; - } + break; } case TargetOpcode::G_SEXT_INREG: { @@ -1434,6 +1432,95 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { } break; } + case TargetOpcode::G_MEMCPY: + case TargetOpcode::G_MEMMOVE: { + ArrayRef<MachineMemOperand *> MMOs = MI->memoperands(); + if (MMOs.size() != 2) { + report("memcpy/memmove must have 2 memory operands", MI); + break; + } + + if ((!MMOs[0]->isStore() || MMOs[0]->isLoad()) || + (MMOs[1]->isStore() || !MMOs[1]->isLoad())) { + report("wrong memory operand types", MI); + break; + } + + if (MMOs[0]->getSize() != MMOs[1]->getSize()) + report("inconsistent memory operand sizes", MI); + + LLT DstPtrTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcPtrTy = MRI->getType(MI->getOperand(1).getReg()); + + if (!DstPtrTy.isPointer() || !SrcPtrTy.isPointer()) { + report("memory instruction operand must be a pointer", MI); + break; + } + + if (DstPtrTy.getAddressSpace() != MMOs[0]->getAddrSpace()) + report("inconsistent store address space", MI); + if (SrcPtrTy.getAddressSpace() != MMOs[1]->getAddrSpace()) + report("inconsistent load address space", MI); + + break; + } + case TargetOpcode::G_MEMSET: { + ArrayRef<MachineMemOperand *> MMOs = MI->memoperands(); + if (MMOs.size() != 1) { + report("memset must have 1 memory operand", MI); + break; + } + + if ((!MMOs[0]->isStore() || MMOs[0]->isLoad())) { + report("memset memory operand must be a store", MI); + break; + } + + LLT DstPtrTy = MRI->getType(MI->getOperand(0).getReg()); + if (!DstPtrTy.isPointer()) { + report("memset operand must be a pointer", MI); + break; + } + + if (DstPtrTy.getAddressSpace() != MMOs[0]->getAddrSpace()) + report("inconsistent memset address space", MI); + + break; + } + case TargetOpcode::G_VECREDUCE_SEQ_FADD: + case TargetOpcode::G_VECREDUCE_SEQ_FMUL: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT Src1Ty = MRI->getType(MI->getOperand(1).getReg()); + LLT Src2Ty = MRI->getType(MI->getOperand(2).getReg()); + if (!DstTy.isScalar()) + report("Vector reduction requires a scalar destination type", MI); + if (!Src1Ty.isScalar()) + report("Sequential FADD/FMUL vector reduction requires a scalar 1st operand", MI); + if (!Src2Ty.isVector()) + report("Sequential FADD/FMUL vector reduction must have a vector 2nd operand", MI); + break; + } + case TargetOpcode::G_VECREDUCE_FADD: + case TargetOpcode::G_VECREDUCE_FMUL: + case TargetOpcode::G_VECREDUCE_FMAX: + case TargetOpcode::G_VECREDUCE_FMIN: + case TargetOpcode::G_VECREDUCE_ADD: + case TargetOpcode::G_VECREDUCE_MUL: + case TargetOpcode::G_VECREDUCE_AND: + case TargetOpcode::G_VECREDUCE_OR: + case TargetOpcode::G_VECREDUCE_XOR: + case TargetOpcode::G_VECREDUCE_SMAX: + case TargetOpcode::G_VECREDUCE_SMIN: + case TargetOpcode::G_VECREDUCE_UMAX: + case TargetOpcode::G_VECREDUCE_UMIN: { + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); + if (!DstTy.isScalar()) + report("Vector reduction requires a scalar destination type", MI); + if (!SrcTy.isVector()) + report("Vector reduction requires vector source=", MI); + break; + } default: break; } @@ -1461,6 +1548,16 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { if (MI->isInlineAsm()) verifyInlineAsm(MI); + // Check that unspillable terminators define a reg and have at most one use. + if (TII->isUnspillableTerminator(MI)) { + if (!MI->getOperand(0).isReg() || !MI->getOperand(0).isDef()) + report("Unspillable Terminator does not define a reg", MI); + Register Def = MI->getOperand(0).getReg(); + if (Def.isVirtual() && + std::distance(MRI->use_nodbg_begin(Def), MRI->use_nodbg_end()) > 1) + report("Unspillable Terminator expected to have at most one use!", MI); + } + // A fully-formed DBG_VALUE must have a location. Ignore partially formed // DBG_VALUEs: these are convenient to use in tests, but should never get // generated. @@ -1468,6 +1565,11 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { if (!MI->getDebugLoc()) report("Missing DebugLoc for debug instruction", MI); + // Meta instructions should never be the subject of debug value tracking, + // they don't create a value in the output program at all. + if (MI->isMetaInstruction() && MI->peekDebugInstrNum()) + report("Metadata instruction should not have a value tracking number", MI); + // Check the MachineMemOperands for basic consistency. for (MachineMemOperand *Op : MI->memoperands()) { if (Op->isLoad() && !MI->mayLoad()) @@ -1543,6 +1645,10 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { } auto VerifyStackMapConstant = [&](unsigned Offset) { + if (Offset >= MI->getNumOperands()) { + report("stack map constant to STATEPOINT is out of range!", MI); + return; + } if (!MI->getOperand(Offset - 1).isImm() || MI->getOperand(Offset - 1).getImm() != StackMaps::ConstantOp || !MI->getOperand(Offset).isImm()) @@ -1551,6 +1657,25 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { VerifyStackMapConstant(SO.getCCIdx()); VerifyStackMapConstant(SO.getFlagsIdx()); VerifyStackMapConstant(SO.getNumDeoptArgsIdx()); + VerifyStackMapConstant(SO.getNumGCPtrIdx()); + VerifyStackMapConstant(SO.getNumAllocaIdx()); + VerifyStackMapConstant(SO.getNumGcMapEntriesIdx()); + + // Verify that all explicit statepoint defs are tied to gc operands as + // they are expected to be a relocation of gc operands. + unsigned FirstGCPtrIdx = SO.getFirstGCPtrIdx(); + unsigned LastGCPtrIdx = SO.getNumAllocaIdx() - 2; + for (unsigned Idx = 0; Idx < MI->getNumDefs(); Idx++) { + unsigned UseOpIdx; + if (!MI->isRegTiedToUseOperand(Idx, &UseOpIdx)) { + report("STATEPOINT defs expected to be tied", MI); + break; + } + if (UseOpIdx < FirstGCPtrIdx || UseOpIdx > LastGCPtrIdx) { + report("STATEPOINT def tied to non-gc operand", MI); + break; + } + } // TODO: verify we have properly encoded deopt arguments } break; @@ -1865,8 +1990,10 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO, - unsigned MONum, SlotIndex UseIdx, const LiveRange &LR, unsigned VRegOrUnit, - LaneBitmask LaneMask) { + unsigned MONum, SlotIndex UseIdx, + const LiveRange &LR, + Register VRegOrUnit, + LaneBitmask LaneMask) { LiveQueryResult LRQ = LR.Query(UseIdx); // Check if we have a segment at the use, note however that we only need one // live subregister range, the others may be dead. @@ -1887,8 +2014,11 @@ void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO, } void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO, - unsigned MONum, SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit, - bool SubRangeCheck, LaneBitmask LaneMask) { + unsigned MONum, SlotIndex DefIdx, + const LiveRange &LR, + Register VRegOrUnit, + bool SubRangeCheck, + LaneBitmask LaneMask) { if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) { assert(VNI && "NULL valno is not allowed"); if (VNI->def != DefIdx) { @@ -1932,7 +2062,7 @@ void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO, void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { const MachineInstr *MI = MO->getParent(); - const unsigned Reg = MO->getReg(); + const Register Reg = MO->getReg(); // Both use and def operands can read a register. if (MO->readsReg()) { @@ -1950,8 +2080,9 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { if (LiveInts && !LiveInts->isNotInMIMap(*MI)) { SlotIndex UseIdx = LiveInts->getInstructionIndex(*MI); // Check the cached regunit intervals. - if (Register::isPhysicalRegister(Reg) && !isReserved(Reg)) { - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { + if (Reg.isPhysical() && !isReserved(Reg)) { + for (MCRegUnitIterator Units(Reg.asMCReg(), TRI); Units.isValid(); + ++Units) { if (MRI->isReservedRegUnit(*Units)) continue; if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) @@ -2097,9 +2228,9 @@ void MachineVerifier::visitMachineBundleAfter(const MachineInstr *MI) { // Kill any masked registers. while (!regMasks.empty()) { const uint32_t *Mask = regMasks.pop_back_val(); - for (unsigned Reg : regsLive) - if (Register::isPhysicalRegister(Reg) && - MachineOperand::clobbersPhysReg(Mask, Reg)) + for (Register Reg : regsLive) + if (Reg.isPhysical() && + MachineOperand::clobbersPhysReg(Mask, Reg.asMCReg())) regsDead.push_back(Reg); } set_subtract(regsLive, regsDead); regsDead.clear(); @@ -2132,7 +2263,7 @@ struct VRegFilter { // Add elements to the filter itself. \pre Input set \p FromRegSet must have // no duplicates. Both virtual and physical registers are fine. template <typename RegSetT> void add(const RegSetT &FromRegSet) { - SmallVector<unsigned, 0> VRegsBuffer; + SmallVector<Register, 0> VRegsBuffer; filterAndAdd(FromRegSet, VRegsBuffer); } // Filter \p FromRegSet through the filter and append passed elements into \p @@ -2140,13 +2271,13 @@ struct VRegFilter { // \returns true if anything changed. template <typename RegSetT> bool filterAndAdd(const RegSetT &FromRegSet, - SmallVectorImpl<unsigned> &ToVRegs) { + SmallVectorImpl<Register> &ToVRegs) { unsigned SparseUniverse = Sparse.size(); unsigned NewSparseUniverse = SparseUniverse; unsigned NewDenseSize = Dense.size(); size_t Begin = ToVRegs.size(); - for (unsigned Reg : FromRegSet) { - if (!Register::isVirtualRegister(Reg)) + for (Register Reg : FromRegSet) { + if (!Reg.isVirtual()) continue; unsigned Index = Register::virtReg2Index(Reg); if (Index < SparseUniverseMax) { @@ -2170,7 +2301,7 @@ struct VRegFilter { Sparse.resize(NewSparseUniverse); Dense.reserve(NewDenseSize); for (unsigned I = Begin; I < End; ++I) { - unsigned Reg = ToVRegs[I]; + Register Reg = ToVRegs[I]; unsigned Index = Register::virtReg2Index(Reg); if (Index < SparseUniverseMax) Sparse.set(Index); @@ -2203,7 +2334,7 @@ private: // universe). filter_b implicitly contains all physical registers at all times. class FilteringVRegSet { VRegFilter Filter; - SmallVector<unsigned, 0> VRegs; + SmallVector<Register, 0> VRegs; public: // Set-up the filter_b. \pre Input register set \p RS must have no duplicates. @@ -2229,63 +2360,28 @@ public: // can pass through an MBB live, but may not be live every time. It is assumed // that all vregsPassed sets are empty before the call. void MachineVerifier::calcRegsPassed() { - // This is a forward dataflow, doing it in RPO. A standard map serves as a - // priority (sorting by RPO number) queue, deduplicating worklist, and an RPO - // number to MBB mapping all at once. - std::map<unsigned, const MachineBasicBlock *> RPOWorklist; - DenseMap<const MachineBasicBlock *, unsigned> RPONumbers; - if (MF->empty()) { + if (MF->empty()) // ReversePostOrderTraversal doesn't handle empty functions. return; - } - std::vector<FilteringVRegSet> VRegsPassedSets(MF->size()); - for (const MachineBasicBlock *MBB : - ReversePostOrderTraversal<const MachineFunction *>(MF)) { - // Careful with the evaluation order, fetch next number before allocating. - unsigned Number = RPONumbers.size(); - RPONumbers[MBB] = Number; - // Set-up the transfer functions for all blocks. - const BBInfo &MInfo = MBBInfoMap[MBB]; - VRegsPassedSets[Number].addToFilter(MInfo.regsKilled); - VRegsPassedSets[Number].addToFilter(MInfo.regsLiveOut); - } - // First push live-out regs to successors' vregsPassed. Remember the MBBs that - // have any vregsPassed. - for (const MachineBasicBlock &MBB : *MF) { - const BBInfo &MInfo = MBBInfoMap[&MBB]; - if (!MInfo.reachable) - continue; - for (const MachineBasicBlock *Succ : MBB.successors()) { - unsigned SuccNumber = RPONumbers[Succ]; - FilteringVRegSet &SuccSet = VRegsPassedSets[SuccNumber]; - if (SuccSet.add(MInfo.regsLiveOut)) - RPOWorklist.emplace(SuccNumber, Succ); - } - } - // Iteratively push vregsPassed to successors. - while (!RPOWorklist.empty()) { - auto Next = RPOWorklist.begin(); - const MachineBasicBlock *MBB = Next->second; - RPOWorklist.erase(Next); - FilteringVRegSet &MSet = VRegsPassedSets[RPONumbers[MBB]]; - for (const MachineBasicBlock *Succ : MBB->successors()) { - if (Succ == MBB) + for (const MachineBasicBlock *MB : + ReversePostOrderTraversal<const MachineFunction *>(MF)) { + FilteringVRegSet VRegs; + BBInfo &Info = MBBInfoMap[MB]; + assert(Info.reachable); + + VRegs.addToFilter(Info.regsKilled); + VRegs.addToFilter(Info.regsLiveOut); + for (const MachineBasicBlock *Pred : MB->predecessors()) { + const BBInfo &PredInfo = MBBInfoMap[Pred]; + if (!PredInfo.reachable) continue; - unsigned SuccNumber = RPONumbers[Succ]; - FilteringVRegSet &SuccSet = VRegsPassedSets[SuccNumber]; - if (SuccSet.add(MSet)) - RPOWorklist.emplace(SuccNumber, Succ); + + VRegs.add(PredInfo.regsLiveOut); + VRegs.add(PredInfo.vregsPassed); } - } - // Copy the results back to BBInfos. - for (const MachineBasicBlock &MBB : *MF) { - BBInfo &MInfo = MBBInfoMap[&MBB]; - if (!MInfo.reachable) - continue; - const FilteringVRegSet &MSet = VRegsPassedSets[RPONumbers[&MBB]]; - MInfo.vregsPassed.reserve(MSet.size()); - MInfo.vregsPassed.insert(MSet.begin(), MSet.end()); + Info.vregsPassed.reserve(VRegs.size()); + Info.vregsPassed.insert(VRegs.begin(), VRegs.end()); } } @@ -2302,6 +2398,23 @@ void MachineVerifier::calcRegsRequired() { if (PInfo.addRequired(MInfo.vregsLiveIn)) todo.insert(Pred); } + + // Handle the PHI node. + for (const MachineInstr &MI : MBB.phis()) { + for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) { + // Skip those Operands which are undef regs or not regs. + if (!MI.getOperand(i).isReg() || !MI.getOperand(i).readsReg()) + continue; + + // Get register and predecessor for one PHI edge. + Register Reg = MI.getOperand(i).getReg(); + const MachineBasicBlock *Pred = MI.getOperand(i + 1).getMBB(); + + BBInfo &PInfo = MBBInfoMap[Pred]; + if (PInfo.addRequired(Reg)) + todo.insert(Pred); + } + } } // Iteratively push vregsRequired to predecessors. This will converge to the @@ -2399,7 +2512,7 @@ void MachineVerifier::visitMachineFunctionAfter() { // Check for killed virtual registers that should be live out. for (const auto &MBB : *MF) { BBInfo &MInfo = MBBInfoMap[&MBB]; - for (unsigned VReg : MInfo.vregsRequired) + for (Register VReg : MInfo.vregsRequired) if (MInfo.regsKilled.count(VReg)) { report("Virtual register killed in block, but needed live out.", &MBB); errs() << "Virtual register " << printReg(VReg) @@ -2409,7 +2522,7 @@ void MachineVerifier::visitMachineFunctionAfter() { if (!MF->empty()) { BBInfo &MInfo = MBBInfoMap[&MF->front()]; - for (unsigned VReg : MInfo.vregsRequired) { + for (Register VReg : MInfo.vregsRequired) { report("Virtual register defs don't dominate all uses.", MF); report_context_vreg(VReg); } @@ -2449,12 +2562,27 @@ void MachineVerifier::visitMachineFunctionAfter() { for (auto CSInfo : MF->getCallSitesInfo()) if (!CSInfo.first->isCall()) report("Call site info referencing instruction that is not call", MF); + + // If there's debug-info, check that we don't have any duplicate value + // tracking numbers. + if (MF->getFunction().getSubprogram()) { + DenseSet<unsigned> SeenNumbers; + for (auto &MBB : *MF) { + for (auto &MI : MBB) { + if (auto Num = MI.peekDebugInstrNum()) { + auto Result = SeenNumbers.insert((unsigned)Num); + if (!Result.second) + report("Instruction has a duplicated value tracking number", &MI); + } + } + } + } } void MachineVerifier::verifyLiveVariables() { assert(LiveVars && "Don't call verifyLiveVariables without LiveVars"); - for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { - unsigned Reg = Register::index2VirtReg(i); + for (unsigned I = 0, E = MRI->getNumVirtRegs(); I != E; ++I) { + Register Reg = Register::index2VirtReg(I); LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg); for (const auto &MBB : *MF) { BBInfo &MInfo = MBBInfoMap[&MBB]; @@ -2479,8 +2607,8 @@ void MachineVerifier::verifyLiveVariables() { void MachineVerifier::verifyLiveIntervals() { assert(LiveInts && "Don't call verifyLiveIntervals without LiveInts"); - for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { - unsigned Reg = Register::index2VirtReg(i); + for (unsigned I = 0, E = MRI->getNumVirtRegs(); I != E; ++I) { + Register Reg = Register::index2VirtReg(I); // Spilling and splitting may leave unused registers around. Skip them. if (MRI->reg_nodbg_empty(Reg)) @@ -2493,7 +2621,7 @@ void MachineVerifier::verifyLiveIntervals() { } const LiveInterval &LI = LiveInts->getInterval(Reg); - assert(Reg == LI.reg && "Invalid reg to interval mapping"); + assert(Reg == LI.reg() && "Invalid reg to interval mapping"); verifyLiveInterval(LI); } @@ -2504,7 +2632,7 @@ void MachineVerifier::verifyLiveIntervals() { } void MachineVerifier::verifyLiveRangeValue(const LiveRange &LR, - const VNInfo *VNI, unsigned Reg, + const VNInfo *VNI, Register Reg, LaneBitmask LaneMask) { if (VNI->isUnused()) return; @@ -2597,8 +2725,8 @@ void MachineVerifier::verifyLiveRangeValue(const LiveRange &LR, void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR, const LiveRange::const_iterator I, - unsigned Reg, LaneBitmask LaneMask) -{ + Register Reg, + LaneBitmask LaneMask) { const LiveRange::Segment &S = *I; const VNInfo *VNI = S.valno; assert(VNI && "Live segment has no valno"); @@ -2809,7 +2937,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR, } } -void MachineVerifier::verifyLiveRange(const LiveRange &LR, unsigned Reg, +void MachineVerifier::verifyLiveRange(const LiveRange &LR, Register Reg, LaneBitmask LaneMask) { for (const VNInfo *VNI : LR.valnos) verifyLiveRangeValue(LR, VNI, Reg, LaneMask); @@ -2819,7 +2947,7 @@ void MachineVerifier::verifyLiveRange(const LiveRange &LR, unsigned Reg, } void MachineVerifier::verifyLiveInterval(const LiveInterval &LI) { - unsigned Reg = LI.reg; + Register Reg = LI.reg(); assert(Register::isVirtualRegister(Reg)); verifyLiveRange(LI, Reg); @@ -2836,10 +2964,10 @@ void MachineVerifier::verifyLiveInterval(const LiveInterval &LI) { } if (SR.empty()) { report("Subrange must not be empty", MF); - report_context(SR, LI.reg, SR.LaneMask); + report_context(SR, LI.reg(), SR.LaneMask); } Mask |= SR.LaneMask; - verifyLiveRange(SR, LI.reg, SR.LaneMask); + verifyLiveRange(SR, LI.reg(), SR.LaneMask); if (!LI.covers(SR)) { report("A Subrange is not covered by the main range", MF); report_context(LI); |