[llvm] [RemoveDIs][DebugInfo] Handle DPVAssigns in AssignmentTrackingLowering (PR #78980)
Stephen Tozer via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 23 04:30:50 PST 2024
https://github.com/SLTozer updated https://github.com/llvm/llvm-project/pull/78980
>From 3328e91bceda6702bb2905789c49ba34bc9d1bbe Mon Sep 17 00:00:00 2001
From: Stephen Tozer <Stephen.Tozer at Sony.com>
Date: Wed, 3 Jan 2024 16:00:59 +0000
Subject: [PATCH 1/2] Handle DPValues in AssignmentTrackingLowering
---
.../CodeGen/AssignmentTrackingAnalysis.cpp | 427 ++++++++++++------
1 file changed, 289 insertions(+), 138 deletions(-)
diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
index 52b464cc76af4c..2dd681ed744c3f 100644
--- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
+++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
@@ -1019,13 +1019,14 @@ class AssignmentTrackingLowering {
/// 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
@@ -1040,31 +1041,51 @@ class AssignmentTrackingLowering {
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>;
@@ -1091,8 +1112,16 @@ class AssignmentTrackingLowering {
/// After.
void resetInsertionPoint(Instruction &After);
void resetInsertionPoint(DPValue &After);
- void emitDbgValue(LocKind Kind, const DbgVariableIntrinsic *Source,
- Instruction *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) {
@@ -1317,8 +1346,10 @@ class AssignmentTrackingLowering {
/// 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.
@@ -1418,6 +1449,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,
@@ -1466,9 +1503,27 @@ VarLocInsertPt getNextNode(VarLocInsertPt 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) {
@@ -1493,15 +1548,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
@@ -1610,25 +1665,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))
<< " -> ");
@@ -1643,8 +1699,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.
@@ -1669,7 +1725,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";);
@@ -1678,7 +1734,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;
@@ -1689,74 +1745,89 @@ 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(&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);
+ 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");
+
+ setLocKind(LiveSet, Var, LocKind::Val);
+ emitDbgValue(LocKind::Val, DbgValue, DbgValue);
+ };
+ if (isa<DPValue *>(DbgValueRecord))
+ return ProcessDbgValueImpl(cast<DPValue *>(DbgValueRecord));
+ return ProcessDbgValueImpl(cast<DbgValueInst *>(DbgValueRecord));
}
template <typename T> static bool hasZeroSizedFragment(T &DbgValue) {
@@ -1776,33 +1847,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)
@@ -1812,6 +1923,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.
@@ -1868,16 +1983,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;
- return nullptr;
+ if (isa<DbgAssignIntrinsic *>(A.Source) &&
+ cast<DbgAssignIntrinsic *>(A.Source)->isIdenticalTo(
+ cast<DbgAssignIntrinsic *>(B.Source)))
+ return A.Source;
+ 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);
@@ -1986,6 +2107,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.
@@ -2019,31 +2148,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
@@ -2051,13 +2188,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(
@@ -2065,7 +2203,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);
}
}
}
@@ -2112,9 +2254,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;
}
@@ -2227,7 +2373,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()};
@@ -2293,22 +2439,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;
>From 7d3782e1036ad1af9b2b91beba0367cc56b82ea4 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <Stephen.Tozer at Sony.com>
Date: Tue, 23 Jan 2024 12:30:40 +0000
Subject: [PATCH 2/2] clang-format
---
llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
index 2dd681ed744c3f..a558a304e8f41b 100644
--- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
+++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp
@@ -1508,7 +1508,8 @@ DbgAssignIntrinsic *CastToDbgAssign(DbgVariableIntrinsic *DVI) {
}
DPValue *CastToDbgAssign(DPValue *DPV) {
- assert(DPV->isDbgAssign() && "Attempted to cast non-assign DPValue to DPVAssign.");
+ assert(DPV->isDbgAssign() &&
+ "Attempted to cast non-assign DPValue to DPVAssign.");
return DPV;
}
More information about the llvm-commits
mailing list