diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp index 247258a1ff5533..b9cf36a07846c9 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -183,6 +183,7 @@ class TransferTracker { /// information from it. (XXX make it const?) MLocTracker *MTracker; MachineFunction &MF; + const DebugVariableMap &DVMap; bool ShouldEmitDebugEntryValues; /// Record of all changes in variable locations at a block position. Awkwardly @@ -191,7 +192,9 @@ class TransferTracker { struct Transfer { MachineBasicBlock::instr_iterator Pos; /// Position to insert DBG_VALUes MachineBasicBlock *MBB; /// non-null if we should insert after. - SmallVector Insts; /// Vector of DBG_VALUEs to insert. + /// Vector of DBG_VALUEs to insert. Store with their DebugVariableID so that + /// they can be sorted into a stable order for emission at a later time. + SmallVector, 4> Insts; }; /// Stores the resolved operands (machine locations and constants) and @@ -227,15 +230,15 @@ class TransferTracker { /// Map from LocIdxes to which DebugVariables are based that location. /// Mantained while stepping through the block. Not accurate if /// VarLocs[Idx] != MTracker->LocIdxToIDNum[Idx]. - DenseMap> ActiveMLocs; + DenseMap> ActiveMLocs; /// Map from DebugVariable to it's current location and qualifying meta /// information. To be used in conjunction with ActiveMLocs to construct /// enough information for the DBG_VALUEs for a particular LocIdx. - DenseMap ActiveVLocs; + DenseMap ActiveVLocs; /// Temporary cache of DBG_VALUEs to be entered into the Transfers collection. - SmallVector PendingDbgValues; + SmallVector, 4> PendingDbgValues; /// Record of a use-before-def: created when a value that's live-in to the /// current block isn't available in any machine location, but it will be @@ -244,12 +247,12 @@ class TransferTracker { /// Value of this variable, def'd in block. SmallVector Values; /// Identity of this variable. - DebugVariable Var; + DebugVariableID VarID; /// Additional variable properties. DbgValueProperties Properties; - UseBeforeDef(ArrayRef Values, const DebugVariable &Var, + UseBeforeDef(ArrayRef Values, DebugVariableID VarID, const DbgValueProperties &Properties) - : Values(Values.begin(), Values.end()), Var(Var), + : Values(Values.begin(), Values.end()), VarID(VarID), Properties(Properties) {} }; @@ -260,15 +263,16 @@ class TransferTracker { /// The set of variables that are in UseBeforeDefs and can become a location /// once the relevant value is defined. An element being erased from this /// collection prevents the use-before-def materializing. - DenseSet UseBeforeDefVariables; + DenseSet UseBeforeDefVariables; const TargetRegisterInfo &TRI; const BitVector &CalleeSavedRegs; TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, - MachineFunction &MF, const TargetRegisterInfo &TRI, + MachineFunction &MF, const DebugVariableMap &DVMap, + const TargetRegisterInfo &TRI, const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC) - : TII(TII), MTracker(MTracker), MF(MF), TRI(TRI), + : TII(TII), MTracker(MTracker), MF(MF), DVMap(DVMap), TRI(TRI), CalleeSavedRegs(CalleeSavedRegs) { TLI = MF.getSubtarget().getTargetLowering(); auto &TM = TPC.getTM(); @@ -352,7 +356,7 @@ class TransferTracker { /// determine the values used by Value. void loadVarInloc(MachineBasicBlock &MBB, DbgOpIDMap &DbgOpStore, const SmallVectorImpl &ValueToLoc, - DebugVariable Var, DbgValue Value) { + DebugVariableID VarID, DbgValue Value) { SmallVector DbgOps; SmallVector ResolvedDbgOps; bool IsValueValid = true; @@ -401,7 +405,7 @@ class TransferTracker { static_cast(Num.getInst())); continue; } - recoverAsEntryValue(Var, Value.Properties, Num); + recoverAsEntryValue(VarID, Value.Properties, Num); IsValueValid = false; break; } @@ -419,8 +423,7 @@ class TransferTracker { // Add UseBeforeDef entry for the last value to be defined in this block. if (LastUseBeforeDef) { - addUseBeforeDef(Var, Value.Properties, DbgOps, - LastUseBeforeDef); + addUseBeforeDef(VarID, Value.Properties, DbgOps, LastUseBeforeDef); return; } @@ -428,13 +431,15 @@ class TransferTracker { // the transfer. for (const ResolvedDbgOp &Op : ResolvedDbgOps) if (!Op.IsConst) - ActiveMLocs[Op.Loc].insert(Var); + ActiveMLocs[Op.Loc].insert(VarID); auto NewValue = ResolvedDbgValue{ResolvedDbgOps, Value.Properties}; - auto Result = ActiveVLocs.insert(std::make_pair(Var, NewValue)); + auto Result = ActiveVLocs.insert(std::make_pair(VarID, NewValue)); if (!Result.second) Result.first->second = NewValue; + auto &[Var, DILoc] = DVMap.lookupDVID(VarID); PendingDbgValues.push_back( - MTracker->emitLoc(ResolvedDbgOps, Var, Value.Properties)); + std::make_pair(VarID, &*MTracker->emitLoc(ResolvedDbgOps, Var, DILoc, + Value.Properties))); } /// Load object with live-in variable values. \p mlocs contains the live-in @@ -445,7 +450,7 @@ class TransferTracker { /// FIXME: could just examine mloctracker instead of passing in \p mlocs? void loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, - const SmallVectorImpl> &VLocs, + const SmallVectorImpl> &VLocs, unsigned NumLocs) { ActiveMLocs.clear(); ActiveVLocs.clear(); @@ -506,11 +511,11 @@ class TransferTracker { /// Record that \p Var has value \p ID, a value that becomes available /// later in the function. - void addUseBeforeDef(const DebugVariable &Var, + void addUseBeforeDef(DebugVariableID VarID, const DbgValueProperties &Properties, const SmallVectorImpl &DbgOps, unsigned Inst) { - UseBeforeDefs[Inst].emplace_back(DbgOps, Var, Properties); - UseBeforeDefVariables.insert(Var); + UseBeforeDefs[Inst].emplace_back(DbgOps, VarID, Properties); + UseBeforeDefVariables.insert(VarID); } /// After the instruction at index \p Inst and position \p pos has been @@ -529,7 +534,7 @@ class TransferTracker { // Populate ValueToLoc with illegal default mappings for every value used by // any UseBeforeDef variables for this instruction. for (auto &Use : MIt->second) { - if (!UseBeforeDefVariables.count(Use.Var)) + if (!UseBeforeDefVariables.count(Use.VarID)) continue; for (DbgOp &Op : Use.Values) { @@ -568,7 +573,7 @@ class TransferTracker { // Using the map of values to locations, produce a final set of values for // this variable. for (auto &Use : MIt->second) { - if (!UseBeforeDefVariables.count(Use.Var)) + if (!UseBeforeDefVariables.count(Use.VarID)) continue; SmallVector DbgOps; @@ -591,8 +596,9 @@ class TransferTracker { continue; // Otherwise, we're good to go. - PendingDbgValues.push_back( - MTracker->emitLoc(DbgOps, Use.Var, Use.Properties)); + auto &[Var, DILoc] = DVMap.lookupDVID(Use.VarID); + PendingDbgValues.push_back(std::make_pair( + Use.VarID, MTracker->emitLoc(DbgOps, Var, DILoc, Use.Properties))); } flushDbgValues(pos, nullptr); } @@ -642,7 +648,7 @@ class TransferTracker { return Reg != SP && Reg != FP; } - bool recoverAsEntryValue(const DebugVariable &Var, + bool recoverAsEntryValue(DebugVariableID VarID, const DbgValueProperties &Prop, const ValueIDNum &Num) { // Is this variable location a candidate to be an entry value. First, @@ -663,6 +669,8 @@ class TransferTracker { DIExpr = *NonVariadicExpression; } + auto &[Var, DILoc] = DVMap.lookupDVID(VarID); + // Is the variable appropriate for entry values (i.e., is a parameter). if (!isEntryValueVariable(Var, DIExpr)) return false; @@ -676,9 +684,8 @@ class TransferTracker { DIExpression::prepend(DIExpr, DIExpression::EntryValue); Register Reg = MTracker->LocIdxToLocID[Num.getLoc()]; MachineOperand MO = MachineOperand::CreateReg(Reg, false); - - PendingDbgValues.push_back( - emitMOLoc(MO, Var, {NewExpr, Prop.Indirect, false})); + PendingDbgValues.push_back(std::make_pair( + VarID, &*emitMOLoc(MO, Var, {NewExpr, Prop.Indirect, false}))); return true; } @@ -687,19 +694,20 @@ class TransferTracker { DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); DbgValueProperties Properties(MI); + DebugVariableID VarID = DVMap.getDVID(Var); // Ignore non-register locations, we don't transfer those. if (MI.isUndefDebugValue() || all_of(MI.debug_operands(), [](const MachineOperand &MO) { return !MO.isReg(); })) { - auto It = ActiveVLocs.find(Var); + auto It = ActiveVLocs.find(VarID); if (It != ActiveVLocs.end()) { for (LocIdx Loc : It->second.loc_indices()) - ActiveMLocs[Loc].erase(Var); + ActiveMLocs[Loc].erase(VarID); ActiveVLocs.erase(It); } // Any use-before-defs no longer apply. - UseBeforeDefVariables.erase(Var); + UseBeforeDefVariables.erase(VarID); return; } @@ -725,14 +733,15 @@ class TransferTracker { SmallVectorImpl &NewLocs) { DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); + DebugVariableID VarID = DVMap.getDVID(Var); // Any use-before-defs no longer apply. - UseBeforeDefVariables.erase(Var); + UseBeforeDefVariables.erase(VarID); // Erase any previous location. - auto It = ActiveVLocs.find(Var); + auto It = ActiveVLocs.find(VarID); if (It != ActiveVLocs.end()) { for (LocIdx Loc : It->second.loc_indices()) - ActiveMLocs[Loc].erase(Var); + ActiveMLocs[Loc].erase(VarID); } // If there _is_ no new location, all we had to do was erase. @@ -742,7 +751,7 @@ class TransferTracker { return; } - SmallVector> LostMLocs; + SmallVector> LostMLocs; for (ResolvedDbgOp &Op : NewLocs) { if (Op.IsConst) continue; @@ -769,17 +778,17 @@ class TransferTracker { for (const auto &LostMLoc : LostMLocs) ActiveMLocs[LostMLoc.first].erase(LostMLoc.second); LostMLocs.clear(); - It = ActiveVLocs.find(Var); + It = ActiveVLocs.find(VarID); ActiveMLocs[NewLoc.asU64()].clear(); VarLocs[NewLoc.asU64()] = MTracker->readMLoc(NewLoc); } - ActiveMLocs[NewLoc].insert(Var); + ActiveMLocs[NewLoc].insert(VarID); } if (It == ActiveVLocs.end()) { ActiveVLocs.insert( - std::make_pair(Var, ResolvedDbgValue(NewLocs, Properties))); + std::make_pair(VarID, ResolvedDbgValue(NewLocs, Properties))); } else { It->second.Ops.assign(NewLocs); It->second.Properties = Properties; @@ -822,21 +831,21 @@ class TransferTracker { // explicitly undef, then stop here. if (!NewLoc && !MakeUndef) { // Try and recover a few more locations with entry values. - for (const auto &Var : ActiveMLocIt->second) { - auto &Prop = ActiveVLocs.find(Var)->second.Properties; - recoverAsEntryValue(Var, Prop, OldValue); + for (DebugVariableID VarID : ActiveMLocIt->second) { + auto &Prop = ActiveVLocs.find(VarID)->second.Properties; + recoverAsEntryValue(VarID, Prop, OldValue); } flushDbgValues(Pos, nullptr); return; } // Examine all the variables based on this location. - DenseSet NewMLocs; + DenseSet NewMLocs; // If no new location has been found, every variable that depends on this // MLoc is dead, so end their existing MLoc->Var mappings as well. - SmallVector> LostMLocs; - for (const auto &Var : ActiveMLocIt->second) { - auto ActiveVLocIt = ActiveVLocs.find(Var); + SmallVector> LostMLocs; + for (DebugVariableID VarID : ActiveMLocIt->second) { + auto ActiveVLocIt = ActiveVLocs.find(VarID); // Re-state the variable location: if there's no replacement then NewLoc // is std::nullopt and a $noreg DBG_VALUE will be created. Otherwise, a // DBG_VALUE identifying the alternative location will be emitted. @@ -855,19 +864,21 @@ class TransferTracker { replace_copy(ActiveVLocIt->second.Ops, DbgOps.begin(), OldOp, NewOp); } - PendingDbgValues.push_back(MTracker->emitLoc(DbgOps, Var, Properties)); + auto &[Var, DILoc] = DVMap.lookupDVID(VarID); + PendingDbgValues.push_back(std::make_pair( + VarID, &*MTracker->emitLoc(DbgOps, Var, DILoc, Properties))); // Update machine locations <=> variable locations maps. Defer updating // ActiveMLocs to avoid invalidating the ActiveMLocIt iterator. if (!NewLoc) { for (LocIdx Loc : ActiveVLocIt->second.loc_indices()) { if (Loc != MLoc) - LostMLocs.emplace_back(Loc, Var); + LostMLocs.emplace_back(Loc, VarID); } ActiveVLocs.erase(ActiveVLocIt); } else { ActiveVLocIt->second.Ops = DbgOps; - NewMLocs.insert(Var); + NewMLocs.insert(VarID); } } @@ -891,8 +902,8 @@ class TransferTracker { // Commit ActiveMLoc changes. ActiveMLocIt->second.clear(); if (!NewMLocs.empty()) - for (auto &Var : NewMLocs) - ActiveMLocs[*NewLoc].insert(Var); + for (DebugVariableID VarID : NewMLocs) + ActiveMLocs[*NewLoc].insert(VarID); } /// Transfer variables based on \p Src to be based on \p Dst. This handles @@ -915,17 +926,18 @@ class TransferTracker { // For each variable based on Src; create a location at Dst. ResolvedDbgOp SrcOp(Src); ResolvedDbgOp DstOp(Dst); - for (const auto &Var : MovingVars) { - auto ActiveVLocIt = ActiveVLocs.find(Var); + for (DebugVariableID VarID : MovingVars) { + auto ActiveVLocIt = ActiveVLocs.find(VarID); assert(ActiveVLocIt != ActiveVLocs.end()); // Update all instances of Src in the variable's tracked values to Dst. std::replace(ActiveVLocIt->second.Ops.begin(), ActiveVLocIt->second.Ops.end(), SrcOp, DstOp); - MachineInstr *MI = MTracker->emitLoc(ActiveVLocIt->second.Ops, Var, + auto &[Var, DILoc] = DVMap.lookupDVID(VarID); + MachineInstr *MI = MTracker->emitLoc(ActiveVLocIt->second.Ops, Var, DILoc, ActiveVLocIt->second.Properties); - PendingDbgValues.push_back(MI); + PendingDbgValues.push_back(std::make_pair(VarID, MI)); } ActiveMLocs[Src].clear(); flushDbgValues(Pos, nullptr); @@ -1176,11 +1188,9 @@ LLVM_DUMP_METHOD void MLocTracker::dump_mloc_map() { MachineInstrBuilder MLocTracker::emitLoc(const SmallVectorImpl &DbgOps, - const DebugVariable &Var, + const DebugVariable &Var, const DILocation *DILoc, const DbgValueProperties &Properties) { - DebugLoc DL = DILocation::get(Var.getVariable()->getContext(), 0, 0, - Var.getVariable()->getScope(), - const_cast(Var.getInlinedAt())); + DebugLoc DL = DebugLoc(DILoc); const MCInstrDesc &Desc = Properties.IsVariadic ? TII.get(TargetOpcode::DBG_VALUE_LIST) @@ -1726,7 +1736,8 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI, LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.getInst()); } if (IsValidUseBeforeDef) { - TTracker->addUseBeforeDef(V, {MI.getDebugExpression(), false, true}, + DebugVariableID VID = DVMap.insertDVID(V, MI.getDebugLoc().get()); + TTracker->addUseBeforeDef(VID, {MI.getDebugExpression(), false, true}, DbgOps, LastUseBeforeDef); } } @@ -1735,9 +1746,11 @@ bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI, // This DBG_VALUE is potentially a $noreg / undefined location, if // FoundLoc is illegal. // (XXX -- could morph the DBG_INSTR_REF in the future). - MachineInstr *DbgMI = MTracker->emitLoc(NewLocs, V, Properties); + MachineInstr *DbgMI = + MTracker->emitLoc(NewLocs, V, MI.getDebugLoc().get(), Properties); + DebugVariableID ID = DVMap.getDVID(V); - TTracker->PendingDbgValues.push_back(DbgMI); + TTracker->PendingDbgValues.push_back(std::make_pair(ID, DbgMI)); TTracker->flushDbgValues(MI.getIterator(), nullptr); return true; } @@ -3112,7 +3125,8 @@ void InstrRefBasedLDV::getBlocksForScope( } void InstrRefBasedLDV::buildVLocValueMap( - const DILocation *DILoc, const SmallSet &VarsWeCareAbout, + const DILocation *DILoc, + const SmallSet &VarsWeCareAbout, SmallPtrSetImpl &AssignBlocks, LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs, SmallVectorImpl &AllTheVLocs) { @@ -3188,7 +3202,7 @@ void InstrRefBasedLDV::buildVLocValueMap( // between blocks. This keeps the locality of working on one lexical scope at // at time, but avoids re-processing variable values because some other // variable has been assigned. - for (const auto &Var : VarsWeCareAbout) { + for (DebugVariableID VarID : VarsWeCareAbout) { // Re-initialize live-ins and live-outs, to clear the remains of previous // variables live-ins / live-outs. for (unsigned int I = 0; I < NumBlocks; ++I) { @@ -3202,7 +3216,7 @@ void InstrRefBasedLDV::buildVLocValueMap( SmallPtrSet DefBlocks; for (const MachineBasicBlock *ExpMBB : BlocksToExplore) { auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars; - if (TransferFunc.contains(Var)) + if (TransferFunc.contains(VarID)) DefBlocks.insert(const_cast(ExpMBB)); } @@ -3212,7 +3226,7 @@ void InstrRefBasedLDV::buildVLocValueMap( // only one value definition, things are very simple. if (DefBlocks.size() == 1) { placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.begin(), - AllTheVLocs, Var, Output); + AllTheVLocs, VarID, Output); continue; } @@ -3285,7 +3299,7 @@ void InstrRefBasedLDV::buildVLocValueMap( // Do transfer function. auto &VTracker = AllTheVLocs[MBB->getNumber()]; - auto TransferIt = VTracker.Vars.find(Var); + auto TransferIt = VTracker.Vars.find(VarID); if (TransferIt != VTracker.Vars.end()) { // Erase on empty transfer (DBG_VALUE $noreg). if (TransferIt->second.Kind == DbgValue::Undef) { @@ -3347,9 +3361,11 @@ void InstrRefBasedLDV::buildVLocValueMap( continue; if (BlockLiveIn->Kind == DbgValue::VPHI) BlockLiveIn->Kind = DbgValue::Def; + auto &[Var, DILoc] = DVMap.lookupDVID(VarID); assert(BlockLiveIn->Properties.DIExpr->getFragmentInfo() == - Var.getFragment() && "Fragment info missing during value prop"); - Output[MBB->getNumber()].push_back(std::make_pair(Var, *BlockLiveIn)); + Var.getFragment() && + "Fragment info missing during value prop"); + Output[MBB->getNumber()].push_back(std::make_pair(VarID, *BlockLiveIn)); } } // Per-variable loop. @@ -3360,7 +3376,7 @@ void InstrRefBasedLDV::buildVLocValueMap( void InstrRefBasedLDV::placePHIsForSingleVarDefinition( const SmallPtrSetImpl &InScopeBlocks, MachineBasicBlock *AssignMBB, SmallVectorImpl &AllTheVLocs, - const DebugVariable &Var, LiveInsT &Output) { + DebugVariableID VarID, LiveInsT &Output) { // If there is a single definition of the variable, then working out it's // value everywhere is very simple: it's every block dominated by the // definition. At the dominance frontier, the usual algorithm would: @@ -3373,7 +3389,7 @@ void InstrRefBasedLDV::placePHIsForSingleVarDefinition( // Pick out the variables value from the block transfer function. VLocTracker &VLocs = AllTheVLocs[AssignMBB->getNumber()]; - auto ValueIt = VLocs.Vars.find(Var); + auto ValueIt = VLocs.Vars.find(VarID); const DbgValue &Value = ValueIt->second; // If it's an explicit assignment of "undef", that means there is no location @@ -3388,7 +3404,7 @@ void InstrRefBasedLDV::placePHIsForSingleVarDefinition( if (!DomTree->properlyDominates(AssignMBB, ScopeBlock)) continue; - Output[ScopeBlock->getNumber()].push_back({Var, Value}); + Output[ScopeBlock->getNumber()].push_back({VarID, Value}); } // All blocks that aren't dominated have no live-in value, thus no variable @@ -3515,9 +3531,9 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit( const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks, LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs, SmallVectorImpl &AllTheVLocs, MachineFunction &MF, - DenseMap &AllVarsNumbering, const TargetPassConfig &TPC) { - TTracker = new TransferTracker(TII, MTracker, MF, *TRI, CalleeSavedRegs, TPC); + TTracker = + new TransferTracker(TII, MTracker, MF, DVMap, *TRI, CalleeSavedRegs, TPC); unsigned NumLocs = MTracker->getNumLocs(); VTracker = nullptr; @@ -3622,31 +3638,24 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit( if (MInLocs.hasTableFor(*MBB)) EjectBlock(*MBB); - return emitTransfers(AllVarsNumbering); + return emitTransfers(); } -bool InstrRefBasedLDV::emitTransfers( - DenseMap &AllVarsNumbering) { +bool InstrRefBasedLDV::emitTransfers() { // Go through all the transfers recorded in the TransferTracker -- this is // both the live-ins to a block, and any movements of values that happen // in the middle. - for (const auto &P : TTracker->Transfers) { + for (auto &P : TTracker->Transfers) { // We have to insert DBG_VALUEs in a consistent order, otherwise they // appear in DWARF in different orders. Use the order that they appear // when walking through each block / each instruction, stored in - // AllVarsNumbering. - SmallVector> Insts; - for (MachineInstr *MI : P.Insts) { - DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(), - MI->getDebugLoc()->getInlinedAt()); - Insts.emplace_back(AllVarsNumbering.find(Var)->second, MI); - } - llvm::sort(Insts, llvm::less_first()); + // DVMap. + llvm::sort(P.Insts, llvm::less_first()); // Insert either before or after the designated point... if (P.MBB) { MachineBasicBlock &MBB = *P.MBB; - for (const auto &Pair : Insts) + for (const auto &Pair : P.Insts) MBB.insert(P.Pos, Pair.second); } else { // Terminators, like tail calls, can clobber things. Don't try and place @@ -3655,7 +3664,7 @@ bool InstrRefBasedLDV::emitTransfers( continue; MachineBasicBlock &MBB = *P.Pos->getParent(); - for (const auto &Pair : Insts) + for (const auto &Pair : P.Insts) MBB.insertAfterBundle(P.Pos, Pair.second); } } @@ -3710,7 +3719,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, initialSetup(MF); MLocTransfer.resize(MaxNumBlocks); - vlocs.resize(MaxNumBlocks, VLocTracker(OverlapFragments, EmptyExpr)); + vlocs.resize(MaxNumBlocks, VLocTracker(DVMap, OverlapFragments, EmptyExpr)); SavedLiveIns.resize(MaxNumBlocks); produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks); @@ -3766,10 +3775,6 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, MTracker->reset(); } - // Number all variables in the order that they appear, to be used as a stable - // insertion order later. - DenseMap AllVarsNumbering; - // Map from one LexicalScope to all the variables in that scope. ScopeToVarsT ScopeToVars; @@ -3788,16 +3793,15 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, auto *VTracker = &vlocs[MBB->getNumber()]; // Collect each variable with a DBG_VALUE in this block. for (auto &idx : VTracker->Vars) { - const auto &Var = idx.first; - const DILocation *ScopeLoc = VTracker->Scopes[Var]; + DebugVariableID VarID = idx.first; + const DILocation *ScopeLoc = VTracker->Scopes[VarID]; assert(ScopeLoc != nullptr); auto *Scope = LS.findLexicalScope(ScopeLoc); // No insts in scope -> shouldn't have been recorded. assert(Scope != nullptr); - AllVarsNumbering.insert(std::make_pair(Var, AllVarsNumbering.size())); - ScopeToVars[Scope].insert(Var); + ScopeToVars[Scope].insert(VarID); ScopeToAssignBlocks[Scope].insert(VTracker->MBB); ScopeToDILocation[Scope] = ScopeLoc; ++VarAssignCount; @@ -3821,7 +3825,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, // the "else" block of this condition. Changed = depthFirstVLocAndEmit( MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks, - SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, AllVarsNumbering, *TPC); + SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, *TPC); } delete MTracker; @@ -3840,6 +3844,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, SeenFragments.clear(); SeenDbgPHIs.clear(); DbgOpStore.clear(); + DVMap.clear(); return Changed; } diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h index 8770983481c2ff..8c03e38eee0620 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -35,6 +35,44 @@ class DbgOpIDMap; using namespace llvm; +using DebugVariableID = unsigned; +using VarAndLoc = std::pair; + +/// Mapping from DebugVariable to/from a unique identifying number. Each +/// DebugVariable consists of three pointers, and after a small amount of +/// work to identify overlapping fragments of variables we mostly only use +/// DebugVariables as identities of variables. It's much more compile-time +/// efficient to use an ID number instead, which this class provides. +class DebugVariableMap { + DenseMap VarToIdx; + SmallVector IdxToVar; + +public: + DebugVariableID getDVID(const DebugVariable &Var) const { + auto It = VarToIdx.find(Var); + assert(It != VarToIdx.end()); + return It->second; + } + + DebugVariableID insertDVID(DebugVariable &Var, const DILocation *Loc) { + unsigned Size = VarToIdx.size(); + auto ItPair = VarToIdx.insert({Var, Size}); + if (ItPair.second) { + IdxToVar.push_back({Var, Loc}); + return Size; + } + + return ItPair.first->second; + } + + const VarAndLoc &lookupDVID(DebugVariableID ID) const { return IdxToVar[ID]; } + + void clear() { + VarToIdx.clear(); + IdxToVar.clear(); + } +}; + /// Handle-class for a particular "location". This value-type uniquely /// symbolises a register or stack location, allowing manipulation of locations /// without concern for where that location is. Practically, this allows us to @@ -985,7 +1023,7 @@ class MLocTracker { /// information in \pProperties, for variable Var. Don't insert it anywhere, /// just return the builder for it. MachineInstrBuilder emitLoc(const SmallVectorImpl &DbgOps, - const DebugVariable &Var, + const DebugVariable &Var, const DILocation *DILoc, const DbgValueProperties &Properties); }; @@ -1003,38 +1041,45 @@ using OverlapMap = /// identified. class VLocTracker { public: + /// Ref to function-wide map of DebugVariable <=> ID-numbers. + DebugVariableMap &DVMap; /// Map DebugVariable to the latest Value it's defined to have. /// Needs to be a MapVector because we determine order-in-the-input-MIR from - /// the order in this container. + /// the order in this container. (FIXME: likely no longer true as the ordering + /// is now provided by DebugVariableMap). /// We only retain the last DbgValue in each block for each variable, to /// determine the blocks live-out variable value. The Vars container forms the /// transfer function for this block, as part of the dataflow analysis. The /// movement of values between locations inside of a block is handled at a /// much later stage, in the TransferTracker class. - MapVector Vars; - SmallDenseMap Scopes; + MapVector Vars; + SmallDenseMap Scopes; MachineBasicBlock *MBB = nullptr; const OverlapMap &OverlappingFragments; DbgValueProperties EmptyProperties; public: - VLocTracker(const OverlapMap &O, const DIExpression *EmptyExpr) - : OverlappingFragments(O), EmptyProperties(EmptyExpr, false, false) {} + VLocTracker(DebugVariableMap &DVMap, const OverlapMap &O, + const DIExpression *EmptyExpr) + : DVMap(DVMap), OverlappingFragments(O), + EmptyProperties(EmptyExpr, false, false) {} void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, const SmallVectorImpl &DebugOps) { assert(MI.isDebugValueLike()); DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); + // Either insert or fetch an ID number for this variable. + DebugVariableID VarID = DVMap.insertDVID(Var, MI.getDebugLoc().get()); DbgValue Rec = (DebugOps.size() > 0) ? DbgValue(DebugOps, Properties) : DbgValue(Properties, DbgValue::Undef); // Attempt insertion; overwrite if it's already mapped. - auto Result = Vars.insert(std::make_pair(Var, Rec)); + auto Result = Vars.insert(std::make_pair(VarID, Rec)); if (!Result.second) Result.first->second = Rec; - Scopes[Var] = MI.getDebugLoc().get(); + Scopes[VarID] = MI.getDebugLoc().get(); considerOverlaps(Var, MI.getDebugLoc().get()); } @@ -1056,13 +1101,15 @@ class VLocTracker { DebugVariable Overlapped(Var.getVariable(), OptFragmentInfo, Var.getInlinedAt()); + // Produce an ID number for this overlapping fragment of a variable. + DebugVariableID OverlappedID = DVMap.insertDVID(Overlapped, Loc); DbgValue Rec = DbgValue(EmptyProperties, DbgValue::Undef); // Attempt insertion; overwrite if it's already mapped. - auto Result = Vars.insert(std::make_pair(Overlapped, Rec)); + auto Result = Vars.insert(std::make_pair(OverlappedID, Rec)); if (!Result.second) Result.first->second = Rec; - Scopes[Overlapped] = Loc; + Scopes[OverlappedID] = Loc; } } @@ -1093,7 +1140,7 @@ class InstrRefBasedLDV : public LDVImpl { /// variables to their values. using LiveIdxT = DenseMap; - using VarAndLoc = std::pair; + using VarAndLoc = std::pair; /// Type for a live-in value: the predecessor block, and its value. using InValueT = std::pair; @@ -1106,7 +1153,8 @@ class InstrRefBasedLDV : public LDVImpl { using ScopeToDILocT = DenseMap; /// Mapping from lexical scopes to variables in that scope. - using ScopeToVarsT = DenseMap>; + using ScopeToVarsT = + DenseMap>; /// Mapping from lexical scopes to blocks where variables in that scope are /// assigned. Such blocks aren't necessarily "in" the lexical scope, it's @@ -1200,6 +1248,11 @@ class InstrRefBasedLDV : public LDVImpl { DbgOpIDMap DbgOpStore; + /// Mapping between DebugVariables and unique ID numbers. This is a more + /// efficient way to represent the identity of a variable, versus a plain + /// DebugVariable. + DebugVariableMap DVMap; + /// True if we need to examine call instructions for stack clobbers. We /// normally assume that they don't clobber SP, but stack probes on Windows /// do. @@ -1330,9 +1383,9 @@ class InstrRefBasedLDV : public LDVImpl { /// performance as it doesn't have to find the dominance frontier between /// different assignments. void placePHIsForSingleVarDefinition( - const SmallPtrSetImpl &InScopeBlocks, - MachineBasicBlock *MBB, SmallVectorImpl &AllTheVLocs, - const DebugVariable &Var, LiveInsT &Output); + const SmallPtrSetImpl &InScopeBlocks, + MachineBasicBlock *MBB, SmallVectorImpl &AllTheVLocs, + DebugVariableID Var, LiveInsT &Output); /// Calculate the iterated-dominance-frontier for a set of defs, using the /// existing LLVM facilities for this. Works for a single "value" or @@ -1381,7 +1434,7 @@ class InstrRefBasedLDV : public LDVImpl { /// scope, but which do contain DBG_VALUEs, which VarLocBasedImpl tracks /// locations through. void buildVLocValueMap(const DILocation *DILoc, - const SmallSet &VarsWeCareAbout, + const SmallSet &VarsWeCareAbout, SmallPtrSetImpl &AssignBlocks, LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs, @@ -1414,10 +1467,8 @@ class InstrRefBasedLDV : public LDVImpl { const SmallVectorImpl &BlockOrders); /// Take collections of DBG_VALUE instructions stored in TTracker, and - /// install them into their output blocks. Preserves a stable order of - /// DBG_VALUEs produced (which would otherwise cause nondeterminism) through - /// the AllVarsNumbering order. - bool emitTransfers(DenseMap &AllVarsNumbering); + /// install them into their output blocks. + bool emitTransfers(); /// Boilerplate computation of some initial sets, artifical blocks and /// RPOT block ordering. @@ -1437,13 +1488,14 @@ class InstrRefBasedLDV : public LDVImpl { /// block information can be fully computed before exploration finishes, /// allowing us to emit it and free data structures earlier than otherwise. /// It's also good for locality. - bool depthFirstVLocAndEmit( - unsigned MaxNumBlocks, const ScopeToDILocT &ScopeToDILocation, - const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToBlocks, - LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs, - SmallVectorImpl &AllTheVLocs, MachineFunction &MF, - DenseMap &AllVarsNumbering, - const TargetPassConfig &TPC); + bool depthFirstVLocAndEmit(unsigned MaxNumBlocks, + const ScopeToDILocT &ScopeToDILocation, + const ScopeToVarsT &ScopeToVars, + ScopeToAssignBlocksT &ScopeToBlocks, + LiveInsT &Output, FuncValueTable &MOutLocs, + FuncValueTable &MInLocs, + SmallVectorImpl &AllTheVLocs, + MachineFunction &MF, const TargetPassConfig &TPC); bool ExtendRanges(MachineFunction &MF, MachineDominatorTree *DomTree, TargetPassConfig *TPC, unsigned InputBBLimit, diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir index b54c748ac9e849..67bfd85dcb3793 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir @@ -17,12 +17,12 @@ # CHECK-LABEL: bb.3.bb3: # CHECK: DBG_VALUE $ecx, $noreg, !{{[0-9]+}}, # CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 0, 32) -# CHECK-NEXT: DBG_VALUE_LIST !{{[0-9]+}}, +# CHECK-NEXT: DBG_VALUE_LIST !{{[0-9]+}}, # CHECK-SAME: !DIExpression({{[^)]+}}, DW_OP_LLVM_fragment, 0, 32) # CHECK-SAME: $ecx, $r8d # CHECK-NEXT: DBG_VALUE $ebx, $noreg, !{{[0-9]+}}, # CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 32, 32) -# CHECK-NEXT: DBG_VALUE_LIST !{{[0-9]+}}, +# CHECK-NEXT: DBG_VALUE_LIST !{{[0-9]+}}, # CHECK-SAME: !DIExpression({{[^)]+}}, DW_OP_LLVM_fragment, 32, 32) # CHECK-SAME: $ebx, $r10d # CHECK-NEXT: XOR32rr diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp index 306a97c3149cc4..50a8cb97ae0619 100644 --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -55,6 +55,7 @@ class InstrRefLDVTest : public testing::Test { DIBasicType *LongInt; DIExpression *EmptyExpr; LiveDebugValues::OverlapMap Overlaps; + LiveDebugValues::DebugVariableMap DVMap; DebugLoc OutermostLoc, InBlockLoc, NotNestedBlockLoc, InlinedLoc; @@ -176,7 +177,7 @@ class InstrRefLDVTest : public testing::Test { void addVTracker() { ASSERT_TRUE(LDV); - VTracker = std::make_unique(Overlaps, EmptyExpr); + VTracker = std::make_unique(DVMap, Overlaps, EmptyExpr); LDV->VTracker = &*VTracker; }