@@ -137,16 +137,24 @@ using VarLocSet = CoalescingBitVector<uint64_t>;
137
137
// / Why encode a location /into/ the VarLocMap index? This makes it possible
138
138
// / to find the open VarLocs killed by a register def very quickly. This is a
139
139
// / performance-critical operation for LiveDebugValues.
140
- // /
141
- // / TODO: Consider adding reserved intervals for kinds of VarLocs other than
142
- // / RegisterKind, like SpillLocKind or EntryValueKind, to optimize iteration
143
- // / over open locations.
144
140
struct LocIndex {
145
141
uint32_t Location; // Physical registers live in the range [1;2^30) (see
146
142
// \ref MCRegister), so we have plenty of range left here
147
143
// to encode non-register locations.
148
144
uint32_t Index;
149
145
146
+ // / The first location greater than 0 that is not reserved for VarLocs of
147
+ // / kind RegisterKind.
148
+ static constexpr uint32_t kFirstInvalidRegLocation = 1 << 30 ;
149
+
150
+ // / A special location reserved for VarLocs of kind SpillLocKind.
151
+ static constexpr uint32_t kSpillLocation = kFirstInvalidRegLocation ;
152
+
153
+ // / A special location reserved for VarLocs of kind EntryValueBackupKind and
154
+ // / EntryValueCopyBackupKind.
155
+ static constexpr uint32_t kEntryValueBackupLocation =
156
+ kFirstInvalidRegLocation + 1 ;
157
+
150
158
LocIndex (uint32_t Location, uint32_t Index)
151
159
: Location(Location), Index(Index) {}
152
160
@@ -166,6 +174,14 @@ struct LocIndex {
166
174
static uint64_t rawIndexForReg (uint32_t Reg) {
167
175
return LocIndex (Reg, 0 ).getAsRawInteger ();
168
176
}
177
+
178
+ // / Return a range covering all set indices in the interval reserved for
179
+ // / \p Location in \p Set.
180
+ static auto indexRangeForLocation (const VarLocSet &Set, uint32_t Location) {
181
+ uint64_t Start = LocIndex (Location, 0 ).getAsRawInteger ();
182
+ uint64_t End = LocIndex (Location + 1 , 0 ).getAsRawInteger ();
183
+ return Set.half_open_range (Start, End);
184
+ }
169
185
};
170
186
171
187
class LiveDebugValues : public MachineFunctionPass {
@@ -211,6 +227,9 @@ class LiveDebugValues : public MachineFunctionPass {
211
227
bool operator ==(const SpillLoc &Other) const {
212
228
return SpillBase == Other.SpillBase && SpillOffset == Other.SpillOffset ;
213
229
}
230
+ bool operator !=(const SpillLoc &Other) const {
231
+ return !(*this == Other);
232
+ }
214
233
};
215
234
216
235
// / Identity of the variable at this location.
@@ -477,10 +496,27 @@ class LiveDebugValues : public MachineFunctionPass {
477
496
// / location.
478
497
SmallDenseMap<uint32_t , std::vector<VarLoc>> Loc2Vars;
479
498
499
+ // / Determine the 32-bit location reserved for \p VL, based on its kind.
500
+ static uint32_t getLocationForVar (const VarLoc &VL) {
501
+ switch (VL.Kind ) {
502
+ case VarLoc::RegisterKind:
503
+ assert ((VL.Loc .RegNo < LocIndex::kFirstInvalidRegLocation ) &&
504
+ " Physreg out of range?" );
505
+ return VL.Loc .RegNo ;
506
+ case VarLoc::SpillLocKind:
507
+ return LocIndex::kSpillLocation ;
508
+ case VarLoc::EntryValueBackupKind:
509
+ case VarLoc::EntryValueCopyBackupKind:
510
+ return LocIndex::kEntryValueBackupLocation ;
511
+ default :
512
+ return 0 ;
513
+ }
514
+ }
515
+
480
516
public:
481
517
// / Retrieve a unique LocIndex for \p VL.
482
518
LocIndex insert (const VarLoc &VL) {
483
- uint32_t Location = VL. isDescribedByReg ( );
519
+ uint32_t Location = getLocationForVar (VL );
484
520
uint32_t &Index = Var2Index[VL];
485
521
if (!Index) {
486
522
auto &Vars = Loc2Vars[Location];
@@ -577,6 +613,30 @@ class LiveDebugValues : public MachineFunctionPass {
577
613
" open ranges are inconsistent" );
578
614
return VarLocs.empty ();
579
615
}
616
+
617
+ // / Get an empty range of VarLoc IDs.
618
+ auto getEmptyVarLocRange () const {
619
+ return iterator_range<VarLocSet::const_iterator>(getVarLocs ().end (),
620
+ getVarLocs ().end ());
621
+ }
622
+
623
+ // / Get all set IDs for VarLocs of kind RegisterKind in \p Reg.
624
+ auto getRegisterVarLocs (Register Reg) const {
625
+ return LocIndex::indexRangeForLocation (getVarLocs (), Reg);
626
+ }
627
+
628
+ // / Get all set IDs for VarLocs of kind SpillLocKind.
629
+ auto getSpillVarLocs () const {
630
+ return LocIndex::indexRangeForLocation (getVarLocs (),
631
+ LocIndex::kSpillLocation );
632
+ }
633
+
634
+ // / Get all set IDs for VarLocs of kind EntryValueBackupKind or
635
+ // / EntryValueCopyBackupKind.
636
+ auto getEntryValueBackupVarLocs () const {
637
+ return LocIndex::indexRangeForLocation (
638
+ getVarLocs (), LocIndex::kEntryValueBackupLocation );
639
+ }
580
640
};
581
641
582
642
// / Collect all VarLoc IDs from \p CollectFrom for VarLocs of kind
@@ -821,7 +881,10 @@ void LiveDebugValues::getUsedRegs(const VarLocSet &CollectFrom,
821
881
// All register-based VarLocs are assigned indices greater than or equal to
822
882
// FirstRegIndex.
823
883
uint64_t FirstRegIndex = LocIndex::rawIndexForReg (1 );
824
- for (auto It = CollectFrom.find (FirstRegIndex), End = CollectFrom.end ();
884
+ uint64_t FirstInvalidIndex =
885
+ LocIndex::rawIndexForReg (LocIndex::kFirstInvalidRegLocation );
886
+ for (auto It = CollectFrom.find (FirstRegIndex),
887
+ End = CollectFrom.find (FirstInvalidIndex);
825
888
It != End;) {
826
889
// We found a VarLoc ID for a VarLoc that lives in a register. Figure out
827
890
// which register and add it to UsedRegs.
@@ -924,11 +987,8 @@ bool LiveDebugValues::removeEntryValue(const MachineInstr &MI,
924
987
}
925
988
926
989
if (TrySalvageEntryValue) {
927
- for (uint64_t ID : OpenRanges.getVarLocs ()) {
990
+ for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs ()) {
928
991
const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger (ID)];
929
- if (!VL.isEntryBackupLoc ())
930
- continue ;
931
-
932
992
if (VL.getEntryValueCopyBackupReg () == Reg &&
933
993
VL.MI .getOperand (0 ).getReg () == SrcRegOp->getReg ())
934
994
return false ;
@@ -1259,10 +1319,11 @@ void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI,
1259
1319
VarLocSet KillSet (Alloc);
1260
1320
if (isSpillInstruction (MI, MF)) {
1261
1321
Loc = extractSpillBaseRegAndOffset (MI);
1262
- for (uint64_t ID : OpenRanges.getVarLocs ()) {
1322
+ for (uint64_t ID : OpenRanges.getSpillVarLocs ()) {
1263
1323
LocIndex Idx = LocIndex::fromRawInteger (ID);
1264
1324
const VarLoc &VL = VarLocIDs[Idx];
1265
- if (VL.Kind == VarLoc::SpillLocKind && VL.Loc .SpillLocation == *Loc) {
1325
+ assert (VL.Kind == VarLoc::SpillLocKind && " Broken VarLocSet?" );
1326
+ if (VL.Loc .SpillLocation == *Loc) {
1266
1327
// This location is overwritten by the current instruction -- terminate
1267
1328
// the open range, and insert an explicit DBG_VALUE $noreg.
1268
1329
//
@@ -1298,21 +1359,31 @@ void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI,
1298
1359
<< " \n " );
1299
1360
}
1300
1361
// Check if the register or spill location is the location of a debug value.
1301
- for (uint64_t ID : OpenRanges.getVarLocs ()) {
1362
+ auto TransferCandidates = OpenRanges.getEmptyVarLocRange ();
1363
+ if (TKind == TransferKind::TransferSpill)
1364
+ TransferCandidates = OpenRanges.getRegisterVarLocs (Reg);
1365
+ else if (TKind == TransferKind::TransferRestore)
1366
+ TransferCandidates = OpenRanges.getSpillVarLocs ();
1367
+ for (uint64_t ID : TransferCandidates) {
1302
1368
LocIndex Idx = LocIndex::fromRawInteger (ID);
1303
1369
const VarLoc &VL = VarLocIDs[Idx];
1304
- if (TKind == TransferKind::TransferSpill && VL.isDescribedByReg () == Reg) {
1370
+ if (TKind == TransferKind::TransferSpill) {
1371
+ assert (VL.isDescribedByReg () == Reg && " Broken VarLocSet?" );
1305
1372
LLVM_DEBUG (dbgs () << " Spilling Register " << printReg (Reg, TRI) << ' ('
1306
1373
<< VL.Var .getVariable ()->getName () << " )\n " );
1307
- } else if (TKind == TransferKind::TransferRestore &&
1308
- VL.Kind == VarLoc::SpillLocKind &&
1309
- VL.Loc .SpillLocation == *Loc) {
1374
+ } else {
1375
+ assert (TKind == TransferKind::TransferRestore &&
1376
+ VL.Kind == VarLoc::SpillLocKind && " Broken VarLocSet?" );
1377
+ if (VL.Loc .SpillLocation != *Loc)
1378
+ // The spill location is not the location of a debug value.
1379
+ continue ;
1310
1380
LLVM_DEBUG (dbgs () << " Restoring Register " << printReg (Reg, TRI) << ' ('
1311
1381
<< VL.Var .getVariable ()->getName () << " )\n " );
1312
- } else
1313
- continue ;
1382
+ }
1314
1383
insertTransferDebugPair (MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
1315
1384
Reg);
1385
+ // FIXME: A comment should explain why it's correct to return early here,
1386
+ // if that is in fact correct.
1316
1387
return ;
1317
1388
}
1318
1389
}
@@ -1356,7 +1427,7 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
1356
1427
// a parameter describing only a moving of the value around, rather then
1357
1428
// modifying it, we are still able to use the entry value if needed.
1358
1429
if (isRegOtherThanSPAndFP (*DestRegOp, MI, TRI)) {
1359
- for (uint64_t ID : OpenRanges.getVarLocs ()) {
1430
+ for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs ()) {
1360
1431
LocIndex Idx = LocIndex::fromRawInteger (ID);
1361
1432
const VarLoc &VL = VarLocIDs[Idx];
1362
1433
if (VL.getEntryValueBackupReg () == SrcReg) {
@@ -1378,13 +1449,14 @@ void LiveDebugValues::transferRegisterCopy(MachineInstr &MI,
1378
1449
if (!SrcRegOp->isKill ())
1379
1450
return ;
1380
1451
1381
- for (uint64_t ID : OpenRanges.getVarLocs ( )) {
1452
+ for (uint64_t ID : OpenRanges.getRegisterVarLocs (SrcReg )) {
1382
1453
LocIndex Idx = LocIndex::fromRawInteger (ID);
1383
- if (VarLocIDs[Idx].isDescribedByReg () == SrcReg) {
1384
- insertTransferDebugPair (MI, OpenRanges, Transfers, VarLocIDs, Idx,
1385
- TransferKind::TransferCopy, DestReg);
1386
- return ;
1387
- }
1454
+ assert (VarLocIDs[Idx].isDescribedByReg () == SrcReg && " Broken VarLocSet?" );
1455
+ insertTransferDebugPair (MI, OpenRanges, Transfers, VarLocIDs, Idx,
1456
+ TransferKind::TransferCopy, DestReg);
1457
+ // FIXME: A comment should explain why it's correct to return early here,
1458
+ // if that is in fact correct.
1459
+ return ;
1388
1460
}
1389
1461
}
1390
1462
0 commit comments