aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp802
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;