mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-21 03:05:26 -04:00
[NFC] Replace a linked list in LiveDebugVariables pass with a DenseMap
In LiveDebugVariables.cpp:
Prior to this patch, UserValues were grouped into linked list chains. Each
chain was the union of two sets: { A: Matching Source variable } or
{ B: Matching virtual register }. A ptr to the heads (or 'leaders')
of each of these chains were kept in a map with the { Source variable } used
as the key (set A predicate) and another with { Virtual register } as key
(set B predicate).
There was a search through the chains in the function getUserValue looking for
UserValues with matching { Source variable, Complex expression, Inlined-at
location }. Essentially searching for a subset of A through two interleaved
linked lists of set A and B. Importantly, by design, the subset will only
contain one or zero elements here. That is to say a UserValue can be uniquely
identified by the tuple { Source variable, Complex expression, Inlined-at
location } if it exists.
This patch removes the linked list and instead uses a DenseMap to map
the tuple { Source variable, Complex expression, Inlined-at location }
to UserValue ptrs so that the getUserValue search predicate is this map key.
The virtual register map now maps a vreg to a SmallVector<UserVal *> so that
set B is still available for quick searches.
Reviewers: aprantl, probinson, vsk, dblaikie
Reviewed By: aprantl
Subscribers: russell.gallop, gbedwell, bjope, hiraditya, llvm-commits
Tags: #debug-info, #llvm
Differential Revision: https://reviews.llvm.org/D68816
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374979 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -142,22 +142,51 @@ namespace {
|
||||
|
||||
class LDVImpl;
|
||||
|
||||
/// A UserValue is uniquely identified by the source variable it refers to
|
||||
/// (Variable), the expression describing how to get the value (Expression) and
|
||||
/// the specific usage (InlinedAt). InlinedAt differentiates both between
|
||||
/// inline and non-inline functions, and multiple inlined instances in the same
|
||||
/// scope. FIXME: The only part of the Expression which matters for UserValue
|
||||
/// identification is the fragment part.
|
||||
class UserValueIdentity {
|
||||
private:
|
||||
/// The debug info variable we are part of.
|
||||
const DILocalVariable *Variable;
|
||||
/// Any complex address expression.
|
||||
const DIExpression *Expression;
|
||||
/// Function usage identification.
|
||||
const DILocation *InlinedAt;
|
||||
|
||||
public:
|
||||
UserValueIdentity(const DILocalVariable *Var, const DIExpression *Expr,
|
||||
const DILocation *IA)
|
||||
: Variable(Var), Expression(Expr), InlinedAt(IA) {}
|
||||
|
||||
bool match(const DILocalVariable *Var, const DIExpression *Expr,
|
||||
const DILocation *IA) const {
|
||||
// FIXME: The fragment should be part of the identity, but not
|
||||
// other things in the expression like stack values.
|
||||
return Var == Variable && Expr == Expression && IA == InlinedAt;
|
||||
}
|
||||
|
||||
bool match(const UserValueIdentity &Other) const {
|
||||
return match(Other.Variable, Other.Expression, Other.InlinedAt);
|
||||
}
|
||||
|
||||
unsigned hash_value() const {
|
||||
return hash_combine(Variable, Expression, InlinedAt);
|
||||
}
|
||||
};
|
||||
|
||||
/// A user value is a part of a debug info user variable.
|
||||
///
|
||||
/// A DBG_VALUE instruction notes that (a sub-register of) a virtual register
|
||||
/// holds part of a user variable. The part is identified by a byte offset.
|
||||
///
|
||||
/// UserValues are grouped into equivalence classes for easier searching. Two
|
||||
/// user values are related if they refer to the same variable, or if they are
|
||||
/// held by the same virtual register. The equivalence class is the transitive
|
||||
/// closure of that relation.
|
||||
class UserValue {
|
||||
const DILocalVariable *Variable; ///< The debug info variable we are part of.
|
||||
const DIExpression *Expression; ///< Any complex address expression.
|
||||
DebugLoc dl; ///< The debug location for the variable. This is
|
||||
///< used by dwarf writer to find lexical scope.
|
||||
UserValue *leader; ///< Equivalence class leader.
|
||||
UserValue *next = nullptr; ///< Next value in equivalence class, or null.
|
||||
|
||||
/// Numbered locations referenced by locmap.
|
||||
SmallVector<MachineOperand, 4> locations;
|
||||
@@ -178,49 +207,15 @@ class UserValue {
|
||||
LiveIntervals &LIS);
|
||||
|
||||
public:
|
||||
UserValue(const UserValue &) = delete;
|
||||
|
||||
/// Create a new UserValue.
|
||||
UserValue(const DILocalVariable *var, const DIExpression *expr, DebugLoc L,
|
||||
LocMap::Allocator &alloc)
|
||||
: Variable(var), Expression(expr), dl(std::move(L)), leader(this),
|
||||
locInts(alloc) {}
|
||||
: Variable(var), Expression(expr), dl(std::move(L)), locInts(alloc) {}
|
||||
|
||||
/// Get the leader of this value's equivalence class.
|
||||
UserValue *getLeader() {
|
||||
UserValue *l = leader;
|
||||
while (l != l->leader)
|
||||
l = l->leader;
|
||||
return leader = l;
|
||||
}
|
||||
|
||||
/// Return the next UserValue in the equivalence class.
|
||||
UserValue *getNext() const { return next; }
|
||||
|
||||
/// Does this UserValue match the parameters?
|
||||
bool match(const DILocalVariable *Var, const DIExpression *Expr,
|
||||
const DILocation *IA) const {
|
||||
// FIXME: The fragment should be part of the equivalence class, but not
|
||||
// other things in the expression like stack values.
|
||||
return Var == Variable && Expr == Expression && dl->getInlinedAt() == IA;
|
||||
}
|
||||
|
||||
/// Merge equivalence classes.
|
||||
static UserValue *merge(UserValue *L1, UserValue *L2) {
|
||||
L2 = L2->getLeader();
|
||||
if (!L1)
|
||||
return L2;
|
||||
L1 = L1->getLeader();
|
||||
if (L1 == L2)
|
||||
return L1;
|
||||
// Splice L2 before L1's members.
|
||||
UserValue *End = L2;
|
||||
while (End->next) {
|
||||
End->leader = L1;
|
||||
End = End->next;
|
||||
}
|
||||
End->leader = L1;
|
||||
End->next = L1->next;
|
||||
L1->next = L2;
|
||||
return L1;
|
||||
UserValueIdentity getId() {
|
||||
return UserValueIdentity(Variable, Expression, dl->getInlinedAt());
|
||||
}
|
||||
|
||||
/// Return the location number that matches Loc.
|
||||
@@ -332,7 +327,29 @@ public:
|
||||
|
||||
void print(raw_ostream &, const TargetRegisterInfo *);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace llvm {
|
||||
template <> struct DenseMapInfo<UserValueIdentity> {
|
||||
static UserValueIdentity getEmptyKey() {
|
||||
auto Key = DenseMapInfo<DILocalVariable *>::getEmptyKey();
|
||||
return UserValueIdentity(Key, nullptr, nullptr);
|
||||
}
|
||||
static UserValueIdentity getTombstoneKey() {
|
||||
auto Key = DenseMapInfo<DILocalVariable *>::getTombstoneKey();
|
||||
return UserValueIdentity(Key, nullptr, nullptr);
|
||||
}
|
||||
static unsigned getHashValue(const UserValueIdentity &Val) {
|
||||
return Val.hash_value();
|
||||
}
|
||||
static bool isEqual(const UserValueIdentity &LHS,
|
||||
const UserValueIdentity &RHS) {
|
||||
return LHS.match(RHS);
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
namespace {
|
||||
/// A user label is a part of a debug info user label.
|
||||
class UserLabel {
|
||||
const DILabel *Label; ///< The debug info label we are part of.
|
||||
@@ -384,20 +401,20 @@ class LDVImpl {
|
||||
/// All allocated UserLabel instances.
|
||||
SmallVector<std::unique_ptr<UserLabel>, 2> userLabels;
|
||||
|
||||
/// Map virtual register to eq class leader.
|
||||
using VRMap = DenseMap<unsigned, UserValue *>;
|
||||
VRMap virtRegToEqClass;
|
||||
/// Map virtual register to UserValues which use it.
|
||||
using VRMap = DenseMap<unsigned, SmallVector<UserValue *, 4>>;
|
||||
VRMap VirtRegToUserVals;
|
||||
|
||||
/// Map user variable to eq class leader.
|
||||
using UVMap = DenseMap<const DILocalVariable *, UserValue *>;
|
||||
UVMap userVarMap;
|
||||
/// Map unique UserValue identity to UserValue.
|
||||
using UVMap = DenseMap<UserValueIdentity, UserValue *>;
|
||||
UVMap UserVarMap;
|
||||
|
||||
/// Find or create a UserValue.
|
||||
UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr,
|
||||
const DebugLoc &DL);
|
||||
|
||||
/// Find the EC leader for VirtReg or null.
|
||||
UserValue *lookupVirtReg(unsigned VirtReg);
|
||||
/// Find the UserValues for VirtReg or null.
|
||||
SmallVectorImpl<UserValue *> *lookupVirtReg(unsigned VirtReg);
|
||||
|
||||
/// Add DBG_VALUE instruction to our maps.
|
||||
///
|
||||
@@ -437,8 +454,8 @@ public:
|
||||
MF = nullptr;
|
||||
userValues.clear();
|
||||
userLabels.clear();
|
||||
virtRegToEqClass.clear();
|
||||
userVarMap.clear();
|
||||
VirtRegToUserVals.clear();
|
||||
UserVarMap.clear();
|
||||
// Make sure we call emitDebugValues if the machine function was modified.
|
||||
assert((!ModifiedMF || EmitDone) &&
|
||||
"Dbg values are not emitted in LDV");
|
||||
@@ -446,8 +463,8 @@ public:
|
||||
ModifiedMF = false;
|
||||
}
|
||||
|
||||
/// Map virtual register to an equivalence class.
|
||||
void mapVirtReg(unsigned VirtReg, UserValue *EC);
|
||||
/// Map virtual register to a UserValue.
|
||||
void mapVirtReg(unsigned VirtReg, UserValue *UV);
|
||||
|
||||
/// Replace all references to OldReg with NewRegs.
|
||||
void splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs);
|
||||
@@ -555,31 +572,27 @@ void UserValue::mapVirtRegs(LDVImpl *LDV) {
|
||||
|
||||
UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,
|
||||
const DIExpression *Expr, const DebugLoc &DL) {
|
||||
UserValue *&Leader = userVarMap[Var];
|
||||
if (Leader) {
|
||||
UserValue *UV = Leader->getLeader();
|
||||
Leader = UV;
|
||||
for (; UV; UV = UV->getNext())
|
||||
if (UV->match(Var, Expr, DL->getInlinedAt()))
|
||||
return UV;
|
||||
}
|
||||
auto Ident = UserValueIdentity(Var, Expr, DL->getInlinedAt());
|
||||
UserValue *&UVEntry = UserVarMap[Ident];
|
||||
|
||||
userValues.push_back(
|
||||
std::make_unique<UserValue>(Var, Expr, DL, allocator));
|
||||
UserValue *UV = userValues.back().get();
|
||||
Leader = UserValue::merge(Leader, UV);
|
||||
return UV;
|
||||
if (UVEntry)
|
||||
return UVEntry;
|
||||
|
||||
userValues.push_back(std::make_unique<UserValue>(Var, Expr, DL, allocator));
|
||||
return UVEntry = userValues.back().get();
|
||||
}
|
||||
|
||||
void LDVImpl::mapVirtReg(unsigned VirtReg, UserValue *EC) {
|
||||
void LDVImpl::mapVirtReg(unsigned VirtReg, UserValue *UV) {
|
||||
assert(Register::isVirtualRegister(VirtReg) && "Only map VirtRegs");
|
||||
UserValue *&Leader = virtRegToEqClass[VirtReg];
|
||||
Leader = UserValue::merge(Leader, EC);
|
||||
assert(UserVarMap.find(UV->getId()) != UserVarMap.end() &&
|
||||
"UserValue should exist in UserVarMap");
|
||||
VirtRegToUserVals[VirtReg].push_back(UV);
|
||||
}
|
||||
|
||||
UserValue *LDVImpl::lookupVirtReg(unsigned VirtReg) {
|
||||
if (UserValue *UV = virtRegToEqClass.lookup(VirtReg))
|
||||
return UV->getLeader();
|
||||
SmallVectorImpl<UserValue *> *LDVImpl::lookupVirtReg(unsigned VirtReg) {
|
||||
VRMap::iterator Itr = VirtRegToUserVals.find(VirtReg);
|
||||
if (Itr != VirtRegToUserVals.end())
|
||||
return &Itr->getSecond();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1116,16 +1129,18 @@ UserValue::splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs,
|
||||
|
||||
void LDVImpl::splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs) {
|
||||
bool DidChange = false;
|
||||
for (UserValue *UV = lookupVirtReg(OldReg); UV; UV = UV->getNext())
|
||||
DidChange |= UV->splitRegister(OldReg, NewRegs, *LIS);
|
||||
if (auto *UserVals = lookupVirtReg(OldReg))
|
||||
for (auto *UV : *UserVals)
|
||||
DidChange |= UV->splitRegister(OldReg, NewRegs, *LIS);
|
||||
|
||||
if (!DidChange)
|
||||
return;
|
||||
|
||||
// Map all of the new virtual registers.
|
||||
UserValue *UV = lookupVirtReg(OldReg);
|
||||
for (unsigned i = 0; i != NewRegs.size(); ++i)
|
||||
mapVirtReg(NewRegs[i], UV);
|
||||
if (auto *UserVals = lookupVirtReg(OldReg))
|
||||
for (auto *UV : *UserVals)
|
||||
for (unsigned i = 0; i != NewRegs.size(); ++i)
|
||||
mapVirtReg(NewRegs[i], UV);
|
||||
}
|
||||
|
||||
void LiveDebugVariables::
|
||||
|
||||
Reference in New Issue
Block a user