LLVM: lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
104#include "llvm/Config/llvm-config.h"
117#include
118#include
119#include
120#include
121#include
122#include
123#include
124#include
125#include
126
129#include
130
131using namespace llvm;
133
134
135#undef DEBUG_TYPE
136#define DEBUG_TYPE "livedebugvalues"
137
138
139
141 cl::desc("Act like old LiveDebugValues did"),
143
144
145
146
147
148
149
150
151
152
155 cl::desc("livedebugvalues-stack-ws-limit"),
157
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
177public:
180
181
182
187
188
189
190
198
199
200
201
219
220
222
223
224
225
226
228
229
230
231
233
234
235
236
238
239
241
242
243
244
256
257
258
260
261
262
263
265
268
276 TLI = MF.getSubtarget().getTargetLowering();
278 }
279
281 unsigned Reg = MTracker->LocIdxToLocID[L];
282 if (Reg >= MTracker->NumRegs)
283 return false;
286 return true;
287 return false;
288 };
289
290
291
292
293
294
302
304 unsigned Location : 24;
305 unsigned Quality : 8;
306
307 public:
310 : Location(L.asU64()), Quality(static_cast<unsigned>(Q)) {}
312 if (!Quality)
314 return LocIdx(Location);
315 }
319 };
320
321 using ValueLocPair = std::pair<ValueIDNum, LocationAndQuality>;
322
326 };
327
328
329
330 std::optional
332 if (L.isIllegal())
333 return std::nullopt;
335 return std::nullopt;
339 return std::nullopt;
343 return std::nullopt;
345 }
346
347
348
349
350
351
352
353
354
360 bool IsValueValid = true;
361 unsigned LastUseBeforeDef = 0;
362 bool DbgLocAvailableAndIsEntryVal = false;
363
364
365
366
367
368
369
370
371
372
373
377 if (ID.isUndef()) {
378 IsValueValid = false;
379 break;
380 }
381 if (ID.isConst()) {
383 continue;
384 }
385
386
387
390 auto ValuesPreferredLoc =
392
393
394 assert(ValuesPreferredLoc != ValueToLoc.end() &&
395 ValuesPreferredLoc->first == Num);
396
397 if (ValuesPreferredLoc->second.isIllegal()) {
398
399
400
401
402 if (Num.getBlock() == (unsigned)MBB.getNumber() && !Num.isPHI()) {
403 LastUseBeforeDef = std::max(LastUseBeforeDef,
404 static_cast<unsigned>(Num.getInst()));
405 continue;
406 }
408 IsValueValid = false;
409 break;
410 }
411
412
413
414 LocIdx M = ValuesPreferredLoc->second.getLoc();
416 if (Value.Properties.DIExpr->isEntryValue())
417 DbgLocAvailableAndIsEntryVal = true;
418 }
419
420
421
422 if (!IsValueValid)
423 return;
424
425
426 if (LastUseBeforeDef) {
428 return;
429 }
430
431 auto &[Var, DILoc] = DVMap.lookupDVID(VarID);
433 std::make_pair(VarID, &*MTracker->emitLoc(ResolvedDbgOps, Var, DILoc,
434 Value.Properties)));
435
436
437
438 if (DbgLocAvailableAndIsEntryVal)
439 return;
440
441
442
444 if (.IsConst)
447 auto Result = ActiveVLocs.insert(std::make_pair(VarID, NewValue));
448 if (!Result.second)
449 Result.first->second = NewValue;
450 }
451
452
453
454
455
456
457
458 void
460 const SmallVectorImpl<std::pair<DebugVariableID, DbgValue>> &VLocs,
461 unsigned NumLocs) {
465 VarLocs.reserve(NumLocs);
468
469
470
472
473
474
475 for (const auto &VLoc : VLocs)
477 for (DbgOpID OpID : VLoc.second.getDbgOpIDs())
478 if (!OpID.ID.IsConst)
481
485
486
487
488
489 for (auto Location : MTracker->locations()) {
490 LocIdx Idx = Location.Idx;
493 continue;
495
496
499 if (VIt == ValueToLoc.end() || VIt->first != VNum)
500 continue;
501
502 auto &Previous = VIt->second;
503
504
505 std::optional ReplacementQuality =
507 if (ReplacementQuality)
509 }
510
511
512 for (const auto &Var : VLocs) {
513 loadVarInloc(MBB, DbgOpStore, ValueToLoc, Var.first, Var.second);
514 }
516 }
517
518
519
526
527
528
529
530
534 return;
535
536
537
539
540
541
542 for (auto &Use : MIt->second) {
544 continue;
545
547 assert(.isUndef() && "UseBeforeDef erroneously created for a "
548 "DbgValue with undef values.");
549 if (Op.IsConst)
550 continue;
551
553 }
554 }
555
556
557 if (ValueToLoc.empty())
558 return;
559
560
561 for (auto Location : MTracker->locations()) {
562 LocIdx Idx = Location.Idx;
564
565
566 auto VIt = ValueToLoc.find(LocValueID);
567 if (VIt == ValueToLoc.end())
568 continue;
569
570 auto &Previous = VIt->second;
571
572
573 std::optional ReplacementQuality =
575 if (ReplacementQuality)
577 }
578
579
580
581 for (auto &Use : MIt->second) {
583 continue;
584
586
588 if (Op.IsConst) {
590 continue;
591 }
592 LocIdx NewLoc = ValueToLoc.find(Op.ID)->second.getLoc();
594 break;
596 }
597
598
599
600
601 if (DbgOps.size() != Use.Values.size())
602 continue;
603
604
605 auto &[Var, DILoc] = DVMap.lookupDVID(Use.VarID);
607 Use.VarID, MTracker->emitLoc(DbgOps, Var, DILoc, Use.Properties)));
608 }
610 }
611
612
615 return;
616
617
619 if (MBB && Pos == MBB->begin())
620 BundleStart = MBB->instr_begin();
621 else
623
626 }
627
631 return false;
632
634 return false;
635
637 return false;
638
639 return true;
640 }
641
643
645 return false;
646
647
649 return false;
650
651 Register SP = TLI->getStackPointerRegisterToSaveRestore();
654 return Reg != SP && Reg != FP;
655 }
656
660
661
663 return false;
664
666
667
669
670
671 auto NonVariadicExpression =
673 if (!NonVariadicExpression)
674 return false;
675 DIExpr = *NonVariadicExpression;
676 }
677
678 auto &[Var, DILoc] = DVMap.lookupDVID(VarID);
679
680
681
687 return true;
688 }
689
690
692 return false;
693
694
696 return false;
697
698
705 return true;
706 }
707
708
710 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
711 MI.getDebugLoc()->getInlinedAt());
714
715
716 if (MI.isUndefDebugValue() || MI.getDebugExpression()->isEntryValue() ||
718 [](const MachineOperand &MO) { return !MO.isReg(); })) {
721 for (LocIdx Loc : It->second.loc_indices())
724 }
725
727 return;
728 }
729
732 if (MO.isReg()) {
733
737 } else {
739 }
740 }
741
743 }
744
745
746
747
750 DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
751 MI.getDebugLoc()->getInlinedAt());
753
755
756
759 for (LocIdx Loc : It->second.loc_indices())
761 }
762
763
764 if (NewLocs.empty()) {
767 return;
768 }
769
772 if (Op.IsConst)
773 continue;
774
776
777
778
779
784 for (LocIdx Loc : LostVLocIt->second.loc_indices()) {
785
786
787 if (Loc == NewLoc)
788 continue;
790 }
791 }
793 }
794 for (const auto &LostMLoc : LostMLocs)
795 ActiveMLocs[LostMLoc.first].erase(LostMLoc.second);
796 LostMLocs.clear();
800 }
801
803 }
804
808 } else {
809 It->second.Ops.assign(NewLocs);
810 It->second.Properties = Properties;
811 }
812 }
813
814
815
816
817
819 bool MakeUndef = true) {
820 auto ActiveMLocIt = ActiveMLocs.find(MLoc);
822 return;
823
824
826 clobberMloc(MLoc, OldValue, Pos, MakeUndef);
827 }
828
829
830
833 auto ActiveMLocIt = ActiveMLocs.find(MLoc);
835 return;
836
838
839
840
841 std::optional NewLoc;
843 if (Loc.Value == OldValue)
844 NewLoc = Loc.Idx;
845
846
847
848 if (!NewLoc && !MakeUndef) {
849
853 }
855 return;
856 }
857
858
860
861
865
866
867
868 const DbgValueProperties &Properties = ActiveVLocIt->second.Properties;
869
870
871
872
874 if (NewLoc) {
877
878 DbgOps.insert(DbgOps.begin(), ActiveVLocIt->second.Ops.size(),
880 replace_copy(ActiveVLocIt->second.Ops, DbgOps.begin(), OldOp, NewOp);
881 }
882
883 auto &[Var, DILoc] = DVMap.lookupDVID(VarID);
885 VarID, &*MTracker->emitLoc(DbgOps, Var, DILoc, Properties)));
886
887
888
889 if (!NewLoc) {
890 for (LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
891 if (Loc != MLoc)
893 }
895 } else {
896 ActiveVLocIt->second.Ops = DbgOps;
898 }
899 }
900
901
902
903 for (auto &LocVarIt : LostMLocs) {
904 auto LostMLocIt = ActiveMLocs.find(LocVarIt.first);
906 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
907 "entries?");
908 LostMLocIt->second.erase(LocVarIt.second);
909 }
910
911
912
913 if (NewLoc)
914 VarLocs[NewLoc->asU64()] = OldValue;
915
917
918
919 ActiveMLocIt->second.clear();
920 if (!NewMLocs.empty())
921 ActiveMLocs[*NewLoc].insert_range(NewMLocs);
922 }
923
924
925
926
928
929
931 return;
932
933
934
935
936
938 ActiveMLocs[Dst].insert_range(MovingVars);
940
941
947
948
950
951 auto &[Var, DILoc] = DVMap.lookupDVID(VarID);
953 ActiveVLocIt->second.Properties);
955 }
958
959
960
963 }
964
971 auto MIB = BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE));
972 MIB.add(MO);
974 MIB.addImm(0);
975 else
976 MIB.addReg(0);
978 MIB.addMetadata(Properties.DIExpr);
979 return MIB;
980 }
981};
982
983
984
985
986
989
990#ifndef NDEBUG
1001 } else if (()) {
1003 }
1004}
1006 if (!OpStore) {
1007 dbgs() << "ID(" << asU32() << ")";
1008 } else {
1009 OpStore->find(*this).dump(MTrack);
1010 }
1011}
1019 else
1020 dbgs() << "Def(";
1021 for (unsigned Idx = 0; Idx < getDbgOpIDs().size(); ++Idx) {
1023 if (Idx != 0)
1024 dbgs() << ",";
1025 }
1026 dbgs() << ")";
1027 }
1029 dbgs() << " indir";
1032}
1033#endif
1034
1044
1045
1046
1047
1048 Register SP = TLI.getStackPointerRegisterToSaveRestore();
1049 if (SP) {
1052
1055 }
1056
1057
1058
1066
1067
1068
1069
1070 for (unsigned int I = 1; I < TRI.getNumSubRegIndices(); ++I) {
1071 unsigned Size = TRI.getSubRegIdxSize(I);
1072 unsigned Offs = TRI.getSubRegIdxOffset(I);
1074
1075
1076
1077 if (Size > 60000 || Offs > 60000)
1078 continue;
1079
1081 }
1082
1083
1085 unsigned Size = TRI.getRegSizeInBits(*RC);
1086
1087
1088
1089
1090 if (Size > 512)
1091 continue;
1092
1095 }
1096
1099
1101}
1102
1108
1109
1111
1112 for (const auto &MaskPair : reverse(Masks)) {
1113 if (MaskPair.first->clobbersPhysReg(ID)) {
1114
1115 ValNum = {CurBB, MaskPair.second, NewIdx};
1116 break;
1117 }
1118 }
1119
1122 return NewIdx;
1123}
1124
1126 unsigned InstID) {
1127
1128
1129
1130 for (auto Location : locations()) {
1132
1135 }
1136 Masks.push_back(std::make_pair(MO, InstID));
1137}
1138
1141
1142 if (SpillID.id() == 0) {
1143
1144
1146 return std::nullopt;
1147
1148
1149
1151 for (unsigned StackIdx = 0; StackIdx < NumSlotIdxes; ++StackIdx) {
1158
1159
1161 }
1162 }
1163 return SpillID;
1164}
1165
1172 return Twine("slot ")
1176 } else {
1177 return TRI.getRegAsmName(ID).str();
1178 }
1179}
1180
1183 return Num.asString(DefName);
1184}
1185
1186#ifndef NDEBUG
1188 for (auto Location : locations()) {
1189 std::string MLocName = LocIdxToName(Location.Value.getLoc());
1190 std::string DefName = Location.Value.asString(MLocName);
1191 dbgs() << LocIdxToName(Location.Idx) << " --> " << DefName << "\n";
1192 }
1193}
1194
1196 for (auto Location : locations()) {
1197 std::string foo = LocIdxToName(Location.Idx);
1198 dbgs() << "Idx " << Location.Idx.asU64() << " " << foo << "\n";
1199 }
1200}
1201#endif
1202
1208
1210 ? TII.get(TargetOpcode::DBG_VALUE_LIST)
1211 : TII.get(TargetOpcode::DBG_VALUE);
1212
1213#ifdef EXPENSIVE_CHECKS
1216 return Op.IsConst || .Loc.isIllegal();
1217 }) &&
1218 "Did not expect illegal ops in DbgOps.");
1221 "Expected to have either one DbgOp per MI LocationOp, or none.");
1222#endif
1223
1224 auto GetRegOp = [](unsigned Reg) -> MachineOperand {
1226 Reg, false, false,
1227 false, false,
1228 false, false,
1229 0, true);
1230 };
1231
1233
1234 auto EmitUndef = [&]() {
1239 };
1240
1241
1242
1243 if (DbgOps.empty())
1244 return EmitUndef();
1245
1246 bool Indirect = Properties.Indirect;
1247
1249
1251
1252
1253
1254
1255 for (size_t Idx = 0; Idx < Properties.getLocationOpCount(); ++Idx) {
1257
1258 if (Op.IsConst) {
1260 continue;
1261 }
1262
1268 unsigned short Offset = StackIdx.second;
1269
1270
1271
1272
1273
1274
1275
1276
1279 unsigned Base = Spill.SpillBase;
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295 bool UseDerefSize = false;
1297 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1298 if (auto Fragment = Var.getFragment()) {
1299 unsigned VariableSizeInBits = Fragment->SizeInBits;
1300 if (VariableSizeInBits != ValueSizeInBits || Expr->isComplex())
1301 UseDerefSize = true;
1303 if (*Size != ValueSizeInBits) {
1304 UseDerefSize = true;
1305 }
1306 }
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326 if (ValueSizeInBits > MF.getTarget().getPointerSizeInBits(0))
1327 UseDerefSize = false;
1328
1330 TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps);
1331 bool StackValue = false;
1332
1334
1335
1336
1338 OffsetOps.push_back(dwarf::DW_OP_deref);
1340
1341
1342
1343
1344
1345 OffsetOps.push_back(dwarf::DW_OP_deref_size);
1346 OffsetOps.push_back(DerefSizeInBytes);
1347 StackValue = true;
1349
1350
1351 OffsetOps.push_back(dwarf::DW_OP_deref);
1352 } else {
1353
1354
1355
1356 Indirect = true;
1357 }
1358
1361 } else {
1362
1363
1364 return EmitUndef();
1365 }
1366 } else {
1367
1369 }
1370 }
1371
1373}
1374
1375
1377
1379 unsigned Reg = MTracker->LocIdxToLocID[L];
1381}
1384 if (CalleeSavedRegs.test((*RAI).id()))
1385 return true;
1386 return false;
1387}
1388
1389
1390
1391
1392
1393#ifndef NDEBUG
1394
1395
1396#endif
1397
1398std::optional
1399InstrRefBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) {
1400 assert(MI.hasOneMemOperand() &&
1401 "Spill instruction does not have exactly one memory operand?");
1402 auto MMOI = MI.memoperands_begin();
1405 "Inconsistent memory operand in spill instruction");
1411}
1412
1413std::optional
1415 std::optional SpillLoc = extractSpillBaseRegAndOffset(MI);
1417 return std::nullopt;
1418
1419
1420
1421
1422
1423 auto *MemOperand = *MI.memoperands_begin();
1424 LocationSize SizeInBits = MemOperand->getSizeInBits();
1425 assert(SizeInBits.hasValue() && "Expected to find a valid size!");
1426
1427
1428 auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.getValue(), 0});
1429 if (IdxIt == MTracker->StackSlotIdxes.end())
1430
1431
1432 return std::nullopt;
1433
1434 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillLoc, IdxIt->second);
1435 return MTracker->getSpillMLoc(SpillID);
1436}
1437
1438
1439
1440bool InstrRefBasedLDV::transferDebugValue(const MachineInstr &MI) {
1441 if (.isDebugValue())
1442 return false;
1443
1444 assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
1445 "Expected inlined-at fields to agree");
1446
1447
1448
1450 if (Scope == nullptr)
1451 return true;
1452
1453
1454
1456 if (MO.isReg() && MO.getReg() != 0)
1457 (void)MTracker->readReg(MO.getReg());
1458
1459
1460
1461
1462 if (VTracker) {
1464
1465
1466 if (.isUndefDebugValue()) {
1468
1469
1470 if (MO.isReg()) {
1472 } else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1474 } else {
1476 }
1477 }
1478 }
1479 VTracker->defVar(MI, DbgValueProperties(MI), DebugOps);
1480 }
1481
1482
1483
1484 if (TTracker)
1485 TTracker->redefVar(MI);
1486 return true;
1487}
1488
1489std::optional InstrRefBasedLDV::getValueForInstrRef(
1492
1493
1494
1495
1496 const MachineFunction &MF = *MI.getParent()->getParent();
1497
1498
1499 auto SoughtSub =
1500 MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
1501
1502 SmallVector<unsigned, 4> SeenSubregs;
1505 LowerBoundIt->Src == SoughtSub.Src) {
1506 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1507 SoughtSub.Src = LowerBoundIt->Dest;
1508 if (unsigned Subreg = LowerBoundIt->Subreg)
1509 SeenSubregs.push_back(Subreg);
1511 }
1512
1513
1514
1515 std::optional NewID;
1516
1517
1518
1519 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1521 if (InstrIt != DebugInstrNumToInstr.end()) {
1522 const MachineInstr &TargetInstr = *InstrIt->second.first;
1524
1525
1526
1530 if (L)
1531 NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
1533
1534
1535
1536
1537
1539 const MachineOperand &MO = TargetInstr.getOperand(OpNo);
1540
1542 unsigned LocID = MTracker->getLocID(MO.getReg());
1543 LocIdx L = MTracker->LocIDToLocIdx[LocID];
1544 NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
1545 }
1546 }
1547
1548 if (!NewID) {
1550 { dbgs() << "Seen instruction reference to illegal operand\n"; });
1551 }
1552 }
1553
1554 } else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
1555
1556
1557 assert(MLiveOuts && MLiveIns);
1558 NewID = resolveDbgPHIs(*MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1559 MI, InstNo);
1560 }
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571 if (NewID && !SeenSubregs.empty()) {
1572 unsigned Offset = 0;
1573 unsigned Size = 0;
1574
1575
1576
1577
1578
1579 for (unsigned Subreg : reverse(SeenSubregs)) {
1580 unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
1581 unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
1582 Offset += ThisOffset;
1583 Size = (Size == 0) ? ThisSize : std::min(Size, ThisSize);
1584 }
1585
1586
1587
1588
1589
1590 LocIdx L = NewID->getLoc();
1591 if (NewID && !MTracker->isSpill(L)) {
1592
1593
1595 const TargetRegisterClass *TRC = nullptr;
1596 for (const auto *TRCI : TRI->regclasses())
1597 if (TRCI->contains(Reg))
1598 TRC = TRCI;
1599 assert(TRC && "Couldn't find target register class?");
1600
1601
1602
1603 unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
1604 if (Size != MainRegSize || Offset) {
1605
1607 for (MCRegister SR : TRI->subregs(Reg)) {
1608 unsigned Subreg = TRI->getSubRegIndex(Reg, SR);
1609 unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
1610 unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
1611 if (SubregSize == Size && SubregOffset == Offset) {
1612 NewReg = SR;
1613 break;
1614 }
1615 }
1616
1617
1618 if (!NewReg) {
1619 NewID = std::nullopt;
1620 } else {
1621
1622
1623 LocIdx NewLoc =
1624 MTracker->lookupOrTrackRegister(MTracker->getLocID(NewReg));
1625 NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1626 }
1627 }
1628 } else {
1629
1630 NewID = std::nullopt;
1631 }
1632 }
1633
1634 return NewID;
1635}
1636
1637bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI,
1640 if (.isDebugRef())
1641 return false;
1642
1643
1644
1645 if (!VTracker && !TTracker)
1646 return false;
1647
1648 const DILocalVariable *Var = MI.getDebugVariable();
1649 const DIExpression *Expr = MI.getDebugExpression();
1650 const DILocation *DebugLoc = MI.getDebugLoc();
1651 const DILocation *InlinedAt = DebugLoc->getInlinedAt();
1653 "Expected inlined-at fields to agree");
1654
1655 DebugVariable V(Var, Expr, InlinedAt);
1656
1657 auto *Scope = LS.findLexicalScope(MI.getDebugLoc().get());
1658 if (Scope == nullptr)
1659 return true;
1660
1662 for (const MachineOperand &MO : MI.debug_operands()) {
1664 assert(!MO.isReg() && "DBG_INSTR_REF should not contain registers");
1665 DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO));
1667 continue;
1668 }
1669
1672
1673
1674
1675 std::optional NewID =
1676 getValueForInstrRef(InstNo, OpNo, MI, MLiveOuts, MLiveIns);
1677
1678
1679 if (NewID) {
1680 DbgOpIDs.push_back(DbgOpStore.insert(*NewID));
1681 } else {
1682 DbgOpIDs.clear();
1683 break;
1684 }
1685 }
1686
1687
1688
1689
1690
1691 DbgValueProperties Properties(Expr, false, true);
1692 if (VTracker)
1693 VTracker->defVar(MI, Properties, DbgOpIDs);
1694
1695
1696
1697 if (!TTracker)
1698 return true;
1699
1700
1702 for (DbgOpID OpID : DbgOpIDs) {
1703 DbgOps.push_back(DbgOpStore.find(OpID));
1704 }
1705
1706
1707
1708 SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs;
1710
1711
1712 for (const DbgOp &Op : DbgOps) {
1713 if (.IsConst)
1716 }
1717
1718 for (auto Location : MTracker->locations()) {
1720 ValueIDNum ID = MTracker->readMLoc(CurL);
1721 auto ValueToFindIt = find(ValuesToFind, ID);
1722 if (ValueToFindIt == ValuesToFind.end())
1723 continue;
1724 auto &Previous = FoundLocs.find(ID)->second;
1725
1726
1727 std::optionalTransferTracker::LocationQuality ReplacementQuality =
1728 TTracker->getLocQualityIfBetter(CurL, Previous.getQuality());
1729 if (ReplacementQuality) {
1730 Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality);
1731 if (Previous.isBest()) {
1732 ValuesToFind.erase(ValueToFindIt);
1733 if (ValuesToFind.empty())
1734 break;
1735 }
1736 }
1737 }
1738
1740 for (const DbgOp &DbgOp : DbgOps) {
1741 if (DbgOp.IsConst) {
1743 continue;
1744 }
1745 LocIdx FoundLoc = FoundLocs.find(DbgOp.ID)->second.getLoc();
1747 NewLocs.clear();
1748 break;
1749 }
1751 }
1752
1753 TTracker->redefVar(MI, Properties, NewLocs);
1754
1755
1756
1757 if (!DbgOps.empty() && NewLocs.empty()) {
1758 bool IsValidUseBeforeDef = true;
1759 uint64_t LastUseBeforeDef = 0;
1760 for (auto ValueLoc : FoundLocs) {
1761 ValueIDNum NewID = ValueLoc.first;
1762 LocIdx FoundLoc = ValueLoc.second.getLoc();
1764 continue;
1765
1766
1767 if (NewID.getBlock() != CurBB || NewID.getInst() <= CurInst) {
1768 IsValidUseBeforeDef = false;
1769 break;
1770 }
1771 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.getInst());
1772 }
1773 if (IsValidUseBeforeDef) {
1774 DebugVariableID VID = DVMap.insertDVID(V, MI.getDebugLoc().get());
1775 TTracker->addUseBeforeDef(VID, {MI.getDebugExpression(), false, true},
1776 DbgOps, LastUseBeforeDef);
1777 }
1778 }
1779
1780
1781
1782
1783
1784 MachineInstr *DbgMI =
1785 MTracker->emitLoc(NewLocs, V, MI.getDebugLoc().get(), Properties);
1787
1788 TTracker->PendingDbgValues.push_back(std::make_pair(ID, DbgMI));
1789 TTracker->flushDbgValues(MI.getIterator(), nullptr);
1790 return true;
1791}
1792
1793bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) {
1794 if (.isDebugPHI())
1795 return false;
1796
1797
1798 if (VTracker || TTracker)
1799 return true;
1800
1801
1802
1803 const MachineOperand &MO = MI.getOperand(0);
1804 unsigned InstrNum = MI.getOperand(1).getImm();
1805
1806 auto EmitBadPHI = [this, &MI, InstrNum]() -> bool {
1807
1808
1809
1810
1811 DebugPHINumToValue.push_back(
1812 {InstrNum, MI.getParent(), std::nullopt, std::nullopt});
1813 return true;
1814 };
1815
1817
1818
1820 ValueIDNum Num = MTracker->readReg(Reg);
1821 auto PHIRec = DebugPHIRecord(
1822 {InstrNum, MI.getParent(), Num,
1823 MTracker->lookupOrTrackRegister(MTracker->getLocID(Reg))});
1824 DebugPHINumToValue.push_back(PHIRec);
1825
1826
1827 for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
1828 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
1829 } else if (MO.isFI()) {
1830
1831 unsigned FI = MO.getIndex();
1832
1833
1834
1835 if (MFI->isDeadObjectIndex(FI))
1836 return EmitBadPHI();
1837
1838
1840 StackOffset Offs = TFI->getFrameIndexReference(*MI.getMF(), FI, Base);
1841 SpillLoc SL = {Base, Offs};
1842 std::optional SpillNo = MTracker->getOrTrackSpillLoc(SL);
1843
1844
1845
1846 if (!SpillNo)
1847 return EmitBadPHI();
1848
1849
1850 assert(MI.getNumOperands() == 3 && "Stack DBG_PHI with no size?");
1851 unsigned slotBitSize = MI.getOperand(2).getImm();
1852
1853 unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
1854 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
1855 ValueIDNum Result = MTracker->readMLoc(SpillLoc);
1856
1857
1858 auto DbgPHI = DebugPHIRecord({InstrNum, MI.getParent(), Result, SpillLoc});
1859 DebugPHINumToValue.push_back(DbgPHI);
1860 } else {
1861
1862
1863
1864
1866 { dbgs() << "Seen DBG_PHI with unrecognised operand format\n"; });
1867 return EmitBadPHI();
1868 }
1869
1870 return true;
1871}
1872
1873void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
1874
1875
1876 if (MI.isImplicitDef()) {
1877
1878
1879
1880
1881 ValueIDNum Num = MTracker->readReg(MI.getOperand(0).getReg());
1882
1883 if (Num.getLoc() != 0)
1884 return;
1885
1886 } else if (MI.isMetaInstruction())
1887 return;
1888
1889
1890
1891
1892
1893
1894 bool CallChangesSP = false;
1895 if (AdjustsStackInCalls && MI.isCall() && MI.getOperand(0).isSymbol() &&
1896 !strcmp(MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
1897 CallChangesSP = true;
1898
1899
1900
1901 auto IgnoreSPAlias = [this, &MI, CallChangesSP](Register R) -> bool {
1902 if (CallChangesSP)
1903 return false;
1904 return MI.isCall() && MTracker->SPAliases.count(R);
1905 };
1906
1907
1908
1909
1910 SmallSet<uint32_t, 32> DeadRegs;
1911 SmallVector<const uint32_t *, 4> RegMasks;
1913 for (const MachineOperand &MO : MI.operands()) {
1914
1916 !IgnoreSPAlias(MO.getReg())) {
1917
1918 for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
1919
1920 DeadRegs.insert((*RAI).id());
1924 }
1925 }
1926
1927
1928 for (uint32_t DeadReg : DeadRegs)
1929 MTracker->defReg(DeadReg, CurBB, CurInst);
1930
1931 for (const auto *MO : RegMaskPtrs)
1932 MTracker->writeRegMask(MO, CurBB, CurInst);
1933
1934
1936 if (std::optional SpillNo =
1937 extractSpillBaseRegAndOffset(MI)) {
1938 for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) {
1939 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I);
1940 LocIdx L = MTracker->getSpillMLoc(SpillID);
1941 MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
1942 }
1943 }
1944 }
1945
1946 if (!TTracker)
1947 return;
1948
1949
1950
1951
1952
1953
1954 for (MCRegister DeadReg : DeadRegs) {
1955 LocIdx Loc = MTracker->lookupOrTrackRegister(MTracker->getLocID(DeadReg));
1956 TTracker->clobberMloc(Loc, MI.getIterator(), false);
1957 }
1958
1959
1960
1961 if (!RegMaskPtrs.empty()) {
1962 for (auto L : MTracker->locations()) {
1963
1964 if (MTracker->isSpill(L.Idx))
1965 continue;
1966
1967 Register Reg = MTracker->LocIdxToLocID[L.Idx];
1968 if (IgnoreSPAlias(Reg))
1969 continue;
1970
1971 for (const auto *MO : RegMaskPtrs)
1973 TTracker->clobberMloc(L.Idx, MI.getIterator(), false);
1974 }
1975 }
1976
1977
1979 if (std::optional SpillNo =
1980 extractSpillBaseRegAndOffset(MI)) {
1981 for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) {
1982 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I);
1983 LocIdx L = MTracker->getSpillMLoc(SpillID);
1984 TTracker->clobberMloc(L, MI.getIterator(), true);
1985 }
1986 }
1987 }
1988}
1989
1990void InstrRefBasedLDV::performCopy(Register SrcRegNum, Register DstRegNum) {
1991
1992 for (MCRegAliasIterator RAI(DstRegNum, TRI, true); RAI.isValid(); ++RAI)
1993 MTracker->defReg(*RAI, CurBB, CurInst);
1994
1995 ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
1996 MTracker->setReg(DstRegNum, SrcValue);
1997
1998
1999 for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
2000 MCRegister SrcSubReg = SRI.getSubReg();
2001 unsigned SubRegIdx = SRI.getSubRegIndex();
2002 MCRegister DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
2003 if (!DstSubReg)
2004 continue;
2005
2006
2007
2008
2009
2010
2011 LocIdx SrcL =
2012 MTracker->lookupOrTrackRegister(MTracker->getLocID(SrcSubReg));
2013 LocIdx DstL =
2014 MTracker->lookupOrTrackRegister(MTracker->getLocID(DstSubReg));
2015 (void)SrcL;
2016 (void)DstL;
2017 ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
2018
2019 MTracker->setReg(DstSubReg, CpyValue);
2020 }
2021}
2022
2023std::optional
2024InstrRefBasedLDV::isSpillInstruction(const MachineInstr &MI,
2026
2027 if (.hasOneMemOperand())
2028 return std::nullopt;
2029
2030
2031 auto MMOI = MI.memoperands_begin();
2032 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
2034 return std::nullopt;
2035
2036 if (.getSpillSize(TII) &&
.getFoldedSpillSize(TII))
2037 return std::nullopt;
2038
2039
2040 return extractSpillBaseRegAndOffset(MI);
2041}
2042
2043bool InstrRefBasedLDV::isLocationSpill(const MachineInstr &MI,
2045 if (!isSpillInstruction(MI, MF))
2046 return false;
2047
2048 int FI;
2049 Reg = TII->isStoreToStackSlotPostFE(MI, FI);
2050 return Reg != 0;
2051}
2052
2053std::optional
2054InstrRefBasedLDV::isRestoreInstruction(const MachineInstr &MI,
2056 if (.hasOneMemOperand())
2057 return std::nullopt;
2058
2059
2060
2061 if (MI.getRestoreSize(TII)) {
2062 Reg = MI.getOperand(0).getReg();
2063 return extractSpillBaseRegAndOffset(MI);
2064 }
2065 return std::nullopt;
2066}
2067
2068bool InstrRefBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI) {
2069
2070
2071
2073 return false;
2074
2075
2076
2077 int DummyFI = -1;
2078 if (!TII->isStoreToStackSlotPostFE(MI, DummyFI) &&
2079 !TII->isLoadFromStackSlotPostFE(MI, DummyFI))
2080 return false;
2081
2082 MachineFunction *MF = MI.getMF();
2083 unsigned Reg;
2084
2086
2087
2088
2089 int FIDummy;
2090 if (!TII->isStoreToStackSlotPostFE(MI, FIDummy) &&
2091 !TII->isLoadFromStackSlotPostFE(MI, FIDummy))
2092 return false;
2093
2094
2095
2096
2097 if (std::optional Loc = isSpillInstruction(MI, MF)) {
2098
2099
2100 for (unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
2101 unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
2102 std::optional MLoc = MTracker->getSpillMLoc(SpillID);
2103 if (!MLoc)
2104 continue;
2105
2106
2107
2108
2109
2110 ValueIDNum Def(CurBB, CurInst, *MLoc);
2111 MTracker->setMLoc(*MLoc, Def);
2112 if (TTracker)
2113 TTracker->clobberMloc(*MLoc, MI.getIterator());
2114 }
2115 }
2116
2117
2118 if (isLocationSpill(MI, MF, Reg)) {
2119
2120
2121 SpillLocationNo Loc = *extractSpillBaseRegAndOffset(MI);
2122
2123 auto DoTransfer = [&](Register SrcReg, unsigned SpillID) {
2124 auto ReadValue = MTracker->readReg(SrcReg);
2125 LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
2126 MTracker->setMLoc(DstLoc, ReadValue);
2127
2128 if (TTracker) {
2129 LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
2130 TTracker->transferMlocs(SrcLoc, DstLoc, MI.getIterator());
2131 }
2132 };
2133
2134
2136
2137 (void)MTracker->lookupOrTrackRegister(MTracker->getLocID(SR));
2138 unsigned SubregIdx = TRI->getSubRegIndex(Reg, SR);
2139 unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
2140 DoTransfer(SR, SpillID);
2141 }
2142
2143
2144 unsigned Size = TRI->getRegSizeInBits(Reg, *MRI);
2145 unsigned SpillID = MTracker->getLocID(Loc, {Size, 0});
2146 DoTransfer(Reg, SpillID);
2147 } else {
2148 std::optional Loc = isRestoreInstruction(MI, MF, Reg);
2149 if (!Loc)
2150 return false;
2151
2152
2153
2154
2155
2156
2157
2158
2159 for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
2160 MTracker->defReg(*RAI, CurBB, CurInst);
2161
2162
2163
2164 auto DoTransfer = [&](Register DestReg, unsigned SpillID) {
2165 LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
2166 auto ReadValue = MTracker->readMLoc(SrcIdx);
2167 MTracker->setReg(DestReg, ReadValue);
2168 };
2169
2171 unsigned Subreg = TRI->getSubRegIndex(Reg, SR);
2172 unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
2173 DoTransfer(SR, SpillID);
2174 }
2175
2176
2177 unsigned Size = TRI->getRegSizeInBits(Reg, *MRI);
2178 unsigned SpillID = MTracker->getLocID(*Loc, {Size, 0});
2179 DoTransfer(Reg, SpillID);
2180 }
2181 return true;
2182}
2183
2184bool InstrRefBasedLDV::transferRegisterCopy(MachineInstr &MI) {
2185 auto DestSrc = TII->isCopyLikeInstr(MI);
2186 if (!DestSrc)
2187 return false;
2188
2189 const MachineOperand *DestRegOp = DestSrc->Destination;
2190 const MachineOperand *SrcRegOp = DestSrc->Source;
2191
2194
2195
2196 if (SrcReg == DestReg)
2197 return true;
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2209 return false;
2210
2211
2213 return false;
2214
2215
2216
2217
2218 DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
2219 if (TTracker) {
2220 for (MCRegAliasIterator RAI(DestReg, TRI, true); RAI.isValid(); ++RAI) {
2221 LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
2222 auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
2223
2224
2225 if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
2226 continue;
2227 ValueIDNum Value = MTracker->readReg(*RAI);
2228 ClobberedLocs[ClobberedLoc] = Value;
2229 }
2230 }
2231
2232
2233 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2234
2235
2236
2237
2238 if (TTracker) {
2239 for (auto LocVal : ClobberedLocs) {
2240 TTracker->clobberMloc(LocVal.first, LocVal.second, MI.getIterator(), false);
2241 }
2242 }
2243
2244
2245
2246
2248 TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
2249 MTracker->getRegMLoc(DestReg), MI.getIterator());
2250
2251
2253 MTracker->defReg(SrcReg, CurBB, CurInst);
2254
2255 return true;
2256}
2257
2258
2259
2260
2261
2262
2263
2264void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) {
2265 assert(MI.isDebugValueLike());
2266 DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),
2267 MI.getDebugLoc()->getInlinedAt());
2268 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2269
2270
2271
2272
2273 auto [SeenIt, Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
2274 if (Inserted) {
2275 SeenIt->second.insert(ThisFragment);
2276
2277 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2278 return;
2279 }
2280
2281
2282
2283 auto IsInOLapMap =
2284 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2285 if (!IsInOLapMap.second)
2286 return;
2287
2288 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2289 auto &AllSeenFragments = SeenIt->second;
2290
2291
2292
2293
2294 for (const auto &ASeenFragment : AllSeenFragments) {
2295
2297
2298 ThisFragmentsOverlaps.push_back(ASeenFragment);
2299
2300
2301 auto ASeenFragmentsOverlaps =
2302 OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
2303 assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
2304 "Previously seen var fragment has no vector of overlaps");
2305 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2306 }
2307 }
2308
2309 AllSeenFragments.insert(ThisFragment);
2310}
2311
2315
2316
2317
2318 if (transferDebugValue(MI))
2319 return;
2320 if (transferDebugInstrRef(MI, MLiveOuts, MLiveIns))
2321 return;
2322 if (transferDebugPHI(MI))
2323 return;
2324 if (transferRegisterCopy(MI))
2325 return;
2326 if (transferSpillOrRestoreInst(MI))
2327 return;
2328 transferRegisterDef(MI);
2329}
2330
2331void InstrRefBasedLDV::produceMLocTransferFunction(
2334
2335
2336
2337
2338
2339
2340
2341
2344
2345
2347 for (auto &BV : BlockMasks)
2348 BV.resize(TRI->getNumRegs(), true);
2349
2350
2351 for (auto &MBB : MF) {
2352
2353
2355 CurInst = 1;
2356
2357
2358
2359 MTracker->reset();
2360 MTracker->setMPhis(CurBB);
2361
2362
2364
2365
2366 process(MI, nullptr, nullptr);
2367
2368
2369 if (MI.isDebugValueLike())
2370 accumulateFragmentMap(MI);
2371
2372
2373
2374 if (uint64_t InstrNo = MI.peekDebugInstrNum()) {
2375 auto InstrAndPos = std::make_pair(&MI, CurInst);
2376 auto InsertResult =
2377 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2378
2379
2380 assert(InsertResult.second);
2381 (void)InsertResult;
2382 }
2383
2384 ++CurInst;
2385 }
2386
2387
2388
2389
2390
2391 for (auto Location : MTracker->locations()) {
2394 if (P.isPHI() && P.getLoc() == Idx.asU64())
2395 continue;
2396
2397
2398 auto &TransferMap = MLocTransfer[CurBB];
2399 auto Result = TransferMap.insert(std::make_pair(Idx.asU64(), P));
2401 Result.first->second = P;
2402 }
2403
2404
2405
2406 for (auto &P : MTracker->Masks) {
2407 BlockMasks[CurBB].clearBitsNotInMask(P.first->getRegMask(), BVWords);
2408 }
2409 }
2410
2411
2412 BitVector UsedRegs(TRI->getNumRegs());
2413 for (auto Location : MTracker->locations()) {
2414 unsigned ID = MTracker->LocIdxToLocID[Location.Idx];
2415
2416 if (ID >= TRI->getNumRegs() || MTracker->SPAliases.count(ID))
2417 continue;
2418 UsedRegs.set(ID);
2419 }
2420
2421
2422
2423
2425 BitVector &BV = BlockMasks[I];
2427 BV &= UsedRegs;
2428
2429
2430
2431 for (unsigned Bit : BV.set_bits()) {
2432 unsigned ID = MTracker->getLocID(Bit);
2433 LocIdx Idx = MTracker->LocIDToLocIdx[ID];
2434 auto &TransferMap = MLocTransfer[I];
2435
2436
2437
2438
2439
2440
2441 ValueIDNum NotGeneratedNum = ValueIDNum(I, 1, Idx);
2443 TransferMap.insert(std::make_pair(Idx.asU64(), NotGeneratedNum));
2444 if (.second) {
2445 ValueIDNum &ValueID = Result.first->second;
2447
2448 ValueID = NotGeneratedNum;
2449 }
2450 }
2451 }
2452}
2453
2454bool InstrRefBasedLDV::mlocJoin(
2459
2460
2461
2462
2463
2464
2466
2467
2468 auto Cmp = [&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
2469 return BBToOrder.find(A)->second < BBToOrder.find(B)->second;
2470 };
2472
2473
2474 if (BlockOrders.size() == 0) {
2475
2476
2478 << "Found not reachable block " << MBB.getFullName()
2479 << " from entry which may lead out of "
2480 "bound access to VarLocs\n");
2481 return false;
2482 }
2483
2484
2485
2486 for (auto Location : MTracker->locations()) {
2488
2489
2490
2491 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.asU64()];
2492
2493
2494
2495 if (InLocs[Idx.asU64()] != ValueIDNum(MBB.getNumber(), 0, Idx)) {
2496 if (InLocs[Idx.asU64()] != FirstVal) {
2497 InLocs[Idx.asU64()] = FirstVal;
2499 }
2500 continue;
2501 }
2502
2503
2504
2505 bool Disagree = false;
2506 for (unsigned int I = 1; I < BlockOrders.size(); ++I) {
2507 const MachineBasicBlock *PredMBB = BlockOrders[I];
2508 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.asU64()];
2509
2510
2511 if (FirstVal == PredLiveOut)
2512 continue;
2513
2514
2515 if (PredLiveOut == ValueIDNum(MBB.getNumber(), 0, Idx))
2516 continue;
2517
2518
2519 Disagree = true;
2520 }
2521
2522
2523 if (!Disagree) {
2524 InLocs[Idx.asU64()] = FirstVal;
2526 }
2527 }
2528
2529
2531}
2532
2533void InstrRefBasedLDV::findStackIndexInterference(
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546 auto It = MTracker->StackSlotIdxes.find({8, 0});
2547 assert(It != MTracker->StackSlotIdxes.end());
2549
2550
2551 for (auto &Pair : MTracker->StackSlotIdxes) {
2552
2553 if (!Pair.first.second)
2554 continue;
2556 }
2557}
2558
2559void InstrRefBasedLDV::placeMLocPHIs(
2562 SmallVector<unsigned, 4> StackUnits;
2563 findStackIndexInterference(StackUnits);
2564
2565
2566
2567
2568
2569
2570
2571
2572 SmallSet<Register, 32> RegUnitsToPHIUp;
2573 SmallSet<LocIdx, 32> NormalLocsToPHI;
2574 SmallSet<SpillLocationNo, 32> StackSlots;
2575 for (auto Location : MTracker->locations()) {
2577 if (MTracker->isSpill(L)) {
2578 StackSlots.insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
2579 continue;
2580 }
2581
2582 Register R = MTracker->LocIdxToLocID[L];
2583 SmallSet<Register, 8> FoundRegUnits;
2584 bool AnyIllegal = false;
2585 for (MCRegUnit Unit : TRI->regunits(R.asMCReg())) {
2586 for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) {
2587 if (!MTracker->isRegisterTracked(*URoot)) {
2588
2589
2590
2591 AnyIllegal = true;
2592 } else {
2593 FoundRegUnits.insert(*URoot);
2594 }
2595 }
2596 }
2597
2598 if (AnyIllegal) {
2599 NormalLocsToPHI.insert(L);
2600 continue;
2601 }
2602
2603 RegUnitsToPHIUp.insert_range(FoundRegUnits);
2604 }
2605
2606
2607
2608 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
2609 auto CollectPHIsForLoc = [&](LocIdx L) {
2610
2611 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
2612 for (MachineBasicBlock *MBB : OrderToBB) {
2613 const auto &TransferFunc = MLocTransfer[MBB->getNumber()];
2614 if (TransferFunc.contains(L))
2616 }
2617
2618
2619
2620
2621 if (!DefBlocks.empty())
2623
2624
2625
2626 PHIBlocks.clear();
2627 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2628 };
2629
2630 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx L) {
2631 for (const MachineBasicBlock *MBB : PHIBlocks)
2632 MInLocs[*MBB][L.asU64()] = ValueIDNum(MBB->getNumber(), 0, L);
2633 };
2634
2635
2636 for (LocIdx L : NormalLocsToPHI) {
2637 CollectPHIsForLoc(L);
2638
2639 InstallPHIsAtLoc(L);
2640 }
2641
2642
2643
2644 for (SpillLocationNo Slot : StackSlots) {
2645 for (unsigned Idx : StackUnits) {
2646 unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
2647 LocIdx L = MTracker->getSpillMLoc(SpillID);
2648 CollectPHIsForLoc(L);
2649 InstallPHIsAtLoc(L);
2650
2651
2653 std::tie(Size, Offset) = MTracker->StackIdxesToPos[Idx];
2654 for (auto &Pair : MTracker->StackSlotIdxes) {
2655 unsigned ThisSize, ThisOffset;
2656 std::tie(ThisSize, ThisOffset) = Pair.first;
2657 if (ThisSize + ThisOffset <= Offset || Size + Offset <= ThisOffset)
2658 continue;
2659
2660 unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
2661 LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
2662 InstallPHIsAtLoc(ThisL);
2663 }
2664 }
2665 }
2666
2667
2668 for (Register R : RegUnitsToPHIUp) {
2669 LocIdx L = MTracker->lookupOrTrackRegister(MTracker->getLocID(R));
2670 CollectPHIsForLoc(L);
2671
2672
2673 InstallPHIsAtLoc(L);
2674
2675
2676 for (MCRegAliasIterator RAI(R, TRI, true); RAI.isValid(); ++RAI) {
2677
2678
2679 if (!MTracker->isRegisterTracked(*RAI))
2680 continue;
2681
2682 LocIdx AliasLoc =
2683 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
2684 InstallPHIsAtLoc(AliasLoc);
2685 }
2686 }
2687}
2688
2689void InstrRefBasedLDV::buildMLocValueMap(
2692 std::priority_queue<unsigned int, std::vector,
2693 std::greater>
2694 Worklist, Pending;
2695
2696
2697
2698
2699 SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
2700
2701
2702
2703 SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
2704 for (unsigned int I = 0; I < BBToOrder.size(); ++I) {
2705 Worklist.push(I);
2706 OnWorklist.insert(OrderToBB[I]);
2707 AllBlocks.insert(OrderToBB[I]);
2708 }
2709
2710
2711 for (auto Location : MTracker->locations())
2713 ValueIDNum(0, 0, Location.Idx);
2714
2715 MTracker->reset();
2716
2717
2718
2719
2720 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2731 while (!Worklist.empty() || !Pending.empty()) {
2732
2734
2735 while (!Worklist.empty()) {
2736 MachineBasicBlock *MBB = OrderToBB[Worklist.top()];
2738 Worklist.pop();
2739
2740
2741 bool InLocsChanged;
2742 InLocsChanged = mlocJoin(*MBB, Visited, MOutLocs, MInLocs[*MBB]);
2743 InLocsChanged |= Visited.insert(MBB).second;
2744
2745
2746
2747 if (!InLocsChanged)
2748 continue;
2749
2750
2751 MTracker->loadFromArray(MInLocs[*MBB], CurBB);
2752
2753
2754
2755 ToRemap.clear();
2756 for (auto &P : MLocTransfer[CurBB]) {
2757 if (P.second.getBlock() == CurBB && P.second.isPHI()) {
2758
2759 ValueIDNum NewID = MTracker->readMLoc(P.second.getLoc());
2760 ToRemap.push_back(std::make_pair(P.first, NewID));
2761 } else {
2762
2763 assert(P.second.getBlock() == CurBB);
2764 ToRemap.push_back(std::make_pair(P.first, P.second));
2765 }
2766 }
2767
2768
2769
2770 for (auto &P : ToRemap)
2771 MTracker->setMLoc(P.first, P.second);
2772
2773
2774
2775
2776 bool OLChanged = false;
2777 for (auto Location : MTracker->locations()) {
2780 }
2781
2782 MTracker->reset();
2783
2784
2785 if (!OLChanged)
2786 continue;
2787
2788
2789
2790
2792
2793 unsigned Order = BBToOrder[s];
2794 if (Order > BBToOrder[MBB]) {
2795
2796 if (OnWorklist.insert(s).second)
2797 Worklist.push(Order);
2798 } else {
2799
2800 if (OnPending.insert(s).second)
2801 Pending.push(Order);
2802 }
2803 }
2804 }
2805
2806 Worklist.swap(Pending);
2807 std::swap(OnPending, OnWorklist);
2808 OnPending.clear();
2809
2810
2811 assert(Pending.empty() && "Pending should be empty");
2812 }
2813
2814
2815
2816}
2817
2818void InstrRefBasedLDV::BlockPHIPlacement(
2822
2823
2824
2825 IDFCalculatorBase<MachineBasicBlock, false> IDF(*DomTree);
2826
2827 IDF.setLiveInBlocks(AllBlocks);
2828 IDF.setDefiningBlocks(DefBlocks);
2829 IDF.calculate(PHIBlocks);
2830}
2831
2832bool InstrRefBasedLDV::pickVPHILoc(
2836
2837
2838 if (BlockOrders.empty())
2839 return false;
2840
2841
2842
2843 SmallDenseSet LocOpsToJoin;
2844
2845 auto FirstValueIt = LiveOuts.find(BlockOrders[0]);
2846 if (FirstValueIt == LiveOuts.end())
2847 return false;
2848 const DbgValue &FirstValue = *FirstValueIt->second;
2849
2850 for (const auto p : BlockOrders) {
2851 auto OutValIt = LiveOuts.find(p);
2852 if (OutValIt == LiveOuts.end())
2853
2854 return false;
2855 const DbgValue &OutVal = *OutValIt->second;
2856
2857
2859 return false;
2860
2861
2862
2864 return false;
2865
2867 return false;
2868
2869 for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) {
2870
2871
2873 LocOpsToJoin.insert(Idx);
2874 continue;
2875 }
2876 DbgOpID FirstValOp = FirstValue.getDbgOpID(Idx);
2877 DbgOpID OutValOp = OutVal.getDbgOpID(Idx);
2878 if (FirstValOp != OutValOp) {
2879
2880
2882 return false;
2883 else
2884 LocOpsToJoin.insert(Idx);
2885 }
2886 }
2887 }
2888
2890
2891 for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) {
2892
2893
2894 if (!LocOpsToJoin.contains(Idx)) {
2896 continue;
2897 }
2898
2899 std::optional JoinedOpLoc =
2900 pickOperandPHILoc(Idx, MBB, LiveOuts, MOutLocs, BlockOrders);
2901
2902 if (!JoinedOpLoc)
2903 return false;
2904
2905 NewDbgOps.push_back(DbgOpStore.insert(*JoinedOpLoc));
2906 }
2907
2908 OutValues.append(NewDbgOps);
2909 return true;
2910}
2911
2912std::optional InstrRefBasedLDV::pickOperandPHILoc(
2916
2917
2918
2920 unsigned NumLocs = MTracker->getNumLocs();
2921
2922 for (const auto p : BlockOrders) {
2923 auto OutValIt = LiveOuts.find(p);
2924 assert(OutValIt != LiveOuts.end());
2925 const DbgValue &OutVal = *OutValIt->second;
2926 DbgOpID OutValOpID = OutVal.getDbgOpID(DbgOpIdx);
2927 DbgOp OutValOp = DbgOpStore.find(OutValOpID);
2929
2930
2932
2933
2934
2938 ValueIDNum ValToLookFor = OutValOp.ID;
2939
2940 for (unsigned int I = 0; I < NumLocs; ++I) {
2941 if (MOutLocs[*p][I] == ValToLookFor)
2942 Locs.back().push_back(LocIdx(I));
2943 }
2944 } else {
2946
2947
2948
2949
2950
2951
2952 for (unsigned int I = 0; I < NumLocs; ++I) {
2954 if (MOutLocs[*p][I] == MPHI)
2955 Locs.back().push_back(LocIdx(I));
2956 }
2957 }
2958 }
2959
2960 assert(Locs.size() == BlockOrders.size());
2961
2962
2963
2965 for (unsigned int I = 1; I < Locs.size(); ++I) {
2966 auto &LocVec = Locs[I];
2968 std::set_intersection(CandidateLocs.begin(), CandidateLocs.end(),
2969 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.begin()));
2970 CandidateLocs = std::move(NewCandidates);
2971 }
2972 if (CandidateLocs.empty())
2973 return std::nullopt;
2974
2975
2976
2977
2978 LocIdx L = *CandidateLocs.begin();
2979
2980
2981 ValueIDNum PHIVal = {(unsigned)MBB.getNumber(), 0, L};
2982 return PHIVal;
2983}
2984
2985bool InstrRefBasedLDV::vlocJoin(
2991
2992
2993 SmallVector<MachineBasicBlock *, 8> BlockOrders(MBB.predecessors());
2994
2995 auto Cmp = [&](MachineBasicBlock *A, MachineBasicBlock *B) {
2996 return BBToOrder[A] < BBToOrder[B];
2997 };
2998
3000
3001 unsigned CurBlockRPONum = BBToOrder[&MBB];
3002
3003
3004
3006 bool Bail = false;
3007 int BackEdgesStart = 0;
3008 for (auto *p : BlockOrders) {
3009
3010
3011 if (!BlocksToExplore.contains(p)) {
3012 Bail = true;
3013 break;
3014 }
3015
3016
3017 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3018
3019
3020
3021 unsigned ThisBBRPONum = BBToOrder[p];
3022 if (ThisBBRPONum < CurBlockRPONum)
3023 ++BackEdgesStart;
3024
3025 Values.push_back(std::make_pair(p, &OutLoc));
3026 }
3027
3028
3029
3030
3031 if (Bail || Values.size() == 0)
3032 return false;
3033
3034
3035
3036
3037 const DbgValue &FirstVal = *Values[0].second;
3038
3039
3040
3041
3043 Changed = LiveIn != FirstVal;
3045 LiveIn = FirstVal;
3047 }
3048
3049
3050
3051
3052 for (const auto &V : Values) {
3053 if (.second->Properties.isJoinable(FirstVal.Properties))
3054 return false;
3056 return false;
3057 if (.second->hasJoinableLocOps(FirstVal))
3058 return false;
3059 }
3060
3061
3062 bool Disagree = false;
3063 for (auto &V : Values) {
3064 if (*V.second == FirstVal)
3065 continue;
3066
3067
3068
3069
3070 if (V.second->hasIdenticalValidLocOps(FirstVal))
3071 continue;
3072
3073
3076
3077 std::distance(Values.begin(), &V) >= BackEdgesStart)
3078 continue;
3079
3080 Disagree = true;
3081 }
3082
3083
3084 if (!Disagree) {
3085 Changed = LiveIn != FirstVal;
3087 LiveIn = FirstVal;
3089 } else {
3090
3092 Changed = LiveIn != VPHI;
3094 LiveIn = VPHI;
3096 }
3097}
3098
3099void InstrRefBasedLDV::getBlocksForScope(
3103
3104 LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
3105
3106
3107
3108
3110
3111
3112 DenseSet<const MachineBasicBlock *> ToAdd;
3113
3114
3115
3116
3117
3118
3119 for (const auto *MBB : BlocksToExplore) {
3120
3121
3122 SmallVector<std::pair<const MachineBasicBlock *,
3124 8>
3125 DFS;
3126
3127
3129 if (BlocksToExplore.count(succ))
3130 continue;
3131 if (!ArtificialBlocks.count(succ))
3132 continue;
3134 DFS.push_back({succ, succ->succ_begin()});
3135 }
3136
3137
3138 while (!DFS.empty()) {
3139 const MachineBasicBlock *CurBB = DFS.back().first;
3141
3142 if (CurSucc == CurBB->succ_end()) {
3143 DFS.pop_back();
3144 continue;
3145 }
3146
3147
3148
3149 if (!ToAdd.count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3150 ToAdd.insert(*CurSucc);
3151 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3152 continue;
3153 }
3154
3155 ++CurSucc;
3156 }
3157 };
3158
3159 BlocksToExplore.insert_range(ToAdd);
3160}
3161
3162void InstrRefBasedLDV::buildVLocValueMap(
3168
3169
3170
3171
3172 std::priority_queue<unsigned int, std::vector,
3173 std::greater>
3174 Worklist, Pending;
3175 SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
3176
3177
3178 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3179
3180
3182 SmallVector<unsigned, 32> BlockOrderNums;
3183
3184 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3185
3186
3187
3188
3189
3190 if (BlocksToExplore.size() == 1)
3191 return;
3192
3193
3194
3195
3196 SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
3197 for (const auto *MBB : BlocksToExplore)
3198 MutBlocksToExplore.insert(const_cast<MachineBasicBlock *>(MBB));
3199
3200
3201
3202
3203 for (const auto *MBB : BlocksToExplore)
3205
3207 for (unsigned int I : BlockOrderNums)
3208 BlockOrders.push_back(OrderToBB[I]);
3209 BlockOrderNums.clear();
3210 unsigned NumBlocks = BlockOrders.size();
3211
3212
3214 LiveIns.reserve(NumBlocks);
3215 LiveOuts.reserve(NumBlocks);
3216
3217
3218
3219 DbgValueProperties EmptyProperties(EmptyExpr, false, false);
3220 for (unsigned int I = 0; I < NumBlocks; ++I) {
3221 DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal);
3222 LiveIns.push_back(EmptyDbgValue);
3223 LiveOuts.push_back(EmptyDbgValue);
3224 }
3225
3226
3227
3228 LiveIdxT LiveOutIdx, LiveInIdx;
3229 LiveOutIdx.reserve(NumBlocks);
3230 LiveInIdx.reserve(NumBlocks);
3231 for (unsigned I = 0; I < NumBlocks; ++I) {
3232 LiveOutIdx[BlockOrders[I]] = &LiveOuts[I];
3233 LiveInIdx[BlockOrders[I]] = &LiveIns[I];
3234 }
3235
3236
3237
3238
3239
3241
3242
3243 for (unsigned int I = 0; I < NumBlocks; ++I) {
3244 DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal);
3245 LiveIns[I] = EmptyDbgValue;
3246 LiveOuts[I] = EmptyDbgValue;
3247 }
3248
3249
3250
3251 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
3252 for (const MachineBasicBlock *ExpMBB : BlocksToExplore) {
3253 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3254 if (TransferFunc.contains(VarID))
3255 DefBlocks.insert(const_cast<MachineBasicBlock *>(ExpMBB));
3256 }
3257
3258 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
3259
3260
3261
3262 if (DefBlocks.size() == 1) {
3263 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.begin(),
3264 AllTheVLocs, VarID, Output);
3265 continue;
3266 }
3267
3268
3269 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3270
3271
3272 for (MachineBasicBlock *PHIMBB : PHIBlocks) {
3273 unsigned BlockNo = PHIMBB->getNumber();
3274 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3275 *LiveIn = DbgValue(BlockNo, EmptyProperties, DbgValue::VPHI);
3276 }
3277
3278 for (auto *MBB : BlockOrders) {
3279 Worklist.push(BBToOrder[MBB]);
3281 }
3282
3283
3284
3285
3286
3287
3288
3289
3290 bool FirstTrip = true;
3291 while (!Worklist.empty() || !Pending.empty()) {
3292 while (!Worklist.empty()) {
3293 auto *MBB = OrderToBB[Worklist.top()];
3295 Worklist.pop();
3296
3297 auto LiveInsIt = LiveInIdx.find(MBB);
3298 assert(LiveInsIt != LiveInIdx.end());
3299 DbgValue *LiveIn = LiveInsIt->second;
3300
3301
3302
3303 bool InLocsChanged =
3304 vlocJoin(*MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3305
3307
3308
3309
3310
3311
3313
3314
3315
3316
3318
3319 if (pickVPHILoc(JoinedOps, *MBB, LiveOutIdx, MOutLocs, Preds)) {
3320 bool NewLocPicked = (LiveIn->getDbgOpIDs(), JoinedOps);
3321 InLocsChanged |= NewLocPicked;
3322 if (NewLocPicked)
3324 }
3325 }
3326
3327 if (!InLocsChanged && !FirstTrip)
3328 continue;
3329
3330 DbgValue *LiveOut = LiveOutIdx[MBB];
3331 bool OLChanged = false;
3332
3333
3334 auto &VTracker = AllTheVLocs[MBB->getNumber()];
3335 auto TransferIt = VTracker.Vars.find(VarID);
3336 if (TransferIt != VTracker.Vars.end()) {
3337
3340 if (*LiveOut != NewVal) {
3341 *LiveOut = NewVal;
3342 OLChanged = true;
3343 }
3344 } else {
3345
3346 if (*LiveOut != TransferIt->second) {
3347 *LiveOut = TransferIt->second;
3348 OLChanged = true;
3349 }
3350 }
3351 } else {
3352
3353 if (*LiveOut != *LiveIn) {
3354 *LiveOut = *LiveIn;
3355 OLChanged = true;
3356 }
3357 }
3358
3359
3360 if (!OLChanged)
3361 continue;
3362
3363
3364
3365
3367
3368 if (!LiveInIdx.contains(s))
3369 continue;
3370
3371 unsigned Order = BBToOrder[s];
3372 if (Order > BBToOrder[MBB]) {
3373 if (OnWorklist.insert(s).second)
3374 Worklist.push(Order);
3375 } else if (OnPending.insert(s).second && (FirstTrip || OLChanged)) {
3376 Pending.push(Order);
3377 }
3378 }
3379 }
3380 Worklist.swap(Pending);
3381 std::swap(OnWorklist, OnPending);
3382 OnPending.clear();
3383 assert(Pending.empty());
3384 FirstTrip = false;
3385 }
3386
3387
3388
3389
3390 for (auto *MBB : BlockOrders) {
3391 DbgValue *BlockLiveIn = LiveInIdx[MBB];
3393 continue;
3395 continue;
3398 [[maybe_unused]] auto &[Var, DILoc] = DVMap.lookupDVID(VarID);
3400 Var.getFragment() &&
3401 "Fragment info missing during value prop");
3402 Output[MBB->getNumber()].push_back(std::make_pair(VarID, *BlockLiveIn));
3403 }
3404 }
3405
3406 BlockOrders.clear();
3407 BlocksToExplore.clear();
3408}
3409
3410void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425 VLocTracker &VLocs = AllTheVLocs[AssignMBB->getNumber()];
3426 auto ValueIt = VLocs.Vars.find(VarID);
3427 const DbgValue &Value = ValueIt->second;
3428
3429
3430
3432 return;
3433
3434
3435
3436
3437 for (auto *ScopeBlock : InScopeBlocks) {
3438 if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
3439 continue;
3440
3441 Output[ScopeBlock->getNumber()].push_back({VarID, Value});
3442 }
3443
3444
3445
3446}
3447
3448#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3451 for (const auto &P : mloc_transfer) {
3452 std::string foo = MTracker->LocIdxToName(P.first);
3453 std::string bar = MTracker->IDAsString(P.second);
3454 dbgs() << "Loc " << foo << " --> " << bar << "\n";
3455 }
3456}
3457#endif
3458
3459void InstrRefBasedLDV::initialSetup(MachineFunction &MF) {
3460
3461
3464
3465 auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool {
3467 return DL.getLine() != 0;
3468 return false;
3469 };
3470
3471
3472
3473 unsigned int Size = 0;
3474 for (auto &MBB : MF) {
3477 ArtificialBlocks.insert(&MBB);
3478 }
3479
3480
3481 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
3482 unsigned int RPONumber = 0;
3483 OrderToBB.reserve(Size);
3484 BBToOrder.reserve(Size);
3485 BBNumToRPO.reserve(Size);
3486 auto processMBB = [&](MachineBasicBlock *MBB) {
3487 OrderToBB.push_back(MBB);
3488 BBToOrder[MBB] = RPONumber;
3490 ++RPONumber;
3491 };
3492 for (MachineBasicBlock *MBB : RPOT)
3493 processMBB(MBB);
3494 for (MachineBasicBlock &MBB : MF)
3495 if (!BBToOrder.contains(&MBB))
3496 processMBB(&MBB);
3497
3498
3499 llvm::sort(MF.DebugValueSubstitutions);
3500
3501#ifdef EXPENSIVE_CHECKS
3502
3503
3504 if (MF.DebugValueSubstitutions.size() > 2) {
3505 for (auto It = MF.DebugValueSubstitutions.begin();
3506 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3507 assert(It->Src != std::next(It)->Src && "Duplicate variable location "
3508 "substitution seen");
3509 }
3510 }
3511#endif
3512}
3513
3514
3515
3516
3517void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3519 const ScopeToDILocT &ScopeToDILocation,
3520 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3521 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3523 auto *TopScope = LS.getCurrentFunctionScope();
3524
3525
3526
3527 WorkStack.push_back({TopScope, TopScope->getChildren().size() - 1});
3528
3529 while (!WorkStack.empty()) {
3530 auto &ScopePosition = WorkStack.back();
3531 LexicalScope *WS = ScopePosition.first;
3532 ssize_t ChildNum = ScopePosition.second--;
3533
3535 if (ChildNum >= 0) {
3536
3537
3538 auto &ChildScope = Children[ChildNum];
3540 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3541 } else {
3543
3544
3545
3546
3547 auto DILocationIt = ScopeToDILocation.find(WS);
3548 if (DILocationIt != ScopeToDILocation.end()) {
3549 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3550 ScopeToAssignBlocks.find(WS)->second);
3551 for (const auto *MBB : BlocksToExplore) {
3553 if (EjectionMap[BBNum] == 0)
3554 EjectionMap[BBNum] = WS->getDFSOut();
3555 }
3556
3557 BlocksToExplore.clear();
3558 }
3559 }
3560 }
3561}
3562
3563bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3564 unsigned MaxNumBlocks, const ScopeToDILocT &ScopeToDILocation,
3565 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3568 bool ShouldEmitDebugEntryValues) {
3569 TTracker = new TransferTracker(TII, MTracker, MF, DVMap, *TRI,
3570 CalleeSavedRegs, ShouldEmitDebugEntryValues);
3571 unsigned NumLocs = MTracker->getNumLocs();
3572 VTracker = nullptr;
3573
3574
3575 if (!LS.getCurrentFunctionScope())
3576 return false;
3577
3578
3579 SmallVector<unsigned, 16> EjectionMap;
3581 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3582 ScopeToAssignBlocks);
3583
3584
3585
3586
3587 auto EjectBlock = [&](MachineBasicBlock &MBB) -> void {
3589 AllTheVLocs[BBNum].clear();
3590
3591
3592
3593 MTracker->reset();
3594 MTracker->loadFromArray(MInLocs[MBB], BBNum);
3595 TTracker->loadInlocs(MBB, MInLocs[MBB], DbgOpStore, Output[BBNum], NumLocs);
3596
3597 CurBB = BBNum;
3598 CurInst = 1;
3600 process(MI, &MOutLocs, &MInLocs);
3601 TTracker->checkInstForNewValues(CurInst, MI.getIterator());
3602 ++CurInst;
3603 }
3604
3605
3608
3609 Output[BBNum].clear();
3610 AllTheVLocs[BBNum].clear();
3611 };
3612
3613 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3615 WorkStack.push_back({LS.getCurrentFunctionScope(), 0});
3616 unsigned HighestDFSIn = 0;
3617
3618
3619 while (!WorkStack.empty()) {
3620 auto &ScopePosition = WorkStack.back();
3621 LexicalScope *WS = ScopePosition.first;
3622 ssize_t ChildNum = ScopePosition.second++;
3623
3624
3625
3626
3627
3628
3629 auto DILocIt = ScopeToDILocation.find(WS);
3630 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3631 const DILocation *DILoc = DILocIt->second;
3632 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3633 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3634
3635 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3636 MInLocs, AllTheVLocs);
3637 }
3638
3639 HighestDFSIn = std::max(HighestDFSIn, WS->getDFSIn());
3640
3641
3643 if (ChildNum < (ssize_t)Children.size()) {
3644
3645 auto &ChildScope = Children[ChildNum];
3646 WorkStack.push_back(std::make_pair(ChildScope, 0));
3647 } else {
3649
3650
3651
3652 auto DILocationIt = ScopeToDILocation.find(WS);
3653 if (DILocationIt == ScopeToDILocation.end())
3654 continue;
3655
3656 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3657 ScopeToAssignBlocks.find(WS)->second);
3658 for (const auto *MBB : BlocksToExplore)
3660 EjectBlock(const_cast<MachineBasicBlock &>(*MBB));
3661
3662 BlocksToExplore.clear();
3663 }
3664 }
3665
3666
3667
3668
3669
3670
3671 for (auto *MBB : ArtificialBlocks)
3673 EjectBlock(*MBB);
3674
3675 return emitTransfers();
3676}
3677
3678bool InstrRefBasedLDV::emitTransfers() {
3679
3680
3681
3682 for (auto &P : TTracker->Transfers) {
3683
3684
3685
3686
3687 llvm::sort(P.Insts, llvm::less_first());
3688
3689
3690 if (P.MBB) {
3691 MachineBasicBlock &MBB = *P.MBB;
3692 for (const auto &Pair : P.Insts)
3694 } else {
3695
3696
3697 if (P.Pos->isTerminator())
3698 continue;
3699
3701 for (const auto &Pair : P.Insts)
3703 }
3704 }
3705
3706 return TTracker->Transfers.size() != 0;
3707}
3708
3709
3710
3713 bool ShouldEmitDebugEntryValues,
3715 unsigned InputDbgValLimit) {
3716
3718 return false;
3719
3721
3722 this->DomTree = DomTree;
3729 LS.scanFunction(MF);
3730
3732 AdjustsStackInCalls = MFI->adjustsStack() &&
3734 if (AdjustsStackInCalls)
3735 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3736
3737 MTracker =
3739 VTracker = nullptr;
3740 TTracker = nullptr;
3741
3745
3747 for (auto &MBB : MF)
3751
3752 initialSetup(MF);
3753
3755 vlocs.resize(MaxNumBlocks, VLocTracker(DVMap, OverlapFragments, EmptyExpr));
3757
3758 produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks);
3759
3760
3761
3762
3763 unsigned NumLocs = MTracker->getNumLocs();
3764 FuncValueTable MOutLocs(MaxNumBlocks, NumLocs);
3765 FuncValueTable MInLocs(MaxNumBlocks, NumLocs);
3766
3767
3768
3769
3770
3771 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3772
3773
3774
3775 for (auto &DBG_PHI : DebugPHINumToValue) {
3776
3777 if (!DBG_PHI.ValueRead)
3778 continue;
3779
3780 ValueIDNum &Num = *DBG_PHI.ValueRead;
3781 if (!Num.isPHI())
3782 continue;
3783
3784 unsigned BlockNo = Num.getBlock();
3785 LocIdx LocNo = Num.getLoc();
3786 ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.asU64()];
3787
3788
3789
3791 Num = ResolvedValue;
3792 }
3793
3795
3796
3797
3798 for (MachineBasicBlock *MBB : OrderToBB) {
3800 VTracker = &vlocs[CurBB];
3801 VTracker->MBB = MBB;
3802 MTracker->loadFromArray(MInLocs[*MBB], CurBB);
3803 CurInst = 1;
3805 process(MI, &MOutLocs, &MInLocs);
3806 ++CurInst;
3807 }
3808 MTracker->reset();
3809 }
3810
3811
3813
3814
3815
3817
3818
3820
3821
3822
3823 unsigned VarAssignCount = 0;
3824 for (MachineBasicBlock *MBB : OrderToBB) {
3826
3827 for (auto &idx : VTracker->Vars) {
3829 const DILocation *ScopeLoc = VTracker->Scopes[VarID];
3830 assert(ScopeLoc != nullptr);
3831 auto *Scope = LS.findLexicalScope(ScopeLoc);
3832
3833
3834 assert(Scope != nullptr);
3835
3837 ScopeToAssignBlocks[Scope].insert(VTracker->MBB);
3838 ScopeToDILocation[Scope] = ScopeLoc;
3839 ++VarAssignCount;
3840 }
3841 }
3842
3844
3845
3846
3847
3849 VarAssignCount > InputDbgValLimit) {
3850 LLVM_DEBUG(dbgs() << "Disabling InstrRefBasedLDV: " << MF.getName()
3851 << " has " << MaxNumBlocks << " basic blocks and "
3852 << VarAssignCount
3853 << " variable assignments, exceeding limits.\n");
3854 } else {
3855
3856
3857
3858 Changed = depthFirstVLocAndEmit(
3859 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3860 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, ShouldEmitDebugEntryValues);
3861 }
3862
3863 delete MTracker;
3864 delete TTracker;
3865 MTracker = nullptr;
3866 VTracker = nullptr;
3867 TTracker = nullptr;
3868
3869 ArtificialBlocks.clear();
3870 OrderToBB.clear();
3871 BBToOrder.clear();
3872 BBNumToRPO.clear();
3873 DebugInstrNumToInstr.clear();
3874 DebugPHINumToValue.clear();
3875 OverlapFragments.clear();
3876 SeenFragments.clear();
3877 SeenDbgPHIs.clear();
3878 DbgOpStore.clear();
3879 DVMap.clear();
3880
3882}
3883
3887
3888namespace {
3889class LDVSSABlock;
3890class LDVSSAUpdater;
3891
3892
3893
3894
3895typedef uint64_t BlockValueNum;
3896
3897
3898
3899
3900class LDVSSAPhi {
3901public:
3903 LDVSSABlock *ParentBlock;
3904 BlockValueNum PHIValNum;
3905 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3906 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3907
3908 LDVSSABlock *getParent() { return ParentBlock; }
3909};
3910
3911
3912
3913class LDVSSABlockIterator {
3914public:
3916 LDVSSAUpdater &Updater;
3917
3919 LDVSSAUpdater &Updater)
3920 : PredIt(PredIt), Updater(Updater) {}
3921
3922 bool operator!=(const LDVSSABlockIterator &OtherIt) const {
3923 return OtherIt.PredIt != PredIt;
3924 }
3925
3926 LDVSSABlockIterator &operator++() {
3927 ++PredIt;
3928 return *this;
3929 }
3930
3932};
3933
3934
3935
3936
3937class LDVSSABlock {
3938public:
3939 MachineBasicBlock &BB;
3940 LDVSSAUpdater &Updater;
3941 using PHIListT = SmallVector<LDVSSAPhi, 1>;
3942
3943 PHIListT PHIList;
3944
3945 LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
3946 : BB(BB), Updater(Updater) {}
3947
3949 return LDVSSABlockIterator(BB.succ_begin(), Updater);
3950 }
3951
3952 LDVSSABlockIterator succ_end() {
3953 return LDVSSABlockIterator(BB.succ_end(), Updater);
3954 }
3955
3956
3957 LDVSSAPhi *newPHI(BlockValueNum Value) {
3958 PHIList.emplace_back(Value, this);
3959 return &PHIList.back();
3960 }
3961
3962
3963 PHIListT &phis() { return PHIList; }
3964};
3965
3966
3967
3968
3969class LDVSSAUpdater {
3970public:
3971
3972 DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
3973
3974
3975 DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap;
3976
3977 DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
3978
3979 LocIdx Loc;
3980
3981 const FuncValueTable &MLiveIns;
3982
3983 LDVSSAUpdater(LocIdx L, const FuncValueTable &MLiveIns)
3984 : Loc(L), MLiveIns(MLiveIns) {}
3985
3986 void reset() {
3987 for (auto &Block : BlockMap)
3988 delete Block.second;
3989
3991 PoisonMap.clear();
3992 BlockMap.clear();
3993 }
3994
3995 ~LDVSSAUpdater() { reset(); }
3996
3997
3998
3999 LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
4000 auto [It, Inserted] = BlockMap.try_emplace(BB);
4001 if (Inserted)
4002 It->second = new LDVSSABlock(*BB, *this);
4003 return It->second;
4004 }
4005
4006
4007
4008 BlockValueNum getValue(LDVSSABlock *LDVBB) {
4009 return MLiveIns[LDVBB->BB][Loc.asU64()].asU64();
4010 }
4011};
4012
4013LDVSSABlock *LDVSSABlockIterator::operator*() {
4014 return Updater.getSSALDVBlock(*PredIt);
4015}
4016
4017#ifndef NDEBUG
4018
4020 out << "SSALDVPHI " << PHI.PHIValNum;
4021 return out;
4022}
4023
4024#endif
4025
4026}
4027
4028namespace llvm {
4029
4030
4031
4032
4033
4035public:
4040
4041
4044
4045
4047 private:
4048 LDVSSAPhi *PHI;
4049 unsigned Idx;
4050
4051 public:
4055 : PHI(P), Idx(PHI->IncomingValues.size()) {}
4056
4058 Idx++;
4059 return *this;
4060 }
4063
4064 BlockValueNum getIncomingValue() { return PHI->IncomingValues[Idx].second; }
4065
4067 };
4068
4070
4074
4075
4076
4080 Preds->push_back(BB->Updater.getSSALDVBlock(Pred));
4081 }
4082
4083
4084
4085
4086 static BlockValueNum GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4087
4088
4089
4091 Updater->PoisonMap[&BB->BB] = Num;
4092 return Num;
4093 }
4094
4095
4096
4097
4098
4099
4100 static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds,
4101 LDVSSAUpdater *Updater) {
4102 BlockValueNum PHIValNum = Updater->getValue(BB);
4103 LDVSSAPhi *PHI = BB->newPHI(PHIValNum);
4104 Updater->PHIs[PHIValNum] = PHI;
4105 return PHIValNum;
4106 }
4107
4108
4109
4110 static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred) {
4111 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4112 }
4113
4114
4115
4116 static LDVSSAPhi *ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4117 return Updater->PHIs.lookup(Val);
4118 }
4119
4120
4121
4122 static LDVSSAPhi *ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4124 if (PHI && PHI->IncomingValues.size() == 0)
4125 return PHI;
4126 return nullptr;
4127 }
4128
4129
4130
4132};
4133
4134}
4135
4136std::optional InstrRefBasedLDV::resolveDbgPHIs(
4139
4140
4141 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4142 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4143 return SeenDbgPHIIt->second;
4144
4145 std::optional Result =
4146 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4147 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum), Result});
4149}
4150
4151std::optional InstrRefBasedLDV::resolveDbgPHIsImpl(
4154
4155
4156 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4157 DebugPHINumToValue.end(), InstrNum);
4158 auto LowerIt = RangePair.first;
4159 auto UpperIt = RangePair.second;
4160
4161
4162 if (LowerIt == UpperIt)
4163 return std::nullopt;
4164
4165
4166
4167
4168
4169 auto DBGPHIRange = make_range(LowerIt, UpperIt);
4170 for (const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4171 if (!DBG_PHI.ValueRead)
4172 return std::nullopt;
4173
4174
4175 if (std::distance(LowerIt, UpperIt) == 1)
4176 return *LowerIt->ValueRead;
4177
4178
4179
4180
4181
4182 LocIdx Loc = *LowerIt->ReadLoc;
4183
4184
4185
4186
4187
4188
4189
4190
4191 LDVSSAUpdater Updater(Loc, MLiveIns);
4192
4193 DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
4194
4196
4197
4198
4199 for (const auto &DBG_PHI : DBGPHIRange) {
4200 LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4201 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4203 }
4204
4205 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.getParent());
4206 const auto &AvailIt = AvailableValues.find(HereBlock);
4207 if (AvailIt != AvailableValues.end()) {
4208
4209
4211 }
4212
4213
4214
4215 SSAUpdaterImpl Impl(&Updater, &AvailableValues, &CreatedPHIs);
4216 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.getParent()));
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230 DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
4231
4232
4233 for (const auto &DBG_PHI : DBGPHIRange) {
4234 LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4235 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4236 ValidatedValues.insert(std::make_pair(Block, Num));
4237 }
4238
4239
4241
4242 llvm::sort(SortedPHIs, [&](LDVSSAPhi *A, LDVSSAPhi *B) {
4243 return BBToOrder[&A->getParent()->BB] < BBToOrder[&B->getParent()->BB];
4244 });
4245
4246 for (auto &PHI : SortedPHIs) {
4247 ValueIDNum ThisBlockValueNum = MLiveIns[PHI->ParentBlock->BB][Loc.asU64()];
4248
4249
4250 for (auto &PHIIt : PHI->IncomingValues) {
4251
4252 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4253 return std::nullopt;
4254
4255 ValueIDNum ValueToCheck;
4256 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4257
4258 auto VVal = ValidatedValues.find(PHIIt.first);
4259 if (VVal == ValidatedValues.end()) {
4260
4261
4262
4263
4264 ValueToCheck = ThisBlockValueNum;
4265 } else {
4266
4267
4268 ValueToCheck = VVal->second;
4269 }
4270
4271 if (BlockLiveOuts[Loc.asU64()] != ValueToCheck)
4272 return std::nullopt;
4273 }
4274
4275
4276 ValidatedValues.insert({PHI->ParentBlock, ThisBlockValueNum});
4277 }
4278
4279
4280
4282}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< unsigned > MaxNumBlocks("debug-ata-max-blocks", cl::init(10000), cl::desc("Maximum num basic blocks before debug info dropped"), cl::Hidden)
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
Compute iterated dominance frontiers using a linear time algorithm.
static cl::opt< unsigned > StackWorkingSetLimit("livedebugvalues-max-stack-slots", cl::Hidden, cl::desc("livedebugvalues-stack-ws-limit"), cl::init(250))
static cl::opt< bool > EmulateOldLDV("emulate-old-livedebugvalues", cl::Hidden, cl::desc("Act like old LiveDebugValues did"), cl::init(false))
static cl::opt< unsigned > InputBBLimit("livedebugvalues-input-bb-limit", cl::desc("Maximum input basic blocks before DBG_VALUE limit applies"), cl::init(10000), cl::Hidden)
Promote Memory to Register
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
Class storing the complete set of values that are observed by DbgValues within the current function.
DbgOp find(DbgOpID ID) const
Returns the DbgOp associated with ID.
DbgOpID insert(DbgOp Op)
If Op does not already exist in this map, it is inserted and the corresponding DbgOpID is returned.
Meta qualifiers for a value.
const DIExpression * DIExpr
bool isJoinable(const DbgValueProperties &Other) const
unsigned getLocationOpCount() const
Class recording the (high level) value of a variable.
int BlockNo
For a NoVal or VPHI DbgValue, which block it was generated in.
DbgValueProperties Properties
Qualifiers for the ValueIDNum above.
ArrayRef< DbgOpID > getDbgOpIDs() const
void setDbgOpIDs(ArrayRef< DbgOpID > NewIDs)
void dump(const MLocTracker *MTrack=nullptr, const DbgOpIDMap *OpStore=nullptr) const
Definition InstrRefBasedImpl.cpp:1012
bool isUnjoinedPHI() const
DbgOpID getDbgOpID(unsigned Index) const
KindT Kind
Discriminator for whether this is a constant or an in-program value.
unsigned getLocationOpCount() const
Mapping from DebugVariable to/from a unique identifying number.
DenseMap< const LexicalScope *, const DILocation * > ScopeToDILocT
Mapping from lexical scopes to a DILocation in that scope.
std::optional< LocIdx > findLocationForMemOperand(const MachineInstr &MI)
Definition InstrRefBasedImpl.cpp:1414
SmallVector< SmallVector< VarAndLoc, 8 >, 8 > LiveInsT
Vector (per block) of a collection (inner smallvector) of live-ins.
LLVM_ABI_FOR_TEST InstrRefBasedLDV()
Default construct and initialize the pass.
DenseMap< const LexicalScope *, SmallPtrSet< MachineBasicBlock *, 4 > > ScopeToAssignBlocksT
Mapping from lexical scopes to blocks where variables in that scope are assigned.
DIExpression::FragmentInfo FragmentInfo
DenseMap< const LexicalScope *, SmallSet< DebugVariableID, 4 > > ScopeToVarsT
Mapping from lexical scopes to variables in that scope.
SmallDenseMap< const MachineBasicBlock *, DbgValue *, 16 > LiveIdxT
Live in/out structure for the variable values: a per-block map of variables to their values.
SmallDenseMap< LocIdx, ValueIDNum > MLocTransferMap
Machine location/value transfer function, a mapping of which locations are assigned which new values.
bool hasFoldedStackStore(const MachineInstr &MI)
bool isCalleeSaved(LocIdx L) const
Definition InstrRefBasedImpl.cpp:1378
bool isCalleeSavedReg(Register R) const
Definition InstrRefBasedImpl.cpp:1382
LLVM_DUMP_METHOD void dump_mloc_transfer(const MLocTransferMap &mloc_transfer) const
Definition InstrRefBasedImpl.cpp:3449
Handle-class for a particular "location".
static LocIdx MakeIllegalLoc()
Tracker for what values are in machine locations.
unsigned getLocSizeInBits(LocIdx L) const
How large is this location (aka, how wide is a value defined there?).
LLVM_ABI_FOR_TEST std::optional< SpillLocationNo > getOrTrackSpillLoc(SpillLoc L)
Find LocIdx for SpillLoc L, creating a new one if it's not tracked.
Definition InstrRefBasedImpl.cpp:1139
IndexedMap< unsigned, LocIdxToIndexFunctor > LocIdxToLocID
Inverse map of LocIDToLocIdx.
unsigned getSpillIDWithIdx(SpillLocationNo Spill, unsigned Idx)
Given a spill number, and a slot within the spill, calculate the ID number for that location.
iterator_range< MLocIterator > locations()
Return a range over all locations currently tracked.
SmallSet< Register, 8 > SPAliases
When clobbering register masks, we chose to not believe the machine model and don't clobber SP.
unsigned getLocID(Register Reg)
Produce location ID number for a Register.
const TargetLowering & TLI
const TargetRegisterInfo & TRI
unsigned NumRegs
Cached local copy of the number of registers the target has.
DenseMap< StackSlotPos, unsigned > StackSlotIdxes
Map from a size/offset pair describing a position in a stack slot, to a numeric identifier for that p...
LocIdx lookupOrTrackRegister(unsigned ID)
SpillLocationNo locIDToSpill(unsigned ID) const
Return the spill number that a location ID corresponds to.
void reset()
Wipe any un-necessary location records after traversing a block.
DenseMap< unsigned, StackSlotPos > StackIdxesToPos
Inverse of StackSlotIdxes.
std::string IDAsString(const ValueIDNum &Num) const
Definition InstrRefBasedImpl.cpp:1181
void writeRegMask(const MachineOperand *MO, unsigned CurBB, unsigned InstID)
Record a RegMask operand being executed.
Definition InstrRefBasedImpl.cpp:1125
std::pair< unsigned short, unsigned short > StackSlotPos
Pair for describing a position within a stack slot – first the size in bits, then the offset.
const TargetInstrInfo & TII
MachineInstrBuilder emitLoc(const SmallVectorImpl< ResolvedDbgOp > &DbgOps, const DebugVariable &Var, const DILocation *DILoc, const DbgValueProperties &Properties)
Create a DBG_VALUE based on debug operands DbgOps.
Definition InstrRefBasedImpl.cpp:1204
LocToValueType LocIdxToIDNum
Map of LocIdxes to the ValueIDNums that they store.
std::vector< LocIdx > LocIDToLocIdx
"Map" of machine location IDs (i.e., raw register or spill number) to the LocIdx key / number for tha...
SmallVector< std::pair< const MachineOperand *, unsigned >, 32 > Masks
Collection of register mask operands that have been observed.
unsigned NumSlotIdxes
Number of slot indexes the target has – distinct segments of a stack slot that can take on the value ...
UniqueVector< SpillLoc > SpillLocs
Unique-ification of spill.
ValueIDNum readReg(Register R)
void defReg(Register R, unsigned BB, unsigned Inst)
Record a definition of the specified register at the given block / inst.
LLVM_DUMP_METHOD void dump()
Definition InstrRefBasedImpl.cpp:1187
LLVM_ABI_FOR_TEST LocIdx trackRegister(unsigned ID)
Create a LocIdx for an untracked register ID.
Definition InstrRefBasedImpl.cpp:1103
LLVM_ABI_FOR_TEST MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const TargetLowering &TLI)
Definition InstrRefBasedImpl.cpp:1035
LLVM_DUMP_METHOD void dump_mloc_map()
Definition InstrRefBasedImpl.cpp:1195
StackSlotPos locIDToSpillIdx(unsigned ID) const
Returns the spill-slot size/offs that a location ID corresponds to.
std::string LocIdxToName(LocIdx Idx) const
Definition InstrRefBasedImpl.cpp:1166
Thin wrapper around an integer – designed to give more type safety to spill location numbers.
SmallMapVector< DebugVariableID, DbgValue, 8 > Vars
Map DebugVariable to the latest Value it's defined to have.
Unique identifier for a value defined by an instruction, as a value type.
static ValueIDNum fromU64(uint64_t v)
std::string asString(const std::string &mlocname) const
static LLVM_ABI_FOR_TEST ValueIDNum EmptyValue
static LLVM_ABI_FOR_TEST ValueIDNum TombstoneValue
uint64_t getBlock() const
LocationAndQuality(LocIdx L, LocationQuality Q)
Definition InstrRefBasedImpl.cpp:309
LocationQuality getQuality() const
Definition InstrRefBasedImpl.cpp:316
LocIdx getLoc() const
Definition InstrRefBasedImpl.cpp:311
bool isBest() const
Definition InstrRefBasedImpl.cpp:318
bool isIllegal() const
Definition InstrRefBasedImpl.cpp:317
LocationAndQuality()
Definition InstrRefBasedImpl.cpp:308
const DebugVariableMap & DVMap
Definition InstrRefBasedImpl.cpp:185
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, MachineFunction &MF, const DebugVariableMap &DVMap, const TargetRegisterInfo &TRI, const BitVector &CalleeSavedRegs, bool ShouldEmitDebugEntryValues)
Definition InstrRefBasedImpl.cpp:269
DenseSet< DebugVariableID > UseBeforeDefVariables
The set of variables that are in UseBeforeDefs and can become a location once the relevant value is d...
Definition InstrRefBasedImpl.cpp:264
const BitVector & CalleeSavedRegs
Definition InstrRefBasedImpl.cpp:267
void loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, const SmallVectorImpl< std::pair< DebugVariableID, DbgValue > > &VLocs, unsigned NumLocs)
Load object with live-in variable values.
Definition InstrRefBasedImpl.cpp:459
const TargetLowering * TLI
Definition InstrRefBasedImpl.cpp:179
void addUseBeforeDef(DebugVariableID VarID, const DbgValueProperties &Properties, const SmallVectorImpl< DbgOp > &DbgOps, unsigned Inst)
Record that Var has value ID, a value that becomes available later in the function.
Definition InstrRefBasedImpl.cpp:520
SmallVector< ValueIDNum, 32 > VarLocs
Local cache of what-value-is-in-what-LocIdx.
Definition InstrRefBasedImpl.cpp:227
MLocTracker * MTracker
This machine location tracker is assumed to always contain the up-to-date value mapping for all machi...
Definition InstrRefBasedImpl.cpp:183
void transferMlocs(LocIdx Src, LocIdx Dst, MachineBasicBlock::iterator Pos)
Transfer variables based on Src to be based on Dst.
Definition InstrRefBasedImpl.cpp:927
MachineFunction & MF
Definition InstrRefBasedImpl.cpp:184
std::optional< LocationQuality > getLocQualityIfBetter(LocIdx L, LocationQuality Min) const
Definition InstrRefBasedImpl.cpp:331
SmallVector< std::pair< DebugVariableID, MachineInstr * >, 4 > PendingDbgValues
Temporary cache of DBG_VALUEs to be entered into the Transfers collection.
Definition InstrRefBasedImpl.cpp:240
bool isEntryValueVariable(const DebugVariable &Var, const DIExpression *Expr) const
Definition InstrRefBasedImpl.cpp:628
void checkInstForNewValues(unsigned Inst, MachineBasicBlock::iterator pos)
After the instruction at index Inst and position pos has been processed, check whether it defines a v...
Definition InstrRefBasedImpl.cpp:531
const TargetInstrInfo * TII
Definition InstrRefBasedImpl.cpp:178
LocationQuality
Definition InstrRefBasedImpl.cpp:295
@ Register
Definition InstrRefBasedImpl.cpp:297
@ CalleeSavedRegister
Definition InstrRefBasedImpl.cpp:298
@ Best
Definition InstrRefBasedImpl.cpp:300
@ Illegal
Definition InstrRefBasedImpl.cpp:296
@ SpillSlot
Definition InstrRefBasedImpl.cpp:299
DenseMap< LocIdx, SmallSet< DebugVariableID, 4 > > ActiveMLocs
Map from LocIdxes to which DebugVariables are based that location.
Definition InstrRefBasedImpl.cpp:232
MachineInstrBuilder emitMOLoc(const MachineOperand &MO, const DebugVariable &Var, const DbgValueProperties &Properties)
Definition InstrRefBasedImpl.cpp:965
bool isEntryValueValue(const ValueIDNum &Val) const
Definition InstrRefBasedImpl.cpp:642
const TargetRegisterInfo & TRI
Definition InstrRefBasedImpl.cpp:266
void redefVar(const MachineInstr &MI)
Change a variable value after encountering a DBG_VALUE inside a block.
Definition InstrRefBasedImpl.cpp:709
bool recoverAsEntryValue(DebugVariableID VarID, const DbgValueProperties &Prop, const ValueIDNum &Num)
Definition InstrRefBasedImpl.cpp:657
bool isCalleeSaved(LocIdx L) const
Definition InstrRefBasedImpl.cpp:280
void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos, bool MakeUndef=true)
Account for a location mloc being clobbered.
Definition InstrRefBasedImpl.cpp:818
void flushDbgValues(MachineBasicBlock::iterator Pos, MachineBasicBlock *MBB)
Helper to move created DBG_VALUEs into Transfers collection.
Definition InstrRefBasedImpl.cpp:613
DenseMap< DebugVariableID, ResolvedDbgValue > ActiveVLocs
Map from DebugVariable to it's current location and qualifying meta information.
Definition InstrRefBasedImpl.cpp:237
DenseMap< unsigned, SmallVector< UseBeforeDef, 1 > > UseBeforeDefs
Map from instruction index (within the block) to the set of UseBeforeDefs that become defined at that...
Definition InstrRefBasedImpl.cpp:259
void clobberMloc(LocIdx MLoc, ValueIDNum OldValue, MachineBasicBlock::iterator Pos, bool MakeUndef=true)
Overload that takes an explicit value OldValue for when the value in MLoc has changed and the Transfe...
Definition InstrRefBasedImpl.cpp:831
SmallVector< Transfer, 32 > Transfers
Collection of transfers (DBG_VALUEs) to be inserted.
Definition InstrRefBasedImpl.cpp:221
bool ShouldEmitDebugEntryValues
Definition InstrRefBasedImpl.cpp:186
void redefVar(const MachineInstr &MI, const DbgValueProperties &Properties, SmallVectorImpl< ResolvedDbgOp > &NewLocs)
Handle a change in variable location within a block.
Definition InstrRefBasedImpl.cpp:748
void loadVarInloc(MachineBasicBlock &MBB, DbgOpIDMap &DbgOpStore, const SmallVectorImpl< ValueLocPair > &ValueToLoc, DebugVariableID VarID, DbgValue Value)
For a variable Var with the live-in value Value, attempts to resolve the DbgValue to a concrete DBG_V...
Definition InstrRefBasedImpl.cpp:355
std::pair< ValueIDNum, LocationAndQuality > ValueLocPair
Definition InstrRefBasedImpl.cpp:321
static bool ValueToLocSort(const ValueLocPair &A, const ValueLocPair &B)
Definition InstrRefBasedImpl.cpp:323
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator_range< const_set_bits_iterator > set_bits() const
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
unsigned getNumElements() const
LLVM_ABI bool isImplicit() const
Return whether this is an implicit location description.
static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)
Check if fragments overlap between a pair of FragmentInfos.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
LLVM_ABI bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static LLVM_ABI std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
LLVM_ABI bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
LLVM_ABI bool isSingleLocationExpression() const
Return whether the evaluated expression makes use of a single location at the start of the expression...
DILocalScope * getScope() const
Get the local scope for this variable.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
LLVM_ABI std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
Identifies a unique instance of a variable.
const DILocation * getInlinedAt() const
std::optional< FragmentInfo > getFragment() const
const DILocalVariable * getVariable() const
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
DISubprogram * getSubprogram() const
Get the attached subprogram.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
unsigned getDFSIn() const
SmallVectorImpl< LexicalScope * > & getChildren()
unsigned getDFSOut() const
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
MCRegAliasIterator enumerates all registers aliasing Reg.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
SmallVectorImpl< MachineBasicBlock * >::const_iterator const_succ_iterator
succ_iterator succ_begin()
LLVM_ABI bool isEntryBlock() const
Returns true if this is the entry block of the function.
SmallVectorImpl< MachineBasicBlock * >::iterator pred_iterator
Instructions::iterator instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI std::string getFullName() const
Return a formatted string to identify this block and its parent function.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
instr_iterator insertAfterBundle(instr_iterator I, MachineInstr *MI)
If I is bundled then insert MI into the instruction list after the end of the bundle,...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
SmallVector< DebugSubstitution, 8 > DebugValueSubstitutions
Debug value substitutions: a collection of DebugSubstitution objects, recording changes in where a va...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static const unsigned int DebugOperandMemNumber
A reserved operand number representing the instructions memory operand, for instructions that have a ...
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getInstrRefOpIndex() const
unsigned getInstrRefInstrIndex() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
static unsigned getRegMaskSize(unsigned NumRegs)
Returns number of elements needed for a regmask array.
Register getReg() const
getReg - Returns the register number.
bool isDbgInstrRef() const
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
Special value supplied for machine level alias analysis.
virtual bool isAliased(const MachineFrameInfo *) const
Test whether the memory pointed to by this PseudoSourceValue may also be pointed to by an LLVM IR Val...
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Iterator for PHI operands.
Definition InstrRefBasedImpl.cpp:4046
BlockValueNum getIncomingValue()
Definition InstrRefBasedImpl.cpp:4064
PHI_iterator(LDVSSAPhi *P, bool)
Definition InstrRefBasedImpl.cpp:4054
LDVSSABlock * getIncomingBlock()
Definition InstrRefBasedImpl.cpp:4066
bool operator!=(const PHI_iterator &X) const
Definition InstrRefBasedImpl.cpp:4062
PHI_iterator(LDVSSAPhi *P)
Definition InstrRefBasedImpl.cpp:4052
PHI_iterator & operator++()
Definition InstrRefBasedImpl.cpp:4057
bool operator==(const PHI_iterator &X) const
Definition InstrRefBasedImpl.cpp:4061
LDVSSABlockIterator BlkSucc_iterator
Definition InstrRefBasedImpl.cpp:4039
static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds, LDVSSAUpdater *Updater)
CreateEmptyPHI - Create a (representation of a) PHI in the given block.
Definition InstrRefBasedImpl.cpp:4100
static BlockValueNum GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater)
GetPoisonVal - Normally creates an IMPLICIT_DEF instruction with a new register.
Definition InstrRefBasedImpl.cpp:4086
static BlkSucc_iterator BlkSucc_end(BlkT *BB)
Definition InstrRefBasedImpl.cpp:4043
LDVSSABlock BlkT
Definition InstrRefBasedImpl.cpp:4036
static PHI_iterator PHI_begin(PhiT *PHI)
Definition InstrRefBasedImpl.cpp:4069
static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred)
AddPHIOperand - Add the specified value as an operand of the PHI for the specified predecessor block.
Definition InstrRefBasedImpl.cpp:4110
LDVSSAPhi PhiT
Definition InstrRefBasedImpl.cpp:4038
static void FindPredecessorBlocks(LDVSSABlock *BB, SmallVectorImpl< LDVSSABlock * > *Preds)
FindPredecessorBlocks - Put the predecessors of BB into the Preds vector.
Definition InstrRefBasedImpl.cpp:4077
static BlockValueNum GetPHIValue(LDVSSAPhi *PHI)
GetPHIValue - For the specified PHI instruction, return the value that it defines.
Definition InstrRefBasedImpl.cpp:4131
static LDVSSAPhi * ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater)
ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source operands, i....
Definition InstrRefBasedImpl.cpp:4122
BlockValueNum ValT
Definition InstrRefBasedImpl.cpp:4037
static PHI_iterator PHI_end(PhiT *PHI)
Definition InstrRefBasedImpl.cpp:4071
static LDVSSAPhi * ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater)
ValueIsPHI - Check if the instruction that defines the specified value is a PHI instruction.
Definition InstrRefBasedImpl.cpp:4116
static BlkSucc_iterator BlkSucc_begin(BlkT *BB)
Definition InstrRefBasedImpl.cpp:4042
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
void insert_range(Range &&R)
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
virtual bool stackProbeFunctionModifiesSP() const
Does the stack probe function call return with a modified stack pointer?
virtual void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetInstrInfo - Interface to description of machine instruction set.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Twine concat(const Twine &Suffix) const
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< ValueIDNum, 0 > ValueTable
Type for a table of values in a block.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
std::tuple< const DIScope *, const DIScope *, const DILocalVariable * > VarID
A unique key that represents a debug variable.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
MachineBasicBlock::instr_iterator getBundleStart(MachineBasicBlock::instr_iterator I)
Returns an iterator to the first instruction in the bundle containing I.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
APInt operator*(APInt a, uint64_t RHS)
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LDVImpl * makeInstrRefBasedLiveDebugValues()
Definition InstrRefBasedImpl.cpp:3884
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace_copy which take ranges instead of having to pass begin/end explicitl...
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
An ID used in the DbgOpIDMap (below) to lookup a stored DbgOp.
void dump(const MLocTracker *MTrack, const DbgOpIDMap *OpStore) const
Definition InstrRefBasedImpl.cpp:1005
static LLVM_ABI_FOR_TEST DbgOpID UndefID
TODO: Might pack better if we changed this to a Struct of Arrays, since MachineOperand is width 32,...
void dump(const MLocTracker *MTrack) const
Definition InstrRefBasedImpl.cpp:998
A collection of ValueTables, one per BB in a function, with convenient accessor methods.
void ejectTableForBlock(const MachineBasicBlock &MBB)
Frees the memory of the ValueTable associated with MBB.
ValueTable & tableForEntryMBB() const
Returns the ValueTable associated with the entry MachineBasicBlock.
bool hasTableFor(MachineBasicBlock &MBB) const
Returns true if the ValueTable associated with MBB has not been freed.
A DbgOp whose ID (if any) has resolved to an actual location, LocIdx.
void dump(const MLocTracker *MTrack) const
Definition InstrRefBasedImpl.cpp:991
Stores the resolved operands (machine locations and constants) and qualifying meta-information needed...
Definition InstrRefBasedImpl.cpp:202
SmallVector< ResolvedDbgOp > Ops
Definition InstrRefBasedImpl.cpp:203
DbgValueProperties Properties
Definition InstrRefBasedImpl.cpp:204
ResolvedDbgValue(SmallVectorImpl< ResolvedDbgOp > &Ops, DbgValueProperties Properties)
Definition InstrRefBasedImpl.cpp:206
auto loc_indices() const
Returns all the LocIdx values used in this struct, in the order in which they appear as operands in t...
Definition InstrRefBasedImpl.cpp:212
Record of all changes in variable locations at a block position.
Definition InstrRefBasedImpl.cpp:191
SmallVector< std::pair< DebugVariableID, MachineInstr * >, 4 > Insts
non-null if we should insert after.
Definition InstrRefBasedImpl.cpp:196
MachineBasicBlock * MBB
Position to insert DBG_VALUes.
Definition InstrRefBasedImpl.cpp:193
MachineBasicBlock::instr_iterator Pos
Definition InstrRefBasedImpl.cpp:192
UseBeforeDef(ArrayRef< DbgOp > Values, DebugVariableID VarID, const DbgValueProperties &Properties)
Definition InstrRefBasedImpl.cpp:252
DbgValueProperties Properties
Additional variable properties.
Definition InstrRefBasedImpl.cpp:251
DebugVariableID VarID
Identity of this variable.
Definition InstrRefBasedImpl.cpp:249
SmallVector< DbgOp > Values
Value of this variable, def'd in block.
Definition InstrRefBasedImpl.cpp:247