diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp | 802 |
1 files changed, 514 insertions, 288 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp index eb372655e5f1..f8ce8f98864e 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/IntrinsicInst.h" @@ -81,6 +82,19 @@ template <> struct llvm::DenseMapInfo<VariableID> { } }; +using VarLocInsertPt = PointerUnion<const Instruction *, const DPValue *>; + +namespace std { +template <> struct hash<VarLocInsertPt> { + using argument_type = VarLocInsertPt; + using result_type = std::size_t; + + result_type operator()(const argument_type &Arg) const { + return std::hash<void *>()(Arg.getOpaqueValue()); + } +}; +} // namespace std + /// Helper class to build FunctionVarLocs, since that class isn't easy to /// modify. TODO: There's not a great deal of value in the split, it could be /// worth merging the two classes. @@ -89,8 +103,7 @@ class FunctionVarLocsBuilder { UniqueVector<DebugVariable> Variables; // Use an unordered_map so we don't invalidate iterators after // insert/modifications. - std::unordered_map<const Instruction *, SmallVector<VarLocInfo>> - VarLocsBeforeInst; + std::unordered_map<VarLocInsertPt, SmallVector<VarLocInfo>> VarLocsBeforeInst; SmallVector<VarLocInfo> SingleLocVars; @@ -109,7 +122,7 @@ public: /// Return ptr to wedge of defs or nullptr if no defs come just before /p /// Before. - const SmallVectorImpl<VarLocInfo> *getWedge(const Instruction *Before) const { + const SmallVectorImpl<VarLocInfo> *getWedge(VarLocInsertPt Before) const { auto R = VarLocsBeforeInst.find(Before); if (R == VarLocsBeforeInst.end()) return nullptr; @@ -117,7 +130,7 @@ public: } /// Replace the defs that come just before /p Before with /p Wedge. - void setWedge(const Instruction *Before, SmallVector<VarLocInfo> &&Wedge) { + void setWedge(VarLocInsertPt Before, SmallVector<VarLocInfo> &&Wedge) { VarLocsBeforeInst[Before] = std::move(Wedge); } @@ -133,7 +146,7 @@ public: } /// Add a def to the wedge of defs just before /p Before. - void addVarLoc(Instruction *Before, DebugVariable Var, DIExpression *Expr, + void addVarLoc(VarLocInsertPt Before, DebugVariable Var, DIExpression *Expr, DebugLoc DL, RawLocationWrapper R) { VarLocInfo VarLoc; VarLoc.VariableID = insertVariable(Var); @@ -201,15 +214,31 @@ void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) { SingleVarLocEnd = VarLocRecords.size(); // Insert a contiguous block of VarLocInfos for each instruction, mapping it - // to the start and end position in the vector with VarLocsBeforeInst. + // to the start and end position in the vector with VarLocsBeforeInst. This + // block includes VarLocs for any DPValues attached to that instruction. for (auto &P : Builder.VarLocsBeforeInst) { + // Process VarLocs attached to a DPValue alongside their marker Instruction. + if (isa<const DPValue *>(P.first)) + continue; + const Instruction *I = cast<const Instruction *>(P.first); unsigned BlockStart = VarLocRecords.size(); + // Any VarLocInfos attached to a DPValue should now be remapped to their + // marker Instruction, in order of DPValue appearance and prior to any + // VarLocInfos attached directly to that instruction. + for (const DPValue &DPV : I->getDbgValueRange()) { + // Even though DPV defines a variable location, VarLocsBeforeInst can + // still be empty if that VarLoc was redundant. + if (!Builder.VarLocsBeforeInst.count(&DPV)) + continue; + for (const VarLocInfo &VarLoc : Builder.VarLocsBeforeInst[&DPV]) + VarLocRecords.emplace_back(VarLoc); + } for (const VarLocInfo &VarLoc : P.second) VarLocRecords.emplace_back(VarLoc); unsigned BlockEnd = VarLocRecords.size(); // Record the start and end indices. if (BlockEnd != BlockStart) - VarLocsBeforeInst[P.first] = {BlockStart, BlockEnd}; + VarLocsBeforeInst[I] = {BlockStart, BlockEnd}; } // Copy the Variables vector from the builder's UniqueVector. @@ -370,7 +399,7 @@ class MemLocFragmentFill { unsigned SizeInBits; DebugLoc DL; }; - using InsertMap = MapVector<Instruction *, SmallVector<FragMemLoc>>; + using InsertMap = MapVector<VarLocInsertPt, SmallVector<FragMemLoc>>; /// BBInsertBeforeMap holds a description for the set of location defs to be /// inserted after the analysis is complete. It is updated during the dataflow @@ -590,7 +619,7 @@ class MemLocFragmentFill { return /*Changed=*/false; } - void insertMemLoc(BasicBlock &BB, Instruction &Before, unsigned Var, + void insertMemLoc(BasicBlock &BB, VarLocInsertPt Before, unsigned Var, unsigned StartBit, unsigned EndBit, unsigned Base, DebugLoc DL) { assert(StartBit < EndBit && "Cannot create fragment of size <= 0"); @@ -603,7 +632,7 @@ class MemLocFragmentFill { assert(Base && "Expected a non-zero ID for Base address"); Loc.Base = Base; Loc.DL = DL; - BBInsertBeforeMap[&BB][&Before].push_back(Loc); + BBInsertBeforeMap[&BB][Before].push_back(Loc); LLVM_DEBUG(dbgs() << "Add mem def for " << Aggregates[Var].first->getName() << " bits [" << StartBit << ", " << EndBit << ")\n"); } @@ -612,7 +641,7 @@ class MemLocFragmentFill { /// in \p FragMap starts before \p StartBit or ends after \p EndBit (which /// indicates - assuming StartBit->EndBit has just been inserted - that the /// slice has been coalesced in the map). - void coalesceFragments(BasicBlock &BB, Instruction &Before, unsigned Var, + void coalesceFragments(BasicBlock &BB, VarLocInsertPt Before, unsigned Var, unsigned StartBit, unsigned EndBit, unsigned Base, DebugLoc DL, const FragsInMemMap &FragMap) { if (!CoalesceAdjacentFragments) @@ -633,7 +662,7 @@ class MemLocFragmentFill { Base, DL); } - void addDef(const VarLocInfo &VarLoc, Instruction &Before, BasicBlock &BB, + void addDef(const VarLocInfo &VarLoc, VarLocInsertPt Before, BasicBlock &BB, VarFragMap &LiveSet) { DebugVariable DbgVar = FnVarLocs->getVariable(VarLoc.VariableID); if (skipVariable(DbgVar.getVariable())) @@ -800,9 +829,16 @@ class MemLocFragmentFill { void process(BasicBlock &BB, VarFragMap &LiveSet) { BBInsertBeforeMap[&BB].clear(); for (auto &I : BB) { + for (auto &DPV : I.getDbgValueRange()) { + if (const auto *Locs = FnVarLocs->getWedge(&DPV)) { + for (const VarLocInfo &Loc : *Locs) { + addDef(Loc, &DPV, *I.getParent(), LiveSet); + } + } + } if (const auto *Locs = FnVarLocs->getWedge(&I)) { for (const VarLocInfo &Loc : *Locs) { - addDef(Loc, I, *I.getParent(), LiveSet); + addDef(Loc, &I, *I.getParent(), LiveSet); } } } @@ -923,7 +959,7 @@ public: for (auto &Pair : BBInsertBeforeMap) { InsertMap &Map = Pair.second; for (auto &Pair : Map) { - Instruction *InsertBefore = Pair.first; + auto InsertBefore = Pair.first; assert(InsertBefore && "should never be null"); auto FragMemLocs = Pair.second; auto &Ctx = Fn.getContext(); @@ -990,13 +1026,14 @@ public: /// i.e. for all values x and y where x != y: /// join(x, x) = x /// join(x, y) = NoneOrPhi + using AssignRecord = PointerUnion<DbgAssignIntrinsic *, DPValue *>; struct Assignment { enum S { Known, NoneOrPhi } Status; /// ID of the assignment. nullptr if Status is not Known. DIAssignID *ID; /// The dbg.assign that marks this dbg-def. Mem-defs don't use this field. /// May be nullptr. - DbgAssignIntrinsic *Source; + AssignRecord Source; bool isSameSourceAssignment(const Assignment &Other) const { // Don't include Source in the equality check. Assignments are @@ -1011,31 +1048,51 @@ public: else OS << "null"; OS << ", s="; - if (Source) - OS << *Source; - else + if (Source.isNull()) OS << "null"; + else if (isa<DbgAssignIntrinsic *>(Source)) + OS << Source.get<DbgAssignIntrinsic *>(); + else + OS << Source.get<DPValue *>(); OS << ")"; } static Assignment make(DIAssignID *ID, DbgAssignIntrinsic *Source) { return Assignment(Known, ID, Source); } - static Assignment makeFromMemDef(DIAssignID *ID) { - return Assignment(Known, ID, nullptr); + static Assignment make(DIAssignID *ID, DPValue *Source) { + assert(Source->isDbgAssign() && + "Cannot make an assignment from a non-assign DPValue"); + return Assignment(Known, ID, Source); } - static Assignment makeNoneOrPhi() { - return Assignment(NoneOrPhi, nullptr, nullptr); + static Assignment make(DIAssignID *ID, AssignRecord Source) { + return Assignment(Known, ID, Source); + } + static Assignment makeFromMemDef(DIAssignID *ID) { + return Assignment(Known, ID); } + static Assignment makeNoneOrPhi() { return Assignment(NoneOrPhi, nullptr); } // Again, need a Top value? - Assignment() - : Status(NoneOrPhi), ID(nullptr), Source(nullptr) { - } // Can we delete this? + Assignment() : Status(NoneOrPhi), ID(nullptr) {} // Can we delete this? + Assignment(S Status, DIAssignID *ID) : Status(Status), ID(ID) { + // If the Status is Known then we expect there to be an assignment ID. + assert(Status == NoneOrPhi || ID); + } Assignment(S Status, DIAssignID *ID, DbgAssignIntrinsic *Source) : Status(Status), ID(ID), Source(Source) { // If the Status is Known then we expect there to be an assignment ID. assert(Status == NoneOrPhi || ID); } + Assignment(S Status, DIAssignID *ID, DPValue *Source) + : Status(Status), ID(ID), Source(Source) { + // If the Status is Known then we expect there to be an assignment ID. + assert(Status == NoneOrPhi || ID); + } + Assignment(S Status, DIAssignID *ID, AssignRecord Source) + : Status(Status), ID(ID), Source(Source) { + // If the Status is Known then we expect there to be an assignment ID. + assert(Status == NoneOrPhi || ID); + } }; using AssignmentMap = SmallVector<Assignment>; @@ -1056,13 +1113,22 @@ private: UntaggedStoreAssignmentMap UntaggedStoreVars; // Machinery to defer inserting dbg.values. - using InsertMap = MapVector<Instruction *, SmallVector<VarLocInfo>>; - InsertMap InsertBeforeMap; + using InstInsertMap = MapVector<VarLocInsertPt, SmallVector<VarLocInfo>>; + InstInsertMap InsertBeforeMap; /// Clear the location definitions currently cached for insertion after /p /// After. void resetInsertionPoint(Instruction &After); - void emitDbgValue(LocKind Kind, const DbgVariableIntrinsic *Source, - Instruction *After); + void resetInsertionPoint(DPValue &After); + + // emitDbgValue can be called with: + // Source=[AssignRecord|DbgValueInst*|DbgAssignIntrinsic*|DPValue*] + // Since AssignRecord can be cast to one of the latter two types, and all + // other types have a shared interface, we use a template to handle the latter + // three types, and an explicit overload for AssignRecord that forwards to + // the template version with the right type. + void emitDbgValue(LocKind Kind, AssignRecord Source, VarLocInsertPt After); + template <typename T> + void emitDbgValue(LocKind Kind, const T Source, VarLocInsertPt After); static bool mapsAreEqual(const BitVector &Mask, const AssignmentMap &A, const AssignmentMap &B) { @@ -1287,8 +1353,10 @@ private: /// Update \p LiveSet after encountering an instruciton without a DIAssignID /// attachment, \p I. void processUntaggedInstruction(Instruction &I, BlockInfo *LiveSet); - void processDbgAssign(DbgAssignIntrinsic &DAI, BlockInfo *LiveSet); - void processDbgValue(DbgValueInst &DVI, BlockInfo *LiveSet); + void processDbgAssign(AssignRecord Assign, BlockInfo *LiveSet); + void processDPValue(DPValue &DPV, BlockInfo *LiveSet); + void processDbgValue(PointerUnion<DbgValueInst *, DPValue *> DbgValueRecord, + BlockInfo *LiveSet); /// Add an assignment to memory for the variable /p Var. void addMemDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV); /// Add an assignment to the variable /p Var. @@ -1388,6 +1456,12 @@ static DIAssignID *getIDFromMarker(const DbgAssignIntrinsic &DAI) { return cast<DIAssignID>(DAI.getAssignID()); } +static DIAssignID *getIDFromMarker(const DPValue &DPV) { + assert(DPV.isDbgAssign() && + "Cannot get a DIAssignID from a non-assign DPValue!"); + return DPV.getAssignID(); +} + /// Return true if \p Var has an assignment in \p M matching \p AV. bool AssignmentTrackingLowering::hasVarWithAssignment( BlockInfo *LiveSet, BlockInfo::AssignmentKind Kind, VariableID Var, @@ -1418,9 +1492,46 @@ const char *locStr(AssignmentTrackingLowering::LocKind Loc) { } #endif +VarLocInsertPt getNextNode(const DPValue *DPV) { + auto NextIt = ++(DPV->getIterator()); + if (NextIt == DPV->getMarker()->getDbgValueRange().end()) + return DPV->getMarker()->MarkedInstr; + return &*NextIt; +} +VarLocInsertPt getNextNode(const Instruction *Inst) { + const Instruction *Next = Inst->getNextNode(); + if (!Next->hasDbgValues()) + return Next; + return &*Next->getDbgValueRange().begin(); +} +VarLocInsertPt getNextNode(VarLocInsertPt InsertPt) { + if (isa<const Instruction *>(InsertPt)) + return getNextNode(cast<const Instruction *>(InsertPt)); + return getNextNode(cast<const DPValue *>(InsertPt)); +} + +DbgAssignIntrinsic *CastToDbgAssign(DbgVariableIntrinsic *DVI) { + return cast<DbgAssignIntrinsic>(DVI); +} + +DPValue *CastToDbgAssign(DPValue *DPV) { + assert(DPV->isDbgAssign() && + "Attempted to cast non-assign DPValue to DPVAssign."); + return DPV; +} + void AssignmentTrackingLowering::emitDbgValue( AssignmentTrackingLowering::LocKind Kind, - const DbgVariableIntrinsic *Source, Instruction *After) { + AssignmentTrackingLowering::AssignRecord Source, VarLocInsertPt After) { + if (isa<DbgAssignIntrinsic *>(Source)) + emitDbgValue(Kind, cast<DbgAssignIntrinsic *>(Source), After); + else + emitDbgValue(Kind, cast<DPValue *>(Source), After); +} +template <typename T> +void AssignmentTrackingLowering::emitDbgValue( + AssignmentTrackingLowering::LocKind Kind, const T Source, + VarLocInsertPt After) { DILocation *DL = Source->getDebugLoc(); auto Emit = [this, Source, After, DL](Metadata *Val, DIExpression *Expr) { @@ -1430,7 +1541,7 @@ void AssignmentTrackingLowering::emitDbgValue( PoisonValue::get(Type::getInt1Ty(Source->getContext()))); // Find a suitable insert point. - Instruction *InsertBefore = After->getNextNode(); + auto InsertBefore = getNextNode(After); assert(InsertBefore && "Shouldn't be inserting after a terminator"); VariableID Var = getVariableID(DebugVariable(Source)); @@ -1445,15 +1556,15 @@ void AssignmentTrackingLowering::emitDbgValue( // NOTE: This block can mutate Kind. if (Kind == LocKind::Mem) { - const auto *DAI = cast<DbgAssignIntrinsic>(Source); + const auto *Assign = CastToDbgAssign(Source); // Check the address hasn't been dropped (e.g. the debug uses may not have // been replaced before deleting a Value). - if (DAI->isKillAddress()) { + if (Assign->isKillAddress()) { // The address isn't valid so treat this as a non-memory def. Kind = LocKind::Val; } else { - Value *Val = DAI->getAddress(); - DIExpression *Expr = DAI->getAddressExpression(); + Value *Val = Assign->getAddress(); + DIExpression *Expr = Assign->getAddressExpression(); assert(!Expr->getFragmentInfo() && "fragment info should be stored in value-expression only"); // Copy the fragment info over from the value-expression to the new @@ -1538,8 +1649,9 @@ void AssignmentTrackingLowering::processUntaggedInstruction( Ops.push_back(dwarf::DW_OP_deref); DIE = DIExpression::prependOpcodes(DIE, Ops, /*StackValue=*/false, /*EntryValue=*/false); - // Find a suitable insert point. - Instruction *InsertBefore = I.getNextNode(); + // Find a suitable insert point, before the next instruction or DPValue + // after I. + auto InsertBefore = getNextNode(&I); assert(InsertBefore && "Shouldn't be inserting after a terminator"); // Get DILocation for this unrecorded assignment. @@ -1561,25 +1673,26 @@ void AssignmentTrackingLowering::processUntaggedInstruction( void AssignmentTrackingLowering::processTaggedInstruction( Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { auto Linked = at::getAssignmentMarkers(&I); + auto LinkedDPAssigns = at::getDPVAssignmentMarkers(&I); // No dbg.assign intrinsics linked. // FIXME: All vars that have a stack slot this store modifies that don't have // a dbg.assign linked to it should probably treat this like an untagged // store. - if (Linked.empty()) + if (Linked.empty() && LinkedDPAssigns.empty()) return; LLVM_DEBUG(dbgs() << "processTaggedInstruction on " << I << "\n"); - for (DbgAssignIntrinsic *DAI : Linked) { - VariableID Var = getVariableID(DebugVariable(DAI)); + auto ProcessLinkedAssign = [&](auto *Assign) { + VariableID Var = getVariableID(DebugVariable(Assign)); // Something has gone wrong if VarsWithStackSlot doesn't contain a variable // that is linked to a store. - assert(VarsWithStackSlot->count(getAggregate(DAI)) && - "expected DAI's variable to have stack slot"); + assert(VarsWithStackSlot->count(getAggregate(Assign)) && + "expected Assign's variable to have stack slot"); Assignment AV = Assignment::makeFromMemDef(getIDFromInst(I)); addMemDef(LiveSet, Var, AV); - LLVM_DEBUG(dbgs() << " linked to " << *DAI << "\n"); + LLVM_DEBUG(dbgs() << " linked to " << *Assign << "\n"); LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) << " -> "); @@ -1594,8 +1707,8 @@ void AssignmentTrackingLowering::processTaggedInstruction( LiveSet->DebugValue[static_cast<unsigned>(Var)].dump(dbgs()); dbgs() << "\n"); setLocKind(LiveSet, Var, LocKind::Mem); - emitDbgValue(LocKind::Mem, DAI, &I); - continue; + emitDbgValue(LocKind::Mem, Assign, &I); + return; } // The StackHomeValue and DebugValue for this variable do not match. I.e. @@ -1620,7 +1733,7 @@ void AssignmentTrackingLowering::processTaggedInstruction( // We need to terminate any previously open location now. LLVM_DEBUG(dbgs() << "None, No Debug value available\n";); setLocKind(LiveSet, Var, LocKind::None); - emitDbgValue(LocKind::None, DAI, &I); + emitDbgValue(LocKind::None, Assign, &I); } else { // The previous DebugValue Value can be used here. LLVM_DEBUG(dbgs() << "Val, Debug value is Known\n";); @@ -1629,7 +1742,7 @@ void AssignmentTrackingLowering::processTaggedInstruction( emitDbgValue(LocKind::Val, DbgAV.Source, &I); } else { // PrevAV.Source is nullptr so we must emit undef here. - emitDbgValue(LocKind::None, DAI, &I); + emitDbgValue(LocKind::None, Assign, &I); } } } break; @@ -1640,78 +1753,93 @@ void AssignmentTrackingLowering::processTaggedInstruction( setLocKind(LiveSet, Var, LocKind::None); } break; } - } + }; + for (DbgAssignIntrinsic *DAI : Linked) + ProcessLinkedAssign(DAI); + for (DPValue *DPV : LinkedDPAssigns) + ProcessLinkedAssign(DPV); } -void AssignmentTrackingLowering::processDbgAssign(DbgAssignIntrinsic &DAI, +void AssignmentTrackingLowering::processDbgAssign(AssignRecord Assign, BlockInfo *LiveSet) { - // Only bother tracking variables that are at some point stack homed. Other - // variables can be dealt with trivially later. - if (!VarsWithStackSlot->count(getAggregate(&DAI))) - return; + auto ProcessDbgAssignImpl = [&](auto *DbgAssign) { + // Only bother tracking variables that are at some point stack homed. Other + // variables can be dealt with trivially later. + if (!VarsWithStackSlot->count(getAggregate(DbgAssign))) + return; - VariableID Var = getVariableID(DebugVariable(&DAI)); - Assignment AV = Assignment::make(getIDFromMarker(DAI), &DAI); - addDbgDef(LiveSet, Var, AV); - - LLVM_DEBUG(dbgs() << "processDbgAssign on " << DAI << "\n";); - LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) - << " -> "); - - // Check if the DebugValue and StackHomeValue both hold the same - // Assignment. - if (hasVarWithAssignment(LiveSet, BlockInfo::Stack, Var, AV)) { - // They match. We can use the stack home because the debug intrinsics state - // that an assignment happened here, and we know that specific assignment - // was the last one to take place in memory for this variable. - LocKind Kind; - if (DAI.isKillAddress()) { - LLVM_DEBUG( - dbgs() - << "Val, Stack matches Debug program but address is killed\n";); - Kind = LocKind::Val; + VariableID Var = getVariableID(DebugVariable(DbgAssign)); + Assignment AV = Assignment::make(getIDFromMarker(*DbgAssign), DbgAssign); + addDbgDef(LiveSet, Var, AV); + + LLVM_DEBUG(dbgs() << "processDbgAssign on " << *DbgAssign << "\n";); + LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) + << " -> "); + + // Check if the DebugValue and StackHomeValue both hold the same + // Assignment. + if (hasVarWithAssignment(LiveSet, BlockInfo::Stack, Var, AV)) { + // They match. We can use the stack home because the debug intrinsics + // state that an assignment happened here, and we know that specific + // assignment was the last one to take place in memory for this variable. + LocKind Kind; + if (DbgAssign->isKillAddress()) { + LLVM_DEBUG( + dbgs() + << "Val, Stack matches Debug program but address is killed\n";); + Kind = LocKind::Val; + } else { + LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";); + Kind = LocKind::Mem; + }; + setLocKind(LiveSet, Var, Kind); + emitDbgValue(Kind, DbgAssign, DbgAssign); } else { - LLVM_DEBUG(dbgs() << "Mem, Stack matches Debug program\n";); - Kind = LocKind::Mem; - }; - setLocKind(LiveSet, Var, Kind); - emitDbgValue(Kind, &DAI, &DAI); - } else { - // The last assignment to the memory location isn't the one that we want to - // show to the user so emit a dbg.value(Value). Value may be undef. - LLVM_DEBUG(dbgs() << "Val, Stack contents is unknown\n";); - setLocKind(LiveSet, Var, LocKind::Val); - emitDbgValue(LocKind::Val, &DAI, &DAI); - } + // The last assignment to the memory location isn't the one that we want + // to show to the user so emit a dbg.value(Value). Value may be undef. + LLVM_DEBUG(dbgs() << "Val, Stack contents is unknown\n";); + setLocKind(LiveSet, Var, LocKind::Val); + emitDbgValue(LocKind::Val, DbgAssign, DbgAssign); + } + }; + if (isa<DPValue *>(Assign)) + return ProcessDbgAssignImpl(cast<DPValue *>(Assign)); + return ProcessDbgAssignImpl(cast<DbgAssignIntrinsic *>(Assign)); } -void AssignmentTrackingLowering::processDbgValue(DbgValueInst &DVI, - BlockInfo *LiveSet) { - // Only other tracking variables that are at some point stack homed. - // Other variables can be dealt with trivally later. - if (!VarsWithStackSlot->count(getAggregate(&DVI))) - return; +void AssignmentTrackingLowering::processDbgValue( + PointerUnion<DbgValueInst *, DPValue *> DbgValueRecord, + BlockInfo *LiveSet) { + auto ProcessDbgValueImpl = [&](auto *DbgValue) { + // Only other tracking variables that are at some point stack homed. + // Other variables can be dealt with trivally later. + if (!VarsWithStackSlot->count(getAggregate(DbgValue))) + return; + + VariableID Var = getVariableID(DebugVariable(DbgValue)); + // We have no ID to create an Assignment with so we mark this assignment as + // NoneOrPhi. Note that the dbg.value still exists, we just cannot determine + // the assignment responsible for setting this value. + // This is fine; dbg.values are essentially interchangable with unlinked + // dbg.assigns, and some passes such as mem2reg and instcombine add them to + // PHIs for promoted variables. + Assignment AV = Assignment::makeNoneOrPhi(); + addDbgDef(LiveSet, Var, AV); + + LLVM_DEBUG(dbgs() << "processDbgValue on " << *DbgValue << "\n";); + LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) + << " -> Val, dbg.value override"); - VariableID Var = getVariableID(DebugVariable(&DVI)); - // We have no ID to create an Assignment with so we mark this assignment as - // NoneOrPhi. Note that the dbg.value still exists, we just cannot determine - // the assignment responsible for setting this value. - // This is fine; dbg.values are essentially interchangable with unlinked - // dbg.assigns, and some passes such as mem2reg and instcombine add them to - // PHIs for promoted variables. - Assignment AV = Assignment::makeNoneOrPhi(); - addDbgDef(LiveSet, Var, AV); - - LLVM_DEBUG(dbgs() << "processDbgValue on " << DVI << "\n";); - LLVM_DEBUG(dbgs() << " LiveLoc " << locStr(getLocKind(LiveSet, Var)) - << " -> Val, dbg.value override"); - - setLocKind(LiveSet, Var, LocKind::Val); - emitDbgValue(LocKind::Val, &DVI, &DVI); + setLocKind(LiveSet, Var, LocKind::Val); + emitDbgValue(LocKind::Val, DbgValue, DbgValue); + }; + if (isa<DPValue *>(DbgValueRecord)) + return ProcessDbgValueImpl(cast<DPValue *>(DbgValueRecord)); + return ProcessDbgValueImpl(cast<DbgValueInst *>(DbgValueRecord)); } -static bool hasZeroSizedFragment(DbgVariableIntrinsic &DVI) { - if (auto F = DVI.getExpression()->getFragmentInfo()) +template <typename T> static bool hasZeroSizedFragment(T &DbgValue) { + if (auto F = DbgValue.getExpression()->getFragmentInfo()) return F->SizeInBits == 0; return false; } @@ -1727,33 +1855,73 @@ void AssignmentTrackingLowering::processDbgInstruction( return; if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I)) - processDbgAssign(*DAI, LiveSet); + processDbgAssign(DAI, LiveSet); else if (auto *DVI = dyn_cast<DbgValueInst>(&I)) - processDbgValue(*DVI, LiveSet); + processDbgValue(DVI, LiveSet); +} +void AssignmentTrackingLowering::processDPValue( + DPValue &DPV, AssignmentTrackingLowering::BlockInfo *LiveSet) { + // Ignore assignments to zero bits of the variable. + if (hasZeroSizedFragment(DPV)) + return; + + if (DPV.isDbgAssign()) + processDbgAssign(&DPV, LiveSet); + else if (DPV.isDbgValue()) + processDbgValue(&DPV, LiveSet); } void AssignmentTrackingLowering::resetInsertionPoint(Instruction &After) { assert(!After.isTerminator() && "Can't insert after a terminator"); - auto R = InsertBeforeMap.find(After.getNextNode()); + auto *R = InsertBeforeMap.find(getNextNode(&After)); + if (R == InsertBeforeMap.end()) + return; + R->second.clear(); +} +void AssignmentTrackingLowering::resetInsertionPoint(DPValue &After) { + auto *R = InsertBeforeMap.find(getNextNode(&After)); if (R == InsertBeforeMap.end()) return; R->second.clear(); } void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { + // If the block starts with DPValues, we need to process those DPValues as + // their own frame without processing any instructions first. + bool ProcessedLeadingDPValues = !BB.begin()->hasDbgValues(); for (auto II = BB.begin(), EI = BB.end(); II != EI;) { assert(VarsTouchedThisFrame.empty()); // Process the instructions in "frames". A "frame" includes a single // non-debug instruction followed any debug instructions before the // next non-debug instruction. - if (!isa<DbgInfoIntrinsic>(&*II)) { - if (II->isTerminator()) - break; - resetInsertionPoint(*II); - processNonDbgInstruction(*II, LiveSet); - assert(LiveSet->isValid()); - ++II; + + // Skip the current instruction if it has unprocessed DPValues attached (see + // comment above `ProcessedLeadingDPValues`). + if (ProcessedLeadingDPValues) { + // II is now either a debug intrinsic, a non-debug instruction with no + // attached DPValues, or a non-debug instruction with attached processed + // DPValues. + // II has not been processed. + if (!isa<DbgInfoIntrinsic>(&*II)) { + if (II->isTerminator()) + break; + resetInsertionPoint(*II); + processNonDbgInstruction(*II, LiveSet); + assert(LiveSet->isValid()); + ++II; + } + } + // II is now either a debug intrinsic, a non-debug instruction with no + // attached DPValues, or a non-debug instruction with attached unprocessed + // DPValues. + if (II != EI && II->hasDbgValues()) { + for (DPValue &DPV : II->getDbgValueRange()) { + resetInsertionPoint(DPV); + processDPValue(DPV, LiveSet); + assert(LiveSet->isValid()); + } } + ProcessedLeadingDPValues = true; while (II != EI) { auto *Dbg = dyn_cast<DbgInfoIntrinsic>(&*II); if (!Dbg) @@ -1763,6 +1931,10 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { assert(LiveSet->isValid()); ++II; } + // II is now a non-debug instruction either with no attached DPValues, or + // with attached processed DPValues. II has not been processed, and all + // debug instructions or DPValues in the frame preceding II have been + // processed. // We've processed everything in the "frame". Now determine which variables // cannot be represented by a dbg.declare. @@ -1819,16 +1991,22 @@ AssignmentTrackingLowering::joinAssignment(const Assignment &A, // Here the same assignment (!1) was performed in both preds in the source, // but we can't use either one unless they are identical (e.g. .we don't // want to arbitrarily pick between constant values). - auto JoinSource = [&]() -> DbgAssignIntrinsic * { + auto JoinSource = [&]() -> AssignRecord { if (A.Source == B.Source) return A.Source; - if (A.Source == nullptr || B.Source == nullptr) - return nullptr; - if (A.Source->isIdenticalTo(B.Source)) + if (!A.Source || !B.Source) + return AssignRecord(); + assert(isa<DPValue *>(A.Source) == isa<DPValue *>(B.Source)); + if (isa<DPValue *>(A.Source) && + cast<DPValue *>(A.Source)->isEquivalentTo(*cast<DPValue *>(B.Source))) + return A.Source; + if (isa<DbgAssignIntrinsic *>(A.Source) && + cast<DbgAssignIntrinsic *>(A.Source)->isIdenticalTo( + cast<DbgAssignIntrinsic *>(B.Source))) return A.Source; - return nullptr; + return AssignRecord(); }; - DbgAssignIntrinsic *Source = JoinSource(); + AssignRecord Source = JoinSource(); assert(A.Status == B.Status && A.Status == Assignment::Known); assert(A.ID == B.ID); return Assignment::make(A.ID, Source); @@ -1851,8 +2029,7 @@ bool AssignmentTrackingLowering::join( // invalidated later, we will remove it when we revisit this block. This // is essentially the same as initialising all LocKinds and Assignments to // an implicit ⊥ value which is the identity value for the join operation. - for (auto I = pred_begin(&BB), E = pred_end(&BB); I != E; I++) { - const BasicBlock *Pred = *I; + for (const BasicBlock *Pred : predecessors(&BB)) { if (Visited.count(Pred)) VisitedPreds.push_back(Pred); } @@ -1938,6 +2115,14 @@ getUntaggedStoreAssignmentInfo(const Instruction &I, const DataLayout &Layout) { return std::nullopt; } +DbgDeclareInst *DynCastToDbgDeclare(DbgVariableIntrinsic *DVI) { + return dyn_cast<DbgDeclareInst>(DVI); +} + +DPValue *DynCastToDbgDeclare(DPValue *DPV) { + return DPV->isDbgDeclare() ? DPV : nullptr; +} + /// Build a map of {Variable x: Variables y} where all variable fragments /// contained within the variable fragment x are in set y. This means that /// y does not contain all overlaps because partial overlaps are excluded. @@ -1971,31 +2156,39 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( // UntaggedStoreVars. // We need to add fragments for untagged stores too so that we can correctly // clobber overlapped fragment locations later. - SmallVector<DbgDeclareInst *> Declares; + SmallVector<DbgDeclareInst *> InstDeclares; + SmallVector<DPValue *> DPDeclares; + auto ProcessDbgRecord = [&](auto *Record, auto &DeclareList) { + if (auto *Declare = DynCastToDbgDeclare(Record)) { + DeclareList.push_back(Declare); + return; + } + DebugVariable DV = DebugVariable(Record); + DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; + if (!VarsWithStackSlot.contains(DA)) + return; + if (Seen.insert(DV).second) + FragmentMap[DA].push_back(DV); + }; for (auto &BB : Fn) { for (auto &I : BB) { - if (auto *DDI = dyn_cast<DbgDeclareInst>(&I)) { - Declares.push_back(DDI); - } else if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { - DebugVariable DV = DebugVariable(DII); - DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; - if (!VarsWithStackSlot.contains(DA)) - continue; - if (Seen.insert(DV).second) - FragmentMap[DA].push_back(DV); + for (auto &DPV : I.getDbgValueRange()) + ProcessDbgRecord(&DPV, DPDeclares); + if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { + ProcessDbgRecord(DII, InstDeclares); } else if (auto Info = getUntaggedStoreAssignmentInfo( I, Fn.getParent()->getDataLayout())) { // Find markers linked to this alloca. - for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base)) { + auto HandleDbgAssignForStore = [&](auto *Assign) { std::optional<DIExpression::FragmentInfo> FragInfo; // Skip this assignment if the affected bits are outside of the // variable fragment. if (!at::calculateFragmentIntersect( I.getModule()->getDataLayout(), Info->Base, - Info->OffsetInBits, Info->SizeInBits, DAI, FragInfo) || + Info->OffsetInBits, Info->SizeInBits, Assign, FragInfo) || (FragInfo && FragInfo->SizeInBits == 0)) - continue; + return; // FragInfo from calculateFragmentIntersect is nullopt if the // resultant fragment matches DAI's fragment or entire variable - in @@ -2003,13 +2196,14 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( // nullopt after the copy it means "no fragment info" instead, which // is how it is usually interpreted. if (!FragInfo) - FragInfo = DAI->getExpression()->getFragmentInfo(); + FragInfo = Assign->getExpression()->getFragmentInfo(); - DebugVariable DV = DebugVariable(DAI->getVariable(), FragInfo, - DAI->getDebugLoc().getInlinedAt()); + DebugVariable DV = + DebugVariable(Assign->getVariable(), FragInfo, + Assign->getDebugLoc().getInlinedAt()); DebugAggregate DA = {DV.getVariable(), DV.getInlinedAt()}; if (!VarsWithStackSlot.contains(DA)) - continue; + return; // Cache this info for later. UntaggedStoreVars[&I].push_back( @@ -2017,7 +2211,11 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( if (Seen.insert(DV).second) FragmentMap[DA].push_back(DV); - } + }; + for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base)) + HandleDbgAssignForStore(DAI); + for (DPValue *DPV : at::getDPVAssignmentMarkers(Info->Base)) + HandleDbgAssignForStore(DPV); } } } @@ -2064,9 +2262,13 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( // Finally, insert the declares afterwards, so the first IDs are all // partially stack homed vars. - for (auto *DDI : Declares) + for (auto *DDI : InstDeclares) FnVarLocs->addSingleLocVar(DebugVariable(DDI), DDI->getExpression(), DDI->getDebugLoc(), DDI->getWrappedLocation()); + for (auto *DPV : DPDeclares) + FnVarLocs->addSingleLocVar(DebugVariable(DPV), DPV->getExpression(), + DPV->getDebugLoc(), + RawLocationWrapper(DPV->getRawLocation())); return Map; } @@ -2179,7 +2381,7 @@ bool AssignmentTrackingLowering::run(FunctionVarLocsBuilder *FnVarLocsBuilder) { // we can identify those uneeded defs later. DenseSet<DebugAggregate> AlwaysStackHomed; for (const auto &Pair : InsertBeforeMap) { - const auto &Vec = Pair.second; + auto &Vec = Pair.second; for (VarLocInfo VarLoc : Vec) { DebugVariable Var = FnVarLocs->getVariable(VarLoc.VariableID); DebugAggregate Aggr{Var.getVariable(), Var.getInlinedAt()}; @@ -2245,22 +2447,27 @@ bool AssignmentTrackingLowering::emitPromotedVarLocs( bool InsertedAnyIntrinsics = false; // Go through every block, translating debug intrinsics for fully promoted // variables into FnVarLocs location defs. No analysis required for these. + auto TranslateDbgRecord = [&](auto *Record) { + // Skip variables that haven't been promoted - we've dealt with those + // already. + if (VarsWithStackSlot->contains(getAggregate(Record))) + return; + auto InsertBefore = getNextNode(Record); + assert(InsertBefore && "Unexpected: debug intrinsics after a terminator"); + FnVarLocs->addVarLoc(InsertBefore, DebugVariable(Record), + Record->getExpression(), Record->getDebugLoc(), + RawLocationWrapper(Record->getRawLocation())); + InsertedAnyIntrinsics = true; + }; for (auto &BB : Fn) { for (auto &I : BB) { // Skip instructions other than dbg.values and dbg.assigns. + for (DPValue &DPV : I.getDbgValueRange()) + if (DPV.isDbgValue() || DPV.isDbgAssign()) + TranslateDbgRecord(&DPV); auto *DVI = dyn_cast<DbgValueInst>(&I); - if (!DVI) - continue; - // Skip variables that haven't been promoted - we've dealt with those - // already. - if (VarsWithStackSlot->contains(getAggregate(DVI))) - continue; - Instruction *InsertBefore = I.getNextNode(); - assert(InsertBefore && "Unexpected: debug intrinsics after a terminator"); - FnVarLocs->addVarLoc(InsertBefore, DebugVariable(DVI), - DVI->getExpression(), DVI->getDebugLoc(), - DVI->getWrappedLocation()); - InsertedAnyIntrinsics = true; + if (DVI) + TranslateDbgRecord(DVI); } } return InsertedAnyIntrinsics; @@ -2287,73 +2494,78 @@ removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB, VariableDefinedBytes.clear(); } - // Get the location defs that start just before this instruction. - const auto *Locs = FnVarLocs.getWedge(&I); - if (!Locs) - continue; + auto HandleLocsForWedge = [&](auto *WedgePosition) { + // Get the location defs that start just before this instruction. + const auto *Locs = FnVarLocs.getWedge(WedgePosition); + if (!Locs) + return; + + NumWedgesScanned++; + bool ChangedThisWedge = false; + // The new pruned set of defs, reversed because we're scanning backwards. + SmallVector<VarLocInfo> NewDefsReversed; + + // Iterate over the existing defs in reverse. + for (auto RIt = Locs->rbegin(), REnd = Locs->rend(); RIt != REnd; ++RIt) { + NumDefsScanned++; + DebugAggregate Aggr = + getAggregate(FnVarLocs.getVariable(RIt->VariableID)); + uint64_t SizeInBits = Aggr.first->getSizeInBits().value_or(0); + uint64_t SizeInBytes = divideCeil(SizeInBits, 8); + + // Cutoff for large variables to prevent expensive bitvector operations. + const uint64_t MaxSizeBytes = 2048; + + if (SizeInBytes == 0 || SizeInBytes > MaxSizeBytes) { + // If the size is unknown (0) then keep this location def to be safe. + // Do the same for defs of large variables, which would be expensive + // to represent with a BitVector. + NewDefsReversed.push_back(*RIt); + continue; + } - NumWedgesScanned++; - bool ChangedThisWedge = false; - // The new pruned set of defs, reversed because we're scanning backwards. - SmallVector<VarLocInfo> NewDefsReversed; - - // Iterate over the existing defs in reverse. - for (auto RIt = Locs->rbegin(), REnd = Locs->rend(); RIt != REnd; ++RIt) { - NumDefsScanned++; - DebugAggregate Aggr = - getAggregate(FnVarLocs.getVariable(RIt->VariableID)); - uint64_t SizeInBits = Aggr.first->getSizeInBits().value_or(0); - uint64_t SizeInBytes = divideCeil(SizeInBits, 8); - - // Cutoff for large variables to prevent expensive bitvector operations. - const uint64_t MaxSizeBytes = 2048; - - if (SizeInBytes == 0 || SizeInBytes > MaxSizeBytes) { - // If the size is unknown (0) then keep this location def to be safe. - // Do the same for defs of large variables, which would be expensive - // to represent with a BitVector. - NewDefsReversed.push_back(*RIt); - continue; - } + // Only keep this location definition if it is not fully eclipsed by + // other definitions in this wedge that come after it + + // Inert the bytes the location definition defines. + auto InsertResult = + VariableDefinedBytes.try_emplace(Aggr, BitVector(SizeInBytes)); + bool FirstDefinition = InsertResult.second; + BitVector &DefinedBytes = InsertResult.first->second; + + DIExpression::FragmentInfo Fragment = + RIt->Expr->getFragmentInfo().value_or( + DIExpression::FragmentInfo(SizeInBits, 0)); + bool InvalidFragment = Fragment.endInBits() > SizeInBits; + uint64_t StartInBytes = Fragment.startInBits() / 8; + uint64_t EndInBytes = divideCeil(Fragment.endInBits(), 8); + + // If this defines any previously undefined bytes, keep it. + if (FirstDefinition || InvalidFragment || + DefinedBytes.find_first_unset_in(StartInBytes, EndInBytes) != -1) { + if (!InvalidFragment) + DefinedBytes.set(StartInBytes, EndInBytes); + NewDefsReversed.push_back(*RIt); + continue; + } - // Only keep this location definition if it is not fully eclipsed by - // other definitions in this wedge that come after it - - // Inert the bytes the location definition defines. - auto InsertResult = - VariableDefinedBytes.try_emplace(Aggr, BitVector(SizeInBytes)); - bool FirstDefinition = InsertResult.second; - BitVector &DefinedBytes = InsertResult.first->second; - - DIExpression::FragmentInfo Fragment = - RIt->Expr->getFragmentInfo().value_or( - DIExpression::FragmentInfo(SizeInBits, 0)); - bool InvalidFragment = Fragment.endInBits() > SizeInBits; - uint64_t StartInBytes = Fragment.startInBits() / 8; - uint64_t EndInBytes = divideCeil(Fragment.endInBits(), 8); - - // If this defines any previously undefined bytes, keep it. - if (FirstDefinition || InvalidFragment || - DefinedBytes.find_first_unset_in(StartInBytes, EndInBytes) != -1) { - if (!InvalidFragment) - DefinedBytes.set(StartInBytes, EndInBytes); - NewDefsReversed.push_back(*RIt); - continue; + // Redundant def found: throw it away. Since the wedge of defs is being + // rebuilt, doing nothing is the same as deleting an entry. + ChangedThisWedge = true; + NumDefsRemoved++; } - // Redundant def found: throw it away. Since the wedge of defs is being - // rebuilt, doing nothing is the same as deleting an entry. - ChangedThisWedge = true; - NumDefsRemoved++; - } - - // Un-reverse the defs and replace the wedge with the pruned version. - if (ChangedThisWedge) { - std::reverse(NewDefsReversed.begin(), NewDefsReversed.end()); - FnVarLocs.setWedge(&I, std::move(NewDefsReversed)); - NumWedgesChanged++; - Changed = true; - } + // Un-reverse the defs and replace the wedge with the pruned version. + if (ChangedThisWedge) { + std::reverse(NewDefsReversed.begin(), NewDefsReversed.end()); + FnVarLocs.setWedge(WedgePosition, std::move(NewDefsReversed)); + NumWedgesChanged++; + Changed = true; + } + }; + HandleLocsForWedge(&I); + for (DPValue &DPV : reverse(I.getDbgValueRange())) + HandleLocsForWedge(&DPV); } return Changed; @@ -2378,42 +2590,48 @@ removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB, // instructions. for (const Instruction &I : *BB) { // Get the defs that come just before this instruction. - const auto *Locs = FnVarLocs.getWedge(&I); - if (!Locs) - continue; - - NumWedgesScanned++; - bool ChangedThisWedge = false; - // The new pruned set of defs. - SmallVector<VarLocInfo> NewDefs; + auto HandleLocsForWedge = [&](auto *WedgePosition) { + const auto *Locs = FnVarLocs.getWedge(WedgePosition); + if (!Locs) + return; + + NumWedgesScanned++; + bool ChangedThisWedge = false; + // The new pruned set of defs. + SmallVector<VarLocInfo> NewDefs; + + // Iterate over the existing defs. + for (const VarLocInfo &Loc : *Locs) { + NumDefsScanned++; + DebugVariable Key(FnVarLocs.getVariable(Loc.VariableID).getVariable(), + std::nullopt, Loc.DL.getInlinedAt()); + auto VMI = VariableMap.find(Key); + + // Update the map if we found a new value/expression describing the + // variable, or if the variable wasn't mapped already. + if (VMI == VariableMap.end() || VMI->second.first != Loc.Values || + VMI->second.second != Loc.Expr) { + VariableMap[Key] = {Loc.Values, Loc.Expr}; + NewDefs.push_back(Loc); + continue; + } - // Iterate over the existing defs. - for (const VarLocInfo &Loc : *Locs) { - NumDefsScanned++; - DebugVariable Key(FnVarLocs.getVariable(Loc.VariableID).getVariable(), - std::nullopt, Loc.DL.getInlinedAt()); - auto VMI = VariableMap.find(Key); - - // Update the map if we found a new value/expression describing the - // variable, or if the variable wasn't mapped already. - if (VMI == VariableMap.end() || VMI->second.first != Loc.Values || - VMI->second.second != Loc.Expr) { - VariableMap[Key] = {Loc.Values, Loc.Expr}; - NewDefs.push_back(Loc); - continue; + // Did not insert this Loc, which is the same as removing it. + ChangedThisWedge = true; + NumDefsRemoved++; } - // Did not insert this Loc, which is the same as removing it. - ChangedThisWedge = true; - NumDefsRemoved++; - } + // Replace the existing wedge with the pruned version. + if (ChangedThisWedge) { + FnVarLocs.setWedge(WedgePosition, std::move(NewDefs)); + NumWedgesChanged++; + Changed = true; + } + }; - // Replace the existing wedge with the pruned version. - if (ChangedThisWedge) { - FnVarLocs.setWedge(&I, std::move(NewDefs)); - NumWedgesChanged++; - Changed = true; - } + for (DPValue &DPV : I.getDbgValueRange()) + HandleLocsForWedge(&DPV); + HandleLocsForWedge(&I); } return Changed; @@ -2460,41 +2678,46 @@ removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB, // instructions. for (const Instruction &I : *BB) { // Get the defs that come just before this instruction. - const auto *Locs = FnVarLocs.getWedge(&I); - if (!Locs) - continue; - - NumWedgesScanned++; - bool ChangedThisWedge = false; - // The new pruned set of defs. - SmallVector<VarLocInfo> NewDefs; - - // Iterate over the existing defs. - for (const VarLocInfo &Loc : *Locs) { - NumDefsScanned++; - DebugAggregate Aggr{FnVarLocs.getVariable(Loc.VariableID).getVariable(), - Loc.DL.getInlinedAt()}; - DebugVariable Var = FnVarLocs.getVariable(Loc.VariableID); + auto HandleLocsForWedge = [&](auto *WedgePosition) { + const auto *Locs = FnVarLocs.getWedge(WedgePosition); + if (!Locs) + return; + + NumWedgesScanned++; + bool ChangedThisWedge = false; + // The new pruned set of defs. + SmallVector<VarLocInfo> NewDefs; + + // Iterate over the existing defs. + for (const VarLocInfo &Loc : *Locs) { + NumDefsScanned++; + DebugAggregate Aggr{FnVarLocs.getVariable(Loc.VariableID).getVariable(), + Loc.DL.getInlinedAt()}; + DebugVariable Var = FnVarLocs.getVariable(Loc.VariableID); + + // Remove undef entries that are encountered before any non-undef + // intrinsics from the entry block. + if (Loc.Values.isKillLocation(Loc.Expr) && !HasDefinedBits(Aggr, Var)) { + // Did not insert this Loc, which is the same as removing it. + NumDefsRemoved++; + ChangedThisWedge = true; + continue; + } - // Remove undef entries that are encountered before any non-undef - // intrinsics from the entry block. - if (Loc.Values.isKillLocation(Loc.Expr) && !HasDefinedBits(Aggr, Var)) { - // Did not insert this Loc, which is the same as removing it. - NumDefsRemoved++; - ChangedThisWedge = true; - continue; + DefineBits(Aggr, Var); + NewDefs.push_back(Loc); } - DefineBits(Aggr, Var); - NewDefs.push_back(Loc); - } - - // Replace the existing wedge with the pruned version. - if (ChangedThisWedge) { - FnVarLocs.setWedge(&I, std::move(NewDefs)); - NumWedgesChanged++; - Changed = true; - } + // Replace the existing wedge with the pruned version. + if (ChangedThisWedge) { + FnVarLocs.setWedge(WedgePosition, std::move(NewDefs)); + NumWedgesChanged++; + Changed = true; + } + }; + for (DPValue &DPV : I.getDbgValueRange()) + HandleLocsForWedge(&DPV); + HandleLocsForWedge(&I); } return Changed; @@ -2526,6 +2749,9 @@ static DenseSet<DebugAggregate> findVarsWithStackSlot(Function &Fn) { for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(&I)) { Result.insert({DAI->getVariable(), DAI->getDebugLoc().getInlinedAt()}); } + for (DPValue *DPV : at::getDPVAssignmentMarkers(&I)) { + Result.insert({DPV->getVariable(), DPV->getDebugLoc().getInlinedAt()}); + } } } return Result; |