diff options
| author | Adrian Prantl <aprantl@apple.com> | 2016-09-28 17:51:14 +0000 |
|---|---|---|
| committer | Adrian Prantl <aprantl@apple.com> | 2016-09-28 17:51:14 +0000 |
| commit | 7f5866c227a716cb063b268b6f0edaccb1029605 (patch) | |
| tree | f4b38040c7bf4ca7a2327988945b6954477432b0 /llvm/lib | |
| parent | d4d9dc82529d5788fdf6a18f413584e3aa0b3fd4 (diff) | |
| download | bcm5719-llvm-7f5866c227a716cb063b268b6f0edaccb1029605.tar.gz bcm5719-llvm-7f5866c227a716cb063b268b6f0edaccb1029605.zip | |
Teach LiveDebugValues about lexical scopes.
This addresses PR26055 LiveDebugValues is very slow.
Contrary to the old LiveDebugVariables pass LiveDebugValues currently
doesn't look at the lexical scopes before inserting a DBG_VALUE
intrinsic. This means that we often propagate DBG_VALUEs much further
down than necessary. This is especially noticeable in large C++
functions with many inlined method calls that all use the same
"this"-pointer.
For example, in the following code it makes no sense to propagate the
inlined variable a from the first inlined call to f() into any of the
subsequent basic blocks, because the variable will always be out of
scope:
void sink(int a);
void __attribute((always_inline)) f(int a) { sink(a); }
void foo(int i) {
f(i);
if (i)
f(i);
f(i);
}
This patch reuses the LexicalScopes infrastructure we have for
LiveDebugVariables to take this into account.
The effect on compile time and memory consumption is quite noticeable:
I tested a benchmark that is a large C++ source with an enormous
amount of inlined "this"-pointers that would previously eat >24GiB
(most of them for DBG_VALUE intrinsics) and whose compile time was
dominated by LiveDebugValues. With this patch applied the memory
consumption is 1GiB and 1.7% of the time is spent in LiveDebugValues.
https://reviews.llvm.org/D24994
Thanks to Daniel Berlin and Keith Walker for reviewing!
llvm-svn: 282611
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/LiveDebugValues.cpp | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp index 7d9461214ef..c945376560f 100644 --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/SparseBitVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/UniqueVector.h" +#include "llvm/CodeGen/LexicalScopes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -60,6 +61,26 @@ class LiveDebugValues : public MachineFunctionPass { private: const TargetRegisterInfo *TRI; const TargetInstrInfo *TII; + LexicalScopes LS; + + /// Keeps track of lexical scopes associated with a user value's source + /// location. + class UserValueScopes { + DebugLoc DL; + LexicalScopes &LS; + SmallPtrSet<const MachineBasicBlock *, 4> LBlocks; + + public: + UserValueScopes(DebugLoc D, LexicalScopes &L) : DL(std::move(D)), LS(L) {} + + /// Return true if current scope dominates at least one machine + /// instruction in a given machine basic block. + bool dominates(MachineBasicBlock *MBB) { + if (LBlocks.empty()) + LS.getMachineBasicBlocks(DL, LBlocks); + return LBlocks.count(MBB) != 0 || LS.dominates(DL, MBB); + } + }; /// Based on std::pair so it can be used as an index into a DenseMap. typedef std::pair<const DILocalVariable *, const DILocation *> @@ -83,7 +104,7 @@ private: struct VarLoc { const DebugVariable Var; const MachineInstr &MI; ///< Only used for cloning a new DBG_VALUE. - + mutable UserValueScopes UVS; enum { InvalidKind = 0, RegisterKind } Kind; /// The value location. Stored separately to avoid repeatedly @@ -96,9 +117,9 @@ private: uint64_t Hash; } Loc; - VarLoc(const MachineInstr &MI) + VarLoc(const MachineInstr &MI, LexicalScopes &LS) : Var(MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()), MI(MI), - Kind(InvalidKind) { + UVS(MI.getDebugLoc(), LS), Kind(InvalidKind) { static_assert((sizeof(Loc) == sizeof(uint64_t)), "hash does not cover all members of Loc"); assert(MI.isDebugValue() && "not a DBG_VALUE"); @@ -125,6 +146,10 @@ private: return 0; } + /// Determine whether the lexical scope of this value's debug location + /// dominates MBB. + bool dominates(MachineBasicBlock &MBB) const { return UVS.dominates(&MBB); } + void dump() const { MI.dump(); } bool operator==(const VarLoc &Other) const { @@ -229,6 +254,7 @@ public: /// Calculate the liveness information for the given machine function. bool runOnMachineFunction(MachineFunction &MF) override; }; + } // namespace //===----------------------------------------------------------------------===// @@ -295,7 +321,7 @@ void LiveDebugValues::transferDebugValue(const MachineInstr &MI, // Add the VarLoc to OpenRanges from this DBG_VALUE. // TODO: Currently handles DBG_VALUE which has only reg as location. if (isDbgValueDescribedByReg(MI)) { - VarLoc VL(MI); + VarLoc VL(MI, LS); unsigned ID = VarLocIDs.insert(VL); OpenRanges.insert(ID, VL.Var); } @@ -399,6 +425,13 @@ bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, NumVisited++; } + // Filter out DBG_VALUES that are out of scope. + VarLocSet KillSet; + for (auto ID : InLocsT) + if (!VarLocIDs[ID].dominates(MBB)) + KillSet.set(ID); + InLocsT.intersectWithComplement(KillSet); + // As we are processing blocks in reverse post-order we // should have processed at least one predecessor, unless it // is the entry block which has no predecessor. @@ -520,12 +553,14 @@ bool LiveDebugValues::ExtendRanges(MachineFunction &MF) { } bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) { + if (!MF.getFunction()->getSubprogram()) + // LiveDebugValues will already have removed all DBG_VALUEs. + return false; + TRI = MF.getSubtarget().getRegisterInfo(); TII = MF.getSubtarget().getInstrInfo(); + LS.initialize(MF); - bool Changed = false; - - Changed |= ExtendRanges(MF); - + bool Changed = ExtendRanges(MF); return Changed; } |

