Skip to content

Commit acacec3

Browse files
[LiveDebugValues][nfc] Reduce memory usage of InstrRef (#76051)
Commit 1b531d5 (#74203) removed the usage of unique_ptrs of arrays in favour of using vectors, but inadvertently increased peak memory usage by removing the ability to deallocate vector memory that was no longer needed mid-LDV. In that same review, it was pointed out that `FuncValueTable` typedef could be removed, since it was "just a vector". This commit addresses both issues by making `FuncValueTable` a real data structure, capable of mapping BBs to ValueTables and able to free ValueTables as needed. This reduces peak memory usage in the compiler by 10% in the benchmarks flagged by the original review. As a consequence, we had to remove a handful of instances of the "declare-then-initialize" antipattern in unittests, as the FuncValueTable class is no longer default-constructible.
1 parent fbcf8a8 commit acacec3

File tree

3 files changed

+80
-61
lines changed

3 files changed

+80
-61
lines changed

llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,7 +2413,7 @@ bool InstrRefBasedLDV::mlocJoin(
24132413

24142414
// Pick out the first predecessors live-out value for this location. It's
24152415
// guaranteed to not be a backedge, as we order by RPO.
2416-
ValueIDNum FirstVal = OutLocs[BlockOrders[0]->getNumber()][Idx.asU64()];
2416+
ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.asU64()];
24172417

24182418
// If we've already eliminated a PHI here, do no further checking, just
24192419
// propagate the first live-in value into this block.
@@ -2430,8 +2430,7 @@ bool InstrRefBasedLDV::mlocJoin(
24302430
bool Disagree = false;
24312431
for (unsigned int I = 1; I < BlockOrders.size(); ++I) {
24322432
const MachineBasicBlock *PredMBB = BlockOrders[I];
2433-
const ValueIDNum &PredLiveOut =
2434-
OutLocs[PredMBB->getNumber()][Idx.asU64()];
2433+
const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.asU64()];
24352434

24362435
// Incoming values agree, continue trying to eliminate this PHI.
24372436
if (FirstVal == PredLiveOut)
@@ -2556,7 +2555,7 @@ void InstrRefBasedLDV::placeMLocPHIs(
25562555

25572556
auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx L) {
25582557
for (const MachineBasicBlock *MBB : PHIBlocks)
2559-
MInLocs[MBB->getNumber()][L.asU64()] = ValueIDNum(MBB->getNumber(), 0, L);
2558+
MInLocs[*MBB][L.asU64()] = ValueIDNum(MBB->getNumber(), 0, L);
25602559
};
25612560

25622561
// For locations with no reg units, just place PHIs.
@@ -2635,7 +2634,8 @@ void InstrRefBasedLDV::buildMLocValueMap(
26352634

26362635
// Initialize entry block to PHIs. These represent arguments.
26372636
for (auto Location : MTracker->locations())
2638-
MInLocs[0][Location.Idx.asU64()] = ValueIDNum(0, 0, Location.Idx);
2637+
MInLocs.tableForEntryMBB()[Location.Idx.asU64()] =
2638+
ValueIDNum(0, 0, Location.Idx);
26392639

26402640
MTracker->reset();
26412641

@@ -2664,7 +2664,7 @@ void InstrRefBasedLDV::buildMLocValueMap(
26642664

26652665
// Join the values in all predecessor blocks.
26662666
bool InLocsChanged;
2667-
InLocsChanged = mlocJoin(*MBB, Visited, MOutLocs, MInLocs[CurBB]);
2667+
InLocsChanged = mlocJoin(*MBB, Visited, MOutLocs, MInLocs[*MBB]);
26682668
InLocsChanged |= Visited.insert(MBB).second;
26692669

26702670
// Don't examine transfer function if we've visited this loc at least
@@ -2673,7 +2673,7 @@ void InstrRefBasedLDV::buildMLocValueMap(
26732673
continue;
26742674

26752675
// Load the current set of live-ins into MLocTracker.
2676-
MTracker->loadFromArray(MInLocs[CurBB], CurBB);
2676+
MTracker->loadFromArray(MInLocs[*MBB], CurBB);
26772677

26782678
// Each element of the transfer function can be a new def, or a read of
26792679
// a live-in value. Evaluate each element, and store to "ToRemap".
@@ -2700,8 +2700,8 @@ void InstrRefBasedLDV::buildMLocValueMap(
27002700
// the transfer function, and mlocJoin.
27012701
bool OLChanged = false;
27022702
for (auto Location : MTracker->locations()) {
2703-
OLChanged |= MOutLocs[CurBB][Location.Idx.asU64()] != Location.Value;
2704-
MOutLocs[CurBB][Location.Idx.asU64()] = Location.Value;
2703+
OLChanged |= MOutLocs[*MBB][Location.Idx.asU64()] != Location.Value;
2704+
MOutLocs[*MBB][Location.Idx.asU64()] = Location.Value;
27052705
}
27062706

27072707
MTracker->reset();
@@ -2844,7 +2844,6 @@ std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
28442844
unsigned NumLocs = MTracker->getNumLocs();
28452845

28462846
for (const auto p : BlockOrders) {
2847-
unsigned ThisBBNum = p->getNumber();
28482847
auto OutValIt = LiveOuts.find(p);
28492848
assert(OutValIt != LiveOuts.end());
28502849
const DbgValue &OutVal = *OutValIt->second;
@@ -2863,7 +2862,7 @@ std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
28632862
ValueIDNum ValToLookFor = OutValOp.ID;
28642863
// Search the live-outs of the predecessor for the specified value.
28652864
for (unsigned int I = 0; I < NumLocs; ++I) {
2866-
if (MOutLocs[ThisBBNum][I] == ValToLookFor)
2865+
if (MOutLocs[*p][I] == ValToLookFor)
28672866
Locs.back().push_back(LocIdx(I));
28682867
}
28692868
} else {
@@ -2876,7 +2875,7 @@ std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
28762875
// machine-value PHI locations.
28772876
for (unsigned int I = 0; I < NumLocs; ++I) {
28782877
ValueIDNum MPHI(MBB.getNumber(), 0, LocIdx(I));
2879-
if (MOutLocs[ThisBBNum][I] == MPHI)
2878+
if (MOutLocs[*p][I] == MPHI)
28802879
Locs.back().push_back(LocIdx(I));
28812880
}
28822881
}
@@ -3498,19 +3497,15 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit(
34983497
// Helper lambda for ejecting a block -- if nothing is going to use the block,
34993498
// we can translate the variable location information into DBG_VALUEs and then
35003499
// free all of InstrRefBasedLDV's data structures.
3501-
SmallPtrSet<const MachineBasicBlock *, 8> EjectedBBs;
35023500
auto EjectBlock = [&](MachineBasicBlock &MBB) -> void {
3503-
if (EjectedBBs.insert(&MBB).second == false)
3504-
return;
35053501
unsigned BBNum = MBB.getNumber();
35063502
AllTheVLocs[BBNum].clear();
35073503

35083504
// Prime the transfer-tracker, and then step through all the block
35093505
// instructions, installing transfers.
35103506
MTracker->reset();
3511-
MTracker->loadFromArray(MInLocs[BBNum], BBNum);
3512-
TTracker->loadInlocs(MBB, MInLocs[BBNum], DbgOpStore, Output[BBNum],
3513-
NumLocs);
3507+
MTracker->loadFromArray(MInLocs[MBB], BBNum);
3508+
TTracker->loadInlocs(MBB, MInLocs[MBB], DbgOpStore, Output[BBNum], NumLocs);
35143509

35153510
CurBB = BBNum;
35163511
CurInst = 1;
@@ -3521,8 +3516,8 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit(
35213516
}
35223517

35233518
// Free machine-location tables for this block.
3524-
MInLocs[BBNum] = ValueTable();
3525-
MOutLocs[BBNum] = ValueTable();
3519+
MInLocs.ejectTableForBlock(MBB);
3520+
MOutLocs.ejectTableForBlock(MBB);
35263521
// We don't need live-in variable values for this block either.
35273522
Output[BBNum].clear();
35283523
AllTheVLocs[BBNum].clear();
@@ -3587,7 +3582,8 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit(
35873582
// anything for such out-of-scope blocks, but for the sake of being similar
35883583
// to VarLocBasedLDV, eject these too.
35893584
for (auto *MBB : ArtificialBlocks)
3590-
EjectBlock(*MBB);
3585+
if (MInLocs.hasTableFor(*MBB))
3586+
EjectBlock(*MBB);
35913587

35923588
return emitTransfers(AllVarsNumbering);
35933589
}
@@ -3686,8 +3682,8 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
36863682
// machine values. The outer dimension is the block number; while the inner
36873683
// dimension is a LocIdx from MLocTracker.
36883684
unsigned NumLocs = MTracker->getNumLocs();
3689-
FuncValueTable MOutLocs(MaxNumBlocks, ValueTable(NumLocs));
3690-
FuncValueTable MInLocs(MaxNumBlocks, ValueTable(NumLocs));
3685+
FuncValueTable MOutLocs(MaxNumBlocks, NumLocs);
3686+
FuncValueTable MInLocs(MaxNumBlocks, NumLocs);
36913687

36923688
// Solve the machine value dataflow problem using the MLocTransfer function,
36933689
// storing the computed live-ins / live-outs into the array-of-arrays. We use
@@ -3725,7 +3721,7 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
37253721
CurBB = MBB.getNumber();
37263722
VTracker = &vlocs[CurBB];
37273723
VTracker->MBB = &MBB;
3728-
MTracker->loadFromArray(MInLocs[CurBB], CurBB);
3724+
MTracker->loadFromArray(MInLocs[MBB], CurBB);
37293725
CurInst = 1;
37303726
for (auto &MI : MBB) {
37313727
process(MI, &MOutLocs, &MInLocs);
@@ -3939,7 +3935,7 @@ class LDVSSAUpdater {
39393935
/// Find the live-in value number for the given block. Looks up the value at
39403936
/// the PHI location on entry.
39413937
BlockValueNum getValue(LDVSSABlock *LDVBB) {
3942-
return MLiveIns[LDVBB->BB.getNumber()][Loc.asU64()].asU64();
3938+
return MLiveIns[LDVBB->BB][Loc.asU64()].asU64();
39433939
}
39443940
};
39453941

@@ -4179,8 +4175,7 @@ std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
41794175
});
41804176

41814177
for (auto &PHI : SortedPHIs) {
4182-
ValueIDNum ThisBlockValueNum =
4183-
MLiveIns[PHI->ParentBlock->BB.getNumber()][Loc.asU64()];
4178+
ValueIDNum ThisBlockValueNum = MLiveIns[PHI->ParentBlock->BB][Loc.asU64()];
41844179

41854180
// Are all these things actually defined?
41864181
for (auto &PHIIt : PHI->IncomingValues) {
@@ -4189,7 +4184,7 @@ std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
41894184
return std::nullopt;
41904185

41914186
ValueIDNum ValueToCheck;
4192-
const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB.getNumber()];
4187+
const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
41934188

41944189
auto VVal = ValidatedValues.find(PHIIt.first);
41954190
if (VVal == ValidatedValues.end()) {

llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,48 @@ using namespace llvm;
207207
/// Type for a table of values in a block.
208208
using ValueTable = SmallVector<ValueIDNum, 0>;
209209

210-
/// Type for a table-of-table-of-values, i.e., the collection of either
211-
/// live-in or live-out values for each block in the function.
212-
using FuncValueTable = SmallVector<ValueTable, 0>;
210+
/// A collection of ValueTables, one per BB in a function, with convenient
211+
/// accessor methods.
212+
struct FuncValueTable {
213+
FuncValueTable(int NumBBs, int NumLocs) {
214+
Storage.reserve(NumBBs);
215+
for (int i = 0; i != NumBBs; ++i)
216+
Storage.push_back(
217+
std::make_unique<ValueTable>(NumLocs, ValueIDNum::EmptyValue));
218+
}
219+
220+
/// Returns the ValueTable associated with MBB.
221+
ValueTable &operator[](const MachineBasicBlock &MBB) const {
222+
return (*this)[MBB.getNumber()];
223+
}
224+
225+
/// Returns the ValueTable associated with the MachineBasicBlock whose number
226+
/// is MBBNum.
227+
ValueTable &operator[](int MBBNum) const {
228+
auto &TablePtr = Storage[MBBNum];
229+
assert(TablePtr && "Trying to access a deleted table");
230+
return *TablePtr;
231+
}
232+
233+
/// Returns the ValueTable associated with the entry MachineBasicBlock.
234+
ValueTable &tableForEntryMBB() const { return (*this)[0]; }
235+
236+
/// Returns true if the ValueTable associated with MBB has not been freed.
237+
bool hasTableFor(MachineBasicBlock &MBB) const {
238+
return Storage[MBB.getNumber()] != nullptr;
239+
}
240+
241+
/// Frees the memory of the ValueTable associated with MBB.
242+
void ejectTableForBlock(const MachineBasicBlock &MBB) {
243+
Storage[MBB.getNumber()].reset();
244+
}
245+
246+
private:
247+
/// ValueTables are stored as unique_ptrs to allow for deallocation during
248+
/// LDV; this was measured to have a significant impact on compiler memory
249+
/// usage.
250+
SmallVector<std::unique_ptr<ValueTable>, 0> Storage;
251+
};
213252

214253
/// Thin wrapper around an integer -- designed to give more type safety to
215254
/// spill location numbers.

llvm/unittests/CodeGen/InstrRefLDVTest.cpp

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,7 @@ body: |
497497

498498
std::pair<FuncValueTable, FuncValueTable>
499499
allocValueTables(unsigned Blocks, unsigned Locs) {
500-
return {FuncValueTable(Blocks, ValueTable(Locs)),
501-
FuncValueTable(Blocks, ValueTable(Locs))};
500+
return {FuncValueTable(Blocks, Locs), FuncValueTable(Blocks, Locs)};
502501
}
503502
};
504503

@@ -917,8 +916,7 @@ TEST_F(InstrRefLDVTest, MLocSingleBlock) {
917916

918917
// Set up live-in and live-out tables for this function: two locations (we
919918
// add one later) in a single block.
920-
FuncValueTable MOutLocs, MInLocs;
921-
std::tie(MOutLocs, MInLocs) = allocValueTables(1, 2);
919+
auto [MOutLocs, MInLocs] = allocValueTables(1, 2);
922920

923921
// Transfer function: nothing.
924922
SmallVector<MLocTransferMap, 1> TransferFunc;
@@ -983,8 +981,7 @@ TEST_F(InstrRefLDVTest, MLocDiamondBlocks) {
983981
Register RAX = getRegByName("RAX");
984982
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
985983

986-
FuncValueTable MInLocs, MOutLocs;
987-
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
984+
auto [MInLocs, MOutLocs] = allocValueTables(4, 2);
988985

989986
// Transfer function: start with nothing.
990987
SmallVector<MLocTransferMap, 1> TransferFunc;
@@ -1137,8 +1134,7 @@ TEST_F(InstrRefLDVTest, MLocDiamondSpills) {
11371134
// There are other locations, for things like xmm0, which we're going to
11381135
// ignore here.
11391136

1140-
FuncValueTable MInLocs, MOutLocs;
1141-
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 11);
1137+
auto [MInLocs, MOutLocs] = allocValueTables(4, 11);
11421138

11431139
// Transfer function: start with nothing.
11441140
SmallVector<MLocTransferMap, 1> TransferFunc;
@@ -1199,8 +1195,7 @@ TEST_F(InstrRefLDVTest, MLocSimpleLoop) {
11991195
Register RAX = getRegByName("RAX");
12001196
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
12011197

1202-
FuncValueTable MInLocs, MOutLocs;
1203-
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
1198+
auto [MInLocs, MOutLocs] = allocValueTables(3, 2);
12041199

12051200
SmallVector<MLocTransferMap, 1> TransferFunc;
12061201
TransferFunc.resize(3);
@@ -1298,8 +1293,7 @@ TEST_F(InstrRefLDVTest, MLocNestedLoop) {
12981293
Register RAX = getRegByName("RAX");
12991294
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
13001295

1301-
FuncValueTable MInLocs, MOutLocs;
1302-
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
1296+
auto [MInLocs, MOutLocs] = allocValueTables(5, 2);
13031297

13041298
SmallVector<MLocTransferMap, 1> TransferFunc;
13051299
TransferFunc.resize(5);
@@ -1500,8 +1494,7 @@ TEST_F(InstrRefLDVTest, MLocNoDominatingLoop) {
15001494
Register RAX = getRegByName("RAX");
15011495
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
15021496

1503-
FuncValueTable MInLocs, MOutLocs;
1504-
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
1497+
auto [MInLocs, MOutLocs] = allocValueTables(5, 2);
15051498

15061499
SmallVector<MLocTransferMap, 1> TransferFunc;
15071500
TransferFunc.resize(5);
@@ -1656,8 +1649,7 @@ TEST_F(InstrRefLDVTest, MLocBadlyNestedLoops) {
16561649
Register RAX = getRegByName("RAX");
16571650
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
16581651

1659-
FuncValueTable MInLocs, MOutLocs;
1660-
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
1652+
auto [MInLocs, MOutLocs] = allocValueTables(5, 2);
16611653

16621654
SmallVector<MLocTransferMap, 1> TransferFunc;
16631655
TransferFunc.resize(5);
@@ -1789,8 +1781,7 @@ TEST_F(InstrRefLDVTest, pickVPHILocDiamond) {
17891781
Register RAX = getRegByName("RAX");
17901782
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
17911783

1792-
FuncValueTable MInLocs, MOutLocs;
1793-
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
1784+
auto [MInLocs, MOutLocs] = allocValueTables(4, 2);
17941785

17951786
initValueArray(MOutLocs, 4, 2);
17961787

@@ -1986,8 +1977,7 @@ TEST_F(InstrRefLDVTest, pickVPHILocLoops) {
19861977
Register RAX = getRegByName("RAX");
19871978
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
19881979

1989-
FuncValueTable MInLocs, MOutLocs;
1990-
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
1980+
auto [MInLocs, MOutLocs] = allocValueTables(3, 2);
19911981

19921982
initValueArray(MOutLocs, 3, 2);
19931983

@@ -2117,8 +2107,7 @@ TEST_F(InstrRefLDVTest, pickVPHILocBadlyNestedLoops) {
21172107
Register RBX = getRegByName("RBX");
21182108
LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX);
21192109

2120-
FuncValueTable MInLocs, MOutLocs;
2121-
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 3);
2110+
auto [MInLocs, MOutLocs] = allocValueTables(5, 3);
21222111

21232112
initValueArray(MOutLocs, 5, 3);
21242113

@@ -2635,8 +2624,7 @@ TEST_F(InstrRefLDVTest, VLocSingleBlock) {
26352624
ASSERT_TRUE(MTracker->getNumLocs() == 1);
26362625
LocIdx RspLoc(0);
26372626

2638-
FuncValueTable MInLocs, MOutLocs;
2639-
std::tie(MInLocs, MOutLocs) = allocValueTables(1, 2);
2627+
auto [MInLocs, MOutLocs] = allocValueTables(1, 2);
26402628

26412629
ValueIDNum LiveInRsp = ValueIDNum(0, 0, RspLoc);
26422630
DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp);
@@ -2699,8 +2687,7 @@ TEST_F(InstrRefLDVTest, VLocDiamondBlocks) {
26992687
DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax);
27002688
DbgOpID RspPHIInBlk3ID = addValueDbgOp(RspPHIInBlk3);
27012689

2702-
FuncValueTable MInLocs, MOutLocs;
2703-
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
2690+
auto [MInLocs, MOutLocs] = allocValueTables(4, 2);
27042691

27052692
initValueArray(MInLocs, 4, 2);
27062693
initValueArray(MOutLocs, 4, 2);
@@ -2921,8 +2908,7 @@ TEST_F(InstrRefLDVTest, VLocSimpleLoop) {
29212908
DbgOpID RspDefInBlk1ID = addValueDbgOp(RspDefInBlk1);
29222909
DbgOpID RaxPHIInBlk1ID = addValueDbgOp(RaxPHIInBlk1);
29232910

2924-
FuncValueTable MInLocs, MOutLocs;
2925-
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
2911+
auto [MInLocs, MOutLocs] = allocValueTables(3, 2);
29262912

29272913
initValueArray(MInLocs, 3, 2);
29282914
initValueArray(MOutLocs, 3, 2);
@@ -3200,8 +3186,7 @@ TEST_F(InstrRefLDVTest, VLocNestedLoop) {
32003186
DbgOpID RspPHIInBlk2ID = addValueDbgOp(RspPHIInBlk2);
32013187
DbgOpID RspDefInBlk2ID = addValueDbgOp(RspDefInBlk2);
32023188

3203-
FuncValueTable MInLocs, MOutLocs;
3204-
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
3189+
auto [MInLocs, MOutLocs] = allocValueTables(5, 2);
32053190

32063191
initValueArray(MInLocs, 5, 2);
32073192
initValueArray(MOutLocs, 5, 2);

0 commit comments

Comments
 (0)