LLVM: lib/CodeGen/LiveDebugValues/VarLocBasedImpl.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

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

114

136#include "llvm/Config/llvm-config.h"

146#include

147#include

148#include

149#include

150#include

151#include

152#include

153#include

154#include

155

156using namespace llvm;

157

158#define DEBUG_TYPE "livedebugvalues"

159

160STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted");

161

162

163

164

168 if (Op.isReg())

169 return false;

170

176

178}

179

180namespace {

181

182

183

185

186

187

188

189

190

191

192

194

195

196

197

198

199

200

201

202

203struct LocIndex {

204 using u32_location_t = uint32_t;

205 using u32_index_t = uint32_t;

206

207 u32_location_t Location;

208

209

210 u32_index_t Index;

211

212

213 static constexpr u32_location_t kUniversalLocation = 0;

214

215

216

217 static constexpr u32_location_t kFirstRegLocation = 1;

218

219

220

221 static constexpr u32_location_t kFirstInvalidRegLocation = 1 << 30;

222

223

224

225 static constexpr u32_location_t kSpillLocation = kFirstInvalidRegLocation;

226

227

228

229 static constexpr u32_location_t kEntryValueBackupLocation =

230 kFirstInvalidRegLocation + 1;

231

232

233

234

235

236

237

238 static constexpr u32_location_t kWasmLocation = kFirstInvalidRegLocation + 2;

239

240

241

242 static constexpr u32_location_t kFirstVirtualRegLocation = 1 << 31;

243

244 LocIndex(u32_location_t Location, u32_index_t Index)

245 : Location(Location), Index(Index) {}

246

247 uint64_t getAsRawInteger() const {

248 return (static_cast<uint64_t>(Location) << 32) | Index;

249 }

250

251 template static LocIndex fromRawInteger(IntT ID) {

252 static_assert(std::is_unsigned_v && sizeof(ID) == sizeof(uint64_t),

253 "Cannot convert raw integer to LocIndex");

254 return {static_cast<u32_location_t>(ID >> 32),

255 static_cast<u32_index_t>(ID)};

256 }

257

258

259

260 static uint64_t rawIndexForReg(Register Reg) {

261 return LocIndex(Reg, 0).getAsRawInteger();

262 }

263

264

265

266 static auto indexRangeForLocation(const VarLocSet &Set,

267 u32_location_t Location) {

268 uint64_t Start = LocIndex(Location, 0).getAsRawInteger();

269 uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();

270 return Set.half_open_range(Start, End);

271 }

272};

273

274

276

277

278

280

281class VarLocBasedLDV : public LDVImpl {

282private:

283 const TargetRegisterInfo *TRI;

284 const TargetInstrInfo *TII;

285 const TargetFrameLowering *TFI;

286 bool ShouldEmitDebugEntryValues;

287 BitVector CalleeSavedRegs;

288 LexicalScopes LS;

289 VarLocSet::Allocator Alloc;

290

291 const MachineInstr *LastNonDbgMI;

292

293 enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };

294

296 using OptFragmentInfo = std::optionalDIExpression::FragmentInfo;

297

298

299 struct VarLoc {

300

301

302 struct SpillLoc {

303 unsigned SpillBase;

304 StackOffset SpillOffset;

306 return SpillBase == Other.SpillBase && SpillOffset == Other.SpillOffset;

307 }

309 return !(*this == Other);

310 }

311 };

312

313

314 struct WasmLoc {

315

316

317

318

319

320 int Index;

321 int64_t Offset;

323 return Index == Other.Index && Offset == Other.Offset;

324 }

326 };

327

328

329 const DebugVariable Var;

330

331

332 const DIExpression *Expr;

333

334

335

336 const MachineInstr &MI;

337

338 enum class MachineLocKind {

339 InvalidKind = 0,

340 RegisterKind,

341 SpillLocKind,

342 ImmediateKind,

343 WasmLocKind

344 };

345

346 enum class EntryValueLocKind {

347 NonEntryValueKind = 0,

348 EntryValueKind,

349 EntryValueBackupKind,

350 EntryValueCopyBackupKind

351 } EVKind = EntryValueLocKind::NonEntryValueKind;

352

353

354

355 union MachineLocValue {

356 uint64_t RegNo;

357 SpillLoc SpillLocation;

358 uint64_t Hash;

359 int64_t Immediate;

361 const ConstantInt *CImm;

362 WasmLoc WasmLocation;

363 MachineLocValue() : Hash(0) {}

364 };

365

366

367

368

369

370 struct MachineLoc {

371 MachineLocKind Kind;

372 MachineLocValue Value;

374 if (Kind != Other.Kind)

375 return false;

376 switch (Kind) {

377 case MachineLocKind::SpillLocKind:

378 return Value.SpillLocation == Other.Value.SpillLocation;

379 case MachineLocKind::WasmLocKind:

380 return Value.WasmLocation == Other.Value.WasmLocation;

381 case MachineLocKind::RegisterKind:

382 case MachineLocKind::ImmediateKind:

383 return Value.Hash == Other.Value.Hash;

384 default:

386 }

387 }

389 switch (Kind) {

390 case MachineLocKind::SpillLocKind:

391 return std::make_tuple(

392 Kind, Value.SpillLocation.SpillBase,

393 Value.SpillLocation.SpillOffset.getFixed(),

394 Value.SpillLocation.SpillOffset.getScalable()) <

395 std::make_tuple(

396 Other.Kind, Other.Value.SpillLocation.SpillBase,

397 Other.Value.SpillLocation.SpillOffset.getFixed(),

398 Other.Value.SpillLocation.SpillOffset.getScalable());

399 case MachineLocKind::WasmLocKind:

400 return std::make_tuple(Kind, Value.WasmLocation.Index,

401 Value.WasmLocation.Offset) <

402 std::make_tuple(Other.Kind, Other.Value.WasmLocation.Index,

403 Other.Value.WasmLocation.Offset);

404 case MachineLocKind::RegisterKind:

405 case MachineLocKind::ImmediateKind:

406 return std::tie(Kind, Value.Hash) <

407 std::tie(Other.Kind, Other.Value.Hash);

408 default:

410 }

411 }

412 };

413

414

415

416

418

419

420

421

422 SmallVector<unsigned, 8> OrigLocMap;

423

424 VarLoc(const MachineInstr &MI)

425 : Var(MI.getDebugVariable(), MI.getDebugExpression(),

427 Expr(MI.getDebugExpression()), MI(MI) {

428 assert(MI.isDebugValue() && "not a DBG_VALUE");

429 assert((MI.isDebugValueList() || MI.getNumOperands() == 4) &&

430 "malformed DBG_VALUE");

431 for (const MachineOperand &Op : MI.debug_operands()) {

432 MachineLoc ML = GetLocForOp(Op);

433 auto It = find(Locs, ML);

434 if (It == Locs.end()) {

435 Locs.push_back(ML);

436 OrigLocMap.push_back(MI.getDebugOperandIndex(&Op));

437 } else {

438

439

440 unsigned OpIdx = Locs.size();

441 unsigned DuplicatingIdx = std::distance(Locs.begin(), It);

443 }

444 }

445

446

447

448 assert(EVKind != EntryValueLocKind::EntryValueKind &&

449 !isEntryBackupLoc());

450 }

451

452 static MachineLoc GetLocForOp(const MachineOperand &Op) {

453 MachineLocKind Kind;

454 MachineLocValue Loc;

455 if (Op.isReg()) {

456 Kind = MachineLocKind::RegisterKind;

457 Loc.RegNo = Op.getReg();

458 } else if (Op.isImm()) {

459 Kind = MachineLocKind::ImmediateKind;

460 Loc.Immediate = Op.getImm();

461 } else if (Op.isFPImm()) {

462 Kind = MachineLocKind::ImmediateKind;

463 Loc.FPImm = Op.getFPImm();

464 } else if (Op.isCImm()) {

465 Kind = MachineLocKind::ImmediateKind;

466 Loc.CImm = Op.getCImm();

467 } else if (Op.isTargetIndex()) {

468 Kind = MachineLocKind::WasmLocKind;

469 Loc.WasmLocation = {Op.getIndex(), Op.getOffset()};

470 } else

472 return {Kind, Loc};

473 }

474

475

476

477 static VarLoc CreateEntryLoc(const MachineInstr &MI,

478 const DIExpression *EntryExpr, Register Reg) {

479 VarLoc VL(MI);

480 assert(VL.Locs.size() == 1 &&

481 VL.Locs[0].Kind == MachineLocKind::RegisterKind);

482 VL.EVKind = EntryValueLocKind::EntryValueKind;

483 VL.Expr = EntryExpr;

484 VL.Locs[0].Value.RegNo = Reg;

485 return VL;

486 }

487

488

489

490

491

492 static VarLoc CreateEntryBackupLoc(const MachineInstr &MI,

493 const DIExpression *EntryExpr) {

494 VarLoc VL(MI);

495 assert(VL.Locs.size() == 1 &&

496 VL.Locs[0].Kind == MachineLocKind::RegisterKind);

497 VL.EVKind = EntryValueLocKind::EntryValueBackupKind;

498 VL.Expr = EntryExpr;

499 return VL;

500 }

501

502

503

504

505 static VarLoc CreateEntryCopyBackupLoc(const MachineInstr &MI,

506 const DIExpression *EntryExpr,

508 VarLoc VL(MI);

509 assert(VL.Locs.size() == 1 &&

510 VL.Locs[0].Kind == MachineLocKind::RegisterKind);

511 VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;

512 VL.Expr = EntryExpr;

513 VL.Locs[0].Value.RegNo = NewReg;

514 return VL;

515 }

516

517

518

519 static VarLoc CreateCopyLoc(const VarLoc &OldVL, const MachineLoc &OldML,

521 VarLoc VL = OldVL;

522 for (MachineLoc &ML : VL.Locs)

523 if (ML == OldML) {

524 ML.Kind = MachineLocKind::RegisterKind;

525 ML.Value.RegNo = NewReg;

526 return VL;

527 }

529 }

530

531

532

533 static VarLoc CreateSpillLoc(const VarLoc &OldVL, const MachineLoc &OldML,

534 unsigned SpillBase, StackOffset SpillOffset) {

535 VarLoc VL = OldVL;

536 for (MachineLoc &ML : VL.Locs)

537 if (ML == OldML) {

538 ML.Kind = MachineLocKind::SpillLocKind;

539 ML.Value.SpillLocation = {SpillBase, SpillOffset};

540 return VL;

541 }

543 }

544

545

546

547

548

549 MachineInstr *BuildDbgValue(MachineFunction &MF) const {

550 assert(!isEntryBackupLoc() &&

551 "Tried to produce DBG_VALUE for backup VarLoc");

552 const DebugLoc &DbgLoc = MI.getDebugLoc();

553 bool Indirect = MI.isIndirectDebugValue();

554 const auto &IID = MI.getDesc();

555 const DILocalVariable *Var = MI.getDebugVariable();

556 NumInserted++;

557

558 const DIExpression *DIExpr = Expr;

560 for (unsigned I = 0, E = Locs.size(); I < E; ++I) {

561 MachineLocKind LocKind = Locs[I].Kind;

562 MachineLocValue Loc = Locs[I].Value;

563 const MachineOperand &Orig = MI.getDebugOperand(OrigLocMap[I]);

564 switch (LocKind) {

565 case MachineLocKind::RegisterKind:

566

567

568

569

570

571

573 EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()

575 false));

576 break;

577 case MachineLocKind::SpillLocKind: {

578

579

580

581

582 unsigned Base = Loc.SpillLocation.SpillBase;

584 if (MI.isNonListDebugValue()) {

586 DIExpr = TRI->prependOffsetExpression(

588 Loc.SpillLocation.SpillOffset);

590 } else {

591 SmallVector<uint64_t, 4> Ops;

592 TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset, Ops);

593 Ops.push_back(dwarf::DW_OP_deref);

595 }

597 break;

598 }

599 case MachineLocKind::ImmediateKind: {

601 break;

602 }

603 case MachineLocKind::WasmLocKind: {

605 break;

606 }

607 case MachineLocKind::InvalidKind:

608 llvm_unreachable("Tried to produce DBG_VALUE for invalid VarLoc");

609 }

610 }

611 return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);

612 }

613

614

615 bool isConstant(MachineLocKind Kind) const {

616 return Kind == MachineLocKind::ImmediateKind;

617 }

618

619

620 bool isEntryBackupLoc() const {

621 return EVKind == EntryValueLocKind::EntryValueBackupKind ||

622 EVKind == EntryValueLocKind::EntryValueCopyBackupKind;

623 }

624

625

626

627 bool isEntryValueBackupReg(Register Reg) const {

628 return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(Reg);

629 }

630

631

632

633 bool isEntryValueCopyBackupReg(Register Reg) const {

634 return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&

635 usesReg(Reg);

636 }

637

638

640 MachineLoc RegML;

641 RegML.Kind = MachineLocKind::RegisterKind;

642 RegML.Value.RegNo = Reg;

644 }

645

646

648 for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)

649 if (Locs[Idx].Kind == MachineLocKind::RegisterKind &&

650 Register{static_cast<unsigned>(Locs[Idx].Value.RegNo)} == Reg)

651 return Idx;

653 }

654

655

656

657 bool getDescribingRegs(SmallVectorImpl<uint32_t> &Regs) const {

658 bool AnyRegs = false;

659 for (const auto &Loc : Locs)

660 if (Loc.Kind == MachineLocKind::RegisterKind) {

662 AnyRegs = true;

663 }

664 return AnyRegs;

665 }

666

667 bool containsSpillLocs() const {

668 return any_of(Locs, [](VarLoc::MachineLoc ML) {

669 return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;

670 });

671 }

672

673

674

675 bool usesSpillLoc(SpillLoc SpillLocation) const {

676 MachineLoc SpillML;

677 SpillML.Kind = MachineLocKind::SpillLocKind;

678 SpillML.Value.SpillLocation = SpillLocation;

680 }

681

682

683

684 unsigned getSpillLocIdx(SpillLoc SpillLocation) const {

685 for (unsigned Idx = 0; Idx < Locs.size(); ++Idx)

686 if (Locs[Idx].Kind == MachineLocKind::SpillLocKind &&

687 Locs[Idx].Value.SpillLocation == SpillLocation)

688 return Idx;

690 }

691

692 bool containsWasmLocs() const {

693 return any_of(Locs, [](VarLoc::MachineLoc ML) {

694 return ML.Kind == VarLoc::MachineLocKind::WasmLocKind;

695 });

696 }

697

698

699

700 bool usesWasmLoc(WasmLoc WasmLocation) const {

701 MachineLoc WasmML;

702 WasmML.Kind = MachineLocKind::WasmLocKind;

703 WasmML.Value.WasmLocation = WasmLocation;

705 }

706

707

708

709 bool dominates(LexicalScopes &LS, MachineBasicBlock &MBB) const {

710 return LS.dominates(MI.getDebugLoc().get(), &MBB);

711 }

712

713#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

714

715 void dump(const TargetRegisterInfo *TRI, const TargetInstrInfo *TII,

716 raw_ostream &Out = dbgs()) const {

717 Out << "VarLoc(";

718 for (const MachineLoc &MLoc : Locs) {

719 if (Locs.begin() != &MLoc)

720 Out << ", ";

721 switch (MLoc.Kind) {

722 case MachineLocKind::RegisterKind:

724 break;

725 case MachineLocKind::SpillLocKind:

726 Out << printReg(MLoc.Value.SpillLocation.SpillBase, TRI);

727 Out << "[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() << " + "

728 << MLoc.Value.SpillLocation.SpillOffset.getScalable()

729 << "x vscale"

730 << "]";

731 break;

732 case MachineLocKind::ImmediateKind:

733 Out << MLoc.Value.Immediate;

734 break;

735 case MachineLocKind::WasmLocKind: {

736 if (TII) {

737 auto Indices = TII->getSerializableTargetIndices();

738 auto Found =

739 find_if(Indices, [&](const std::pair<int, const char *> &I) {

740 return I.first == MLoc.Value.WasmLocation.Index;

741 });

742 assert(Found != Indices.end());

743 Out << Found->second;

744 if (MLoc.Value.WasmLocation.Offset > 0)

745 Out << " + " << MLoc.Value.WasmLocation.Offset;

746 } else {

747 Out << "WasmLoc";

748 }

749 break;

750 }

751 case MachineLocKind::InvalidKind:

753 }

754 }

755

756 Out << ", \"" << Var.getVariable()->getName() << "\", " << *Expr << ", ";

757 if (Var.getInlinedAt())

758 Out << "!" << Var.getInlinedAt()->getMetadataID() << ")\n";

759 else

760 Out << "(null))";

761

762 if (isEntryBackupLoc())

763 Out << " (backup loc)\n";

764 else

765 Out << "\n";

766 }

767#endif

768

770 return std::tie(EVKind, Var, Expr, Locs) ==

772 }

773

774

776 return std::tie(Var, EVKind, Locs, Expr) <

778 }

779 };

780

781#ifndef NDEBUG

782 using VarVec = SmallVector<VarLoc, 32>;

783#endif

784

785

786

787

788

789 class VarLocMap {

790

791

792 std::map<VarLoc, LocIndices> Var2Indices;

793

794

795

796 SmallDenseMap<LocIndex::u32_location_t, std::vector> Loc2Vars;

797

798 public:

799

800 LocIndices insert(const VarLoc &VL) {

801 LocIndices &Indices = Var2Indices[VL];

802

803 if (!Indices.empty())

804 return Indices;

806

807

808

809

810

811 if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {

812 VL.getDescribingRegs(Locations);

814 [](auto RegNo) {

815 return (RegNo < LocIndex::kFirstInvalidRegLocation) ||

816 (LocIndex::kFirstVirtualRegLocation <= RegNo);

817 }) &&

818 "Physical or virtual register out of range?");

819 if (VL.containsSpillLocs())

820 Locations.push_back(LocIndex::kSpillLocation);

821 if (VL.containsWasmLocs())

822 Locations.push_back(LocIndex::kWasmLocation);

823 } else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {

824 LocIndex::u32_location_t Loc = LocIndex::kEntryValueBackupLocation;

826 }

827 Locations.push_back(LocIndex::kUniversalLocation);

828 for (LocIndex::u32_location_t Location : Locations) {

829 auto &Vars = Loc2Vars[Location];

830 Indices.push_back(

831 {Location, static_castLocIndex::u32\_index\_t\(Vars.size())});

832 Vars.push_back(VL);

833 }

834 return Indices;

835 }

836

837 LocIndices getAllIndices(const VarLoc &VL) const {

838 auto IndIt = Var2Indices.find(VL);

839 assert(IndIt != Var2Indices.end() && "VarLoc not tracked");

840 return IndIt->second;

841 }

842

843

844 const VarLoc &operator[](LocIndex ID) const {

845 auto LocIt = Loc2Vars.find(ID.Location);

846 assert(LocIt != Loc2Vars.end() && "Location not tracked");

847 return LocIt->second[ID.Index];

848 }

849 };

850

851 using VarLocInMBB =

852 SmallDenseMap<const MachineBasicBlock *, std::unique_ptr>;

853 struct TransferDebugPair {

854 MachineInstr *TransferInst;

855 LocIndex LocationID;

856 };

857 using TransferMap = SmallVector<TransferDebugPair, 4>;

858

859

860 using InstToEntryLocMap = std::multimap<const MachineInstr *, LocIndex>;

861 using RegDefToInstMap = DenseMap<Register, MachineInstr *>;

862

863

864

865

866 using FragmentOfVar =

867 std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;

868 using OverlapMap =

869 DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;

870

871

872

873 using VarToFragments =

874 DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;

875

876

877

878 static void collectAllVarLocs(SmallVectorImpl &Collected,

879 const VarLocSet &CollectFrom,

880 const VarLocMap &VarLocIDs);

881

882

883

884 void getUsedRegs(const VarLocSet &CollectFrom,

885 SmallVectorImpl &UsedRegs) const;

886

887

888

889

890

891

892

893

894

895

896 class OpenRangesSet {

897 VarLocSet::Allocator &Alloc;

898 VarLocSet VarLocs;

899

900 SmallDenseMap<DebugVariable, LocIndices, 8> Vars;

901

902 SmallDenseMap<DebugVariable, LocIndices, 8> EntryValuesBackupVars;

904

905 public:

906 OpenRangesSet(VarLocSet::Allocator &Alloc, OverlapMap &_OLapMap)

907 : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}

908

909 const VarLocSet &getVarLocs() const { return VarLocs; }

910

911

912

913

914

915

916 void getUniqueVarLocs(SmallVectorImpl &Collected,

917 const VarLocMap &VarLocIDs) const {

918 collectAllVarLocs(Collected, VarLocs, VarLocIDs);

919 }

920

921

922 void erase(const VarLoc &VL);

923

924

925

926 void erase(const VarLocsInRange &KillSet, const VarLocMap &VarLocIDs,

927 LocIndex::u32_location_t Location);

928

929

930 void insert(LocIndices VarLocIDs, const VarLoc &VL);

931

932

933 void insertFromLocSet(const VarLocSet &ToLoad, const VarLocMap &Map);

934

935 std::optional getEntryValueBackup(DebugVariable Var);

936

937

938 void clear() {

939 VarLocs.clear();

940 Vars.clear();

941 EntryValuesBackupVars.clear();

942 }

943

944

945 bool empty() const {

946 assert(Vars.empty() == EntryValuesBackupVars.empty() &&

947 Vars.empty() == VarLocs.empty() &&

948 "open ranges are inconsistent");

949 return VarLocs.empty();

950 }

951

952

953 auto getEmptyVarLocRange() const {

955 getVarLocs().end());

956 }

957

958

959 auto getRegisterVarLocs(Register Reg) const {

960 return LocIndex::indexRangeForLocation(getVarLocs(), Reg);

961 }

962

963

964 auto getSpillVarLocs() const {

965 return LocIndex::indexRangeForLocation(getVarLocs(),

966 LocIndex::kSpillLocation);

967 }

968

969

970

971 auto getEntryValueBackupVarLocs() const {

972 return LocIndex::indexRangeForLocation(

973 getVarLocs(), LocIndex::kEntryValueBackupLocation);

974 }

975

976

977 auto getWasmVarLocs() const {

978 return LocIndex::indexRangeForLocation(getVarLocs(),

979 LocIndex::kWasmLocation);

980 }

981 };

982

983

984

985

986

987 static void collectIDsForRegs(VarLocsInRange &Collected,

988 const DefinedRegsSet &Regs,

989 const VarLocSet &CollectFrom,

990 const VarLocMap &VarLocIDs);

991

992 VarLocSet &getVarLocsInMBB(const MachineBasicBlock *MBB, VarLocInMBB &Locs) {

993 std::unique_ptr &VLS = Locs[MBB];

994 if (!VLS)

995 VLS = std::make_unique(Alloc);

996 return *VLS;

997 }

998

999 const VarLocSet &getVarLocsInMBB(const MachineBasicBlock *MBB,

1000 const VarLocInMBB &Locs) const {

1001 auto It = Locs.find(MBB);

1002 assert(It != Locs.end() && "MBB not in map");

1003 return *It->second;

1004 }

1005

1006

1007 bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF);

1008

1009

1010

1011

1012

1013

1014

1015 bool isLocationSpill(const MachineInstr &MI, MachineFunction *MF,

1017

1018

1019

1020

1021

1022

1023 bool isEntryValueCandidate(const MachineInstr &MI,

1024 const DefinedRegsSet &Regs) const;

1025

1026

1027

1028 std::optionalVarLoc::SpillLoc isRestoreInstruction(const MachineInstr &MI,

1029 MachineFunction *MF,

1031

1032

1033 VarLoc::SpillLoc extractSpillBaseRegAndOffset(const MachineInstr &MI);

1034 void insertTransferDebugPair(MachineInstr &MI, OpenRangesSet &OpenRanges,

1035 TransferMap &Transfers, VarLocMap &VarLocIDs,

1036 LocIndex OldVarID, TransferKind Kind,

1037 const VarLoc::MachineLoc &OldLoc,

1039

1040 void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,

1041 VarLocMap &VarLocIDs,

1042 InstToEntryLocMap &EntryValTransfers,

1043 RegDefToInstMap &RegSetInstrs);

1044 void transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges,

1045 VarLocMap &VarLocIDs, TransferMap &Transfers);

1046 void cleanupEntryValueTransfers(const MachineInstr *MI,

1047 OpenRangesSet &OpenRanges,

1048 VarLocMap &VarLocIDs, const VarLoc &EntryVL,

1049 InstToEntryLocMap &EntryValTransfers);

1050 void removeEntryValue(const MachineInstr &MI, OpenRangesSet &OpenRanges,

1051 VarLocMap &VarLocIDs, const VarLoc &EntryVL,

1052 InstToEntryLocMap &EntryValTransfers,

1053 RegDefToInstMap &RegSetInstrs);

1054 void emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges,

1055 VarLocMap &VarLocIDs,

1056 InstToEntryLocMap &EntryValTransfers,

1057 VarLocsInRange &KillSet);

1058 void recordEntryValue(const MachineInstr &MI,

1059 const DefinedRegsSet &DefinedRegs,

1060 OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);

1061 void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges,

1062 VarLocMap &VarLocIDs, TransferMap &Transfers);

1063 void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges,

1064 VarLocMap &VarLocIDs,

1065 InstToEntryLocMap &EntryValTransfers,

1066 RegDefToInstMap &RegSetInstrs);

1067 void transferWasmDef(MachineInstr &MI, OpenRangesSet &OpenRanges,

1068 VarLocMap &VarLocIDs);

1069 bool transferTerminator(MachineBasicBlock *MBB, OpenRangesSet &OpenRanges,

1070 VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs);

1071

1072 void process(MachineInstr &MI, OpenRangesSet &OpenRanges,

1073 VarLocMap &VarLocIDs, TransferMap &Transfers,

1074 InstToEntryLocMap &EntryValTransfers,

1075 RegDefToInstMap &RegSetInstrs);

1076

1077 void accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments,

1078 OverlapMap &OLapMap);

1079

1080 bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,

1081 const VarLocMap &VarLocIDs,

1082 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,

1083 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks);

1084

1085

1086

1087 void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);

1088

1089 bool ExtendRanges(MachineFunction &MF, MachineDominatorTree *DomTree,

1090 bool ShouldEmitDebugEntryValues, unsigned InputBBLimit,

1091 unsigned InputDbgValLimit) override;

1092

1093public:

1094

1095 VarLocBasedLDV();

1096

1097 ~VarLocBasedLDV() override;

1098

1099

1100 void printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V,

1101 const VarLocMap &VarLocIDs, const char *msg,

1102 raw_ostream &Out) const;

1103};

1104

1105}

1106

1107

1108

1109

1110

1111VarLocBasedLDV::VarLocBasedLDV() = default;

1112

1113VarLocBasedLDV::~VarLocBasedLDV() = default;

1114

1115

1116

1117

1118

1119

1120void VarLocBasedLDV::OpenRangesSet::erase(const VarLoc &VL) {

1121

1122 auto DoErase = [&VL, this](DebugVariable VarToErase) {

1123 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;

1124 auto It = EraseFrom->find(VarToErase);

1125 if (It != EraseFrom->end()) {

1126 LocIndices IDs = It->second;

1127 for (LocIndex ID : IDs)

1128 VarLocs.reset(ID.getAsRawInteger());

1129 EraseFrom->erase(It);

1130 }

1131 };

1132

1133 DebugVariable Var = VL.Var;

1134

1135

1136 DoErase(Var);

1137

1138

1139

1141

1142

1143

1144 auto MapIt = OverlappingFragments.find({Var.getVariable(), ThisFragment});

1145 if (MapIt != OverlappingFragments.end()) {

1146 for (auto Fragment : MapIt->second) {

1147 VarLocBasedLDV::OptFragmentInfo FragmentHolder;

1149 FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment);

1151 }

1152 }

1153}

1154

1155void VarLocBasedLDV::OpenRangesSet::erase(const VarLocsInRange &KillSet,

1156 const VarLocMap &VarLocIDs,

1157 LocIndex::u32_location_t Location) {

1158 VarLocSet RemoveSet(Alloc);

1159 for (LocIndex::u32_index_t ID : KillSet) {

1160 const VarLoc &VL = VarLocIDs[LocIndex(Location, ID)];

1161 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;

1162 EraseFrom->erase(VL.Var);

1163 LocIndices VLI = VarLocIDs.getAllIndices(VL);

1164 for (LocIndex ID : VLI)

1165 RemoveSet.set(ID.getAsRawInteger());

1166 }

1167 VarLocs.intersectWithComplement(RemoveSet);

1168}

1169

1170void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(const VarLocSet &ToLoad,

1171 const VarLocMap &Map) {

1172 VarLocsInRange UniqueVarLocIDs;

1173 DefinedRegsSet Regs;

1174 Regs.insert(LocIndex::kUniversalLocation);

1175 collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);

1176 for (uint64_t ID : UniqueVarLocIDs) {

1177 LocIndex Idx = LocIndex::fromRawInteger(ID);

1178 const VarLoc &VarL = Map[Idx];

1179 const LocIndices Indices = Map.getAllIndices(VarL);

1180 insert(Indices, VarL);

1181 }

1182}

1183

1184void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,

1185 const VarLoc &VL) {

1186 auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;

1187 for (LocIndex ID : VarLocIDs)

1188 VarLocs.set(ID.getAsRawInteger());

1189 InsertInto->insert({VL.Var, VarLocIDs});

1190}

1191

1192

1193

1194std::optional

1195VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {

1196 auto It = EntryValuesBackupVars.find(Var);

1197 if (It != EntryValuesBackupVars.end())

1198 return It->second;

1199

1200 return std::nullopt;

1201}

1202

1203void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,

1204 const DefinedRegsSet &Regs,

1205 const VarLocSet &CollectFrom,

1206 const VarLocMap &VarLocIDs) {

1207 assert(!Regs.empty() && "Nothing to collect");

1211 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.front()));

1212 auto End = CollectFrom.end();

1214

1215

1216

1217 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(Reg);

1218 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(Reg + 1);

1219 It.advanceToLowerBound(FirstIndexForReg);

1220

1221

1222 for (; It != End && *It < FirstInvalidIndex; ++It) {

1223 LocIndex ItIdx = LocIndex::fromRawInteger(*It);

1224 const VarLoc &VL = VarLocIDs[ItIdx];

1225 LocIndices LI = VarLocIDs.getAllIndices(VL);

1226

1227 assert(LI.back().Location == LocIndex::kUniversalLocation &&

1228 "Unexpected order of LocIndices for VarLoc; was it inserted into "

1229 "the VarLocMap correctly?");

1230 Collected.insert(LI.back().Index);

1231 }

1232

1233 if (It == End)

1234 return;

1235 }

1236}

1237

1238void VarLocBasedLDV::getUsedRegs(const VarLocSet &CollectFrom,

1239 SmallVectorImpl &UsedRegs) const {

1240

1241

1242 uint64_t FirstRegIndex =

1243 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);

1244 uint64_t FirstInvalidIndex =

1245 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);

1246 uint64_t FirstVirtualRegIndex =

1247 LocIndex::rawIndexForReg(LocIndex::kFirstVirtualRegLocation);

1248 auto doGetUsedRegs = [&](VarLocSet::const_iterator &It) {

1249

1250

1251 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;

1252 assert((UsedRegs.empty() || FoundReg != UsedRegs.back()) &&

1253 "Duplicate used reg");

1255

1256

1257

1258

1259 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);

1260 It.advanceToLowerBound(NextRegIndex);

1261 };

1262 for (auto It = CollectFrom.find(FirstRegIndex),

1263 End = CollectFrom.find(FirstInvalidIndex);

1264 It != End;) {

1265 doGetUsedRegs(It);

1266 }

1267 for (auto It = CollectFrom.find(FirstVirtualRegIndex),

1268 End = CollectFrom.end();

1269 It != End;) {

1270 doGetUsedRegs(It);

1271 }

1272}

1273

1274

1275

1276

1277

1278#ifndef NDEBUG

1279void VarLocBasedLDV::printVarLocInMBB(const MachineFunction &MF,

1280 const VarLocInMBB &V,

1281 const VarLocMap &VarLocIDs,

1282 const char *msg,

1283 raw_ostream &Out) const {

1284 Out << '\n' << msg << '\n';

1285 for (const MachineBasicBlock &BB : MF) {

1286 if (V.count(&BB))

1287 continue;

1288 const VarLocSet &L = getVarLocsInMBB(&BB, V);

1289 if (L.empty())

1290 continue;

1291 SmallVector<VarLoc, 32> VarLocs;

1292 collectAllVarLocs(VarLocs, L, VarLocIDs);

1293 Out << "MBB: " << BB.getNumber() << ":\n";

1294 for (const VarLoc &VL : VarLocs) {

1295 Out << " Var: " << VL.Var.getVariable()->getName();

1296 Out << " MI: ";

1297 VL.dump(TRI, TII, Out);

1298 }

1299 }

1300 Out << "\n";

1301}

1302#endif

1303

1304VarLocBasedLDV::VarLoc::SpillLoc

1305VarLocBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) {

1306 assert(MI.hasOneMemOperand() &&

1307 "Spill instruction does not have exactly one memory operand?");

1308 auto MMOI = MI.memoperands_begin();

1309 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();

1311 "Inconsistent memory operand in spill instruction");

1313 const MachineBasicBlock *MBB = MI.getParent();

1317}

1318

1319

1320

1321void VarLocBasedLDV::cleanupEntryValueTransfers(

1322 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,

1323 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {

1324 if (EntryValTransfers.empty() || TRInst == nullptr)

1325 return;

1326

1327 auto TransRange = EntryValTransfers.equal_range(TRInst);

1329 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];

1330 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==

1331 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,

1332 EmittedEV.Expr)) {

1333 OpenRanges.erase(EmittedEV);

1334 EntryValTransfers.erase(TRInst);

1335 break;

1336 }

1337 }

1338}

1339

1340

1341

1342

1343

1344void VarLocBasedLDV::removeEntryValue(const MachineInstr &MI,

1345 OpenRangesSet &OpenRanges,

1346 VarLocMap &VarLocIDs,

1347 const VarLoc &EntryVL,

1348 InstToEntryLocMap &EntryValTransfers,

1349 RegDefToInstMap &RegSetInstrs) {

1350

1351 if (&MI == &EntryVL.MI)

1352 return;

1353

1354

1355

1356

1357 if (MI.getDebugOperand(0).isReg())

1358 return;

1359

1360

1362 const MachineInstr *TransferInst =

1363 Reg.isValid() ? RegSetInstrs.lookup(Reg) : nullptr;

1364

1365

1366 if (!TransferInst && !LastNonDbgMI && MI.getParent()->isEntryBlock())

1367 return;

1368

1369

1370

1371

1372 if (MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {

1373

1374

1375

1376

1377

1378

1379 auto DestSrc = TII->isCopyLikeInstr(*TransferInst);

1380 if (DestSrc) {

1381 const MachineOperand *SrcRegOp, *DestRegOp;

1382 SrcRegOp = DestSrc->Source;

1383 DestRegOp = DestSrc->Destination;

1384 if (Reg == DestRegOp->getReg()) {

1385 for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {

1386 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)];

1387 if (VL.isEntryValueCopyBackupReg(Reg) &&

1388

1389 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->getReg())

1390 return;

1391 }

1392 }

1393 }

1394 }

1395

1396 LLVM_DEBUG(dbgs() << "Deleting a DBG entry value because of: ";

1397 MI.print(dbgs(), false,

1398 false, false,

1399 true, TII));

1400 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,

1401 EntryValTransfers);

1402 OpenRanges.erase(EntryVL);

1403}

1404

1405

1406

1407void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI,

1408 OpenRangesSet &OpenRanges,

1409 VarLocMap &VarLocIDs,

1410 InstToEntryLocMap &EntryValTransfers,

1411 RegDefToInstMap &RegSetInstrs) {

1412 if (MI.isDebugValue())

1413 return;

1414 const DILocalVariable *Var = MI.getDebugVariable();

1415 const DIExpression *Expr = MI.getDebugExpression();

1416 const DILocation *DebugLoc = MI.getDebugLoc();

1417 const DILocation *InlinedAt = DebugLoc->getInlinedAt();

1419 "Expected inlined-at fields to agree");

1420

1421 DebugVariable V(Var, Expr, InlinedAt);

1422

1423

1424

1425 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);

1426 if (Var->isParameter() && EntryValBackupID) {

1427 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];

1428 removeEntryValue(MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,

1429 RegSetInstrs);

1430 }

1431

1432 if (all_of(MI.debug_operands(), [](const MachineOperand &MO) {

1433 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||

1434 MO.isCImm() || MO.isTargetIndex();

1435 })) {

1436

1437 VarLoc VL(MI);

1438

1439 OpenRanges.erase(VL);

1440

1441 LocIndices IDs = VarLocIDs.insert(VL);

1442

1443 OpenRanges.insert(IDs, VL);

1444 } else if (MI.memoperands().size() > 0) {

1445 llvm_unreachable("DBG_VALUE with mem operand encountered after regalloc?");

1446 } else {

1447

1448 assert(MI.isUndefDebugValue() &&

1449 "Unexpected non-undef DBG_VALUE encountered");

1450 VarLoc VL(MI);

1451 OpenRanges.erase(VL);

1452 }

1453}

1454

1455

1456void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl &Collected,

1457 const VarLocSet &CollectFrom,

1458 const VarLocMap &VarLocIDs) {

1459

1460

1461

1462 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);

1463 uint64_t FirstInvalidIndex =

1464 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);

1465

1466 for (auto It = CollectFrom.find(FirstIndex), End = CollectFrom.end();

1467 It != End && *It < FirstInvalidIndex; ++It) {

1468 LocIndex RegIdx = LocIndex::fromRawInteger(*It);

1469 Collected.push_back(VarLocIDs[RegIdx]);

1470 }

1471}

1472

1473

1474void VarLocBasedLDV::emitEntryValues(MachineInstr &MI,

1475 OpenRangesSet &OpenRanges,

1476 VarLocMap &VarLocIDs,

1477 InstToEntryLocMap &EntryValTransfers,

1478 VarLocsInRange &KillSet) {

1479

1480 if (MI.isTerminator())

1481 return;

1482

1483 for (uint32_t ID : KillSet) {

1484

1485 LocIndex Idx = LocIndex(LocIndex::kUniversalLocation, ID);

1486 const VarLoc &VL = VarLocIDs[Idx];

1487 if (!VL.Var.getVariable()->isParameter())

1488 continue;

1489

1490 auto DebugVar = VL.Var;

1491 std::optional EntryValBackupIDs =

1492 OpenRanges.getEntryValueBackup(DebugVar);

1493

1494

1495

1496 if (!EntryValBackupIDs)

1497 continue;

1498

1499 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];

1500 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,

1501 EntryVL.Locs[0].Value.RegNo);

1502 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);

1503 assert(EntryValueIDs.size() == 1 &&

1504 "EntryValue loc should not be variadic");

1505 EntryValTransfers.insert({&MI, EntryValueIDs.back()});

1506 OpenRanges.insert(EntryValueIDs, EntryLoc);

1507 }

1508}

1509

1510

1511

1512

1513

1514

1515void VarLocBasedLDV::insertTransferDebugPair(

1516 MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,

1517 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,

1518 const VarLoc::MachineLoc &OldLoc, Register NewReg) {

1519 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];

1520

1521 auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {

1522 LocIndices LocIds = VarLocIDs.insert(VL);

1523

1524

1525 OpenRanges.erase(VL);

1526

1527

1528

1529 OpenRanges.insert(LocIds, VL);

1530 assert(MI.isTerminator() && "Cannot insert DBG_VALUE after terminator");

1531 TransferDebugPair MIP = {&MI, LocIds.back()};

1532 Transfers.push_back(MIP);

1533 };

1534

1535

1536 OpenRanges.erase(VarLocIDs[OldVarID]);

1537 switch (Kind) {

1538 case TransferKind::TransferCopy: {

1540 "No register supplied when handling a copy of a debug value");

1541

1542

1543 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);

1544 ProcessVarLoc(VL);

1546 dbgs() << "Creating VarLoc for register copy:";

1548 });

1549 return;

1550 }

1551 case TransferKind::TransferSpill: {

1552

1553

1554 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI);

1555 VarLoc VL = VarLoc::CreateSpillLoc(

1556 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);

1557 ProcessVarLoc(VL);

1559 dbgs() << "Creating VarLoc for spill:";

1561 });

1562 return;

1563 }

1564 case TransferKind::TransferRestore: {

1566 "No register supplied when handling a restore of a debug value");

1567

1568

1569 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);

1570 ProcessVarLoc(VL);

1572 dbgs() << "Creating VarLoc for restore:";

1574 });

1575 return;

1576 }

1577 }

1579}

1580

1581

1582void VarLocBasedLDV::transferRegisterDef(MachineInstr &MI,

1583 OpenRangesSet &OpenRanges,

1584 VarLocMap &VarLocIDs,

1585 InstToEntryLocMap &EntryValTransfers,

1586 RegDefToInstMap &RegSetInstrs) {

1587

1588

1589

1590 if (MI.isMetaInstruction())

1591 return;

1592

1593 MachineFunction *MF = MI.getMF();

1596

1597

1598 DefinedRegsSet DeadRegs;

1599 SmallVector<const uint32_t *, 4> RegMasks;

1600 for (const MachineOperand &MO : MI.operands()) {

1601

1603 !(MI.isCall() && MO.getReg() == SP)) {

1604

1605 for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)

1606

1607 DeadRegs.insert((*RAI).id());

1608 RegSetInstrs.erase(MO.getReg());

1609 RegSetInstrs.insert({MO.getReg(), &MI});

1612 }

1613 }

1614

1615

1616

1617

1618 if (!RegMasks.empty()) {

1620 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);

1622

1623

1624

1625

1626

1627

1628 if (Reg == SP)

1629 continue;

1630 bool AnyRegMaskKillsReg =

1631 any_of(RegMasks, [Reg](const uint32_t *RegMask) {

1633 });

1634 if (AnyRegMaskKillsReg)

1635 DeadRegs.insert(Reg);

1636 if (AnyRegMaskKillsReg) {

1637 RegSetInstrs.erase(Reg);

1638 RegSetInstrs.insert({Reg, &MI});

1639 }

1640 }

1641 }

1642

1643 if (DeadRegs.empty())

1644 return;

1645

1646 VarLocsInRange KillSet;

1647 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);

1648 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);

1649

1650 if (ShouldEmitDebugEntryValues)

1651 emitEntryValues(MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);

1652}

1653

1654void VarLocBasedLDV::transferWasmDef(MachineInstr &MI,

1655 OpenRangesSet &OpenRanges,

1656 VarLocMap &VarLocIDs) {

1657

1658

1661 if (TII->isExplicitTargetIndexDef(MI, Index, Offset))

1662 return;

1663

1664

1665

1666 VarLocsInRange KillSet;

1668 for (uint64_t ID : OpenRanges.getWasmVarLocs()) {

1669 LocIndex Idx = LocIndex::fromRawInteger(ID);

1670 const VarLoc &VL = VarLocIDs[Idx];

1671 assert(VL.containsWasmLocs() && "Broken VarLocSet?");

1672 if (VL.usesWasmLoc(Loc))

1673 KillSet.insert(ID);

1674 }

1675 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);

1676}

1677

1678bool VarLocBasedLDV::isSpillInstruction(const MachineInstr &MI,

1679 MachineFunction *MF) {

1680

1681 if (MI.hasOneMemOperand())

1682 return false;

1683

1684 if (MI.getSpillSize(TII) && MI.getFoldedSpillSize(TII))

1685 return false;

1686

1687

1688 return true;

1689}

1690

1691bool VarLocBasedLDV::isLocationSpill(const MachineInstr &MI,

1693 if (!isSpillInstruction(MI, MF))

1694 return false;

1695

1696 auto isKilledReg = [&](const MachineOperand MO, Register &Reg) {

1698 Reg = 0;

1699 return false;

1700 }

1703 };

1704

1705 for (const MachineOperand &MO : MI.operands()) {

1706

1707

1708 if (isKilledReg(MO, Reg))

1709 return true;

1710 if (Reg != 0) {

1711

1712

1713

1714 auto NextI = std::next(MI.getIterator());

1715

1716 if (MI.getParent()->end() == NextI)

1717 continue;

1719 for (const MachineOperand &MONext : NextI->operands()) {

1720

1721

1722 if (isKilledReg(MONext, RegNext) && RegNext == Reg)

1723 return true;

1724 }

1725 }

1726 }

1727

1728 return false;

1729}

1730

1731std::optionalVarLocBasedLDV::VarLoc::SpillLoc

1732VarLocBasedLDV::isRestoreInstruction(const MachineInstr &MI,

1734 if (MI.hasOneMemOperand())

1735 return std::nullopt;

1736

1737

1738

1739 if (MI.getRestoreSize(TII)) {

1740 Reg = MI.getOperand(0).getReg();

1741 return extractSpillBaseRegAndOffset(MI);

1742 }

1743 return std::nullopt;

1744}

1745

1746

1747

1748

1749

1750

1751

1752

1753void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI,

1754 OpenRangesSet &OpenRanges,

1755 VarLocMap &VarLocIDs,

1756 TransferMap &Transfers) {

1757 MachineFunction *MF = MI.getMF();

1758 TransferKind TKind;

1760 std::optionalVarLoc::SpillLoc Loc;

1761

1763

1764

1765

1766

1767 VarLocsInRange KillSet;

1768 if (isSpillInstruction(MI, MF)) {

1769 Loc = extractSpillBaseRegAndOffset(MI);

1770 for (uint64_t ID : OpenRanges.getSpillVarLocs()) {

1771 LocIndex Idx = LocIndex::fromRawInteger(ID);

1772 const VarLoc &VL = VarLocIDs[Idx];

1773 assert(VL.containsSpillLocs() && "Broken VarLocSet?");

1774 if (VL.usesSpillLoc(*Loc)) {

1775

1776

1777

1778

1779

1780

1781

1782

1783

1784

1785 KillSet.insert(ID);

1786 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);

1787 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];

1788 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);

1789 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);

1790 Transfers.push_back({&MI, UndefLocIDs.back()});

1791 }

1792 }

1793 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);

1794 }

1795

1796

1797

1798 if (isLocationSpill(MI, MF, Reg)) {

1799 TKind = TransferKind::TransferSpill;

1802 << "\n");

1803 } else {

1804 if (!(Loc = isRestoreInstruction(MI, MF, Reg)))

1805 return;

1806 TKind = TransferKind::TransferRestore;

1809 << "\n");

1810 }

1811

1812 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();

1813 if (TKind == TransferKind::TransferSpill)

1814 TransferCandidates = OpenRanges.getRegisterVarLocs(Reg);

1815 else if (TKind == TransferKind::TransferRestore)

1816 TransferCandidates = OpenRanges.getSpillVarLocs();

1817 for (uint64_t ID : TransferCandidates) {

1818 LocIndex Idx = LocIndex::fromRawInteger(ID);

1819 const VarLoc &VL = VarLocIDs[Idx];

1820 unsigned LocIdx;

1821 if (TKind == TransferKind::TransferSpill) {

1822 assert(VL.usesReg(Reg) && "Broken VarLocSet?");

1824 << VL.Var.getVariable()->getName() << ")\n");

1825 LocIdx = VL.getRegIdx(Reg);

1826 } else {

1827 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&

1828 "Broken VarLocSet?");

1829 if (!VL.usesSpillLoc(*Loc))

1830

1831 continue;

1833 << VL.Var.getVariable()->getName() << ")\n");

1834 LocIdx = VL.getSpillLocIdx(*Loc);

1835 }

1836 VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];

1837 insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,

1838 MLoc, Reg);

1839

1840

1841 return;

1842 }

1843}

1844

1845

1846

1847

1848void VarLocBasedLDV::transferRegisterCopy(MachineInstr &MI,

1849 OpenRangesSet &OpenRanges,

1850 VarLocMap &VarLocIDs,

1851 TransferMap &Transfers) {

1852 auto DestSrc = TII->isCopyLikeInstr(MI);

1853 if (!DestSrc)

1854 return;

1855

1856 const MachineOperand *DestRegOp = DestSrc->Destination;

1857 const MachineOperand *SrcRegOp = DestSrc->Source;

1858

1859 if (!DestRegOp->isDef())

1860 return;

1861

1862 auto isCalleeSavedReg = [&](Register Reg) {

1863 for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)

1864 if (CalleeSavedRegs.test((*RAI).id()))

1865 return true;

1866 return false;

1867 };

1868

1871

1872

1873

1874

1875

1876

1877 if (!isCalleeSavedReg(DestReg))

1878 return;

1879

1880

1881

1882

1884 for (uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {

1885 LocIndex Idx = LocIndex::fromRawInteger(ID);

1886 const VarLoc &VL = VarLocIDs[Idx];

1887 if (VL.isEntryValueBackupReg(SrcReg)) {

1889 VarLoc EntryValLocCopyBackup =

1890 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);

1891

1892 OpenRanges.erase(VL);

1893

1894

1895 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);

1896 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);

1897 break;

1898 }

1899 }

1900 }

1901

1902 if (!SrcRegOp->isKill())

1903 return;

1904

1905 for (uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {

1906 LocIndex Idx = LocIndex::fromRawInteger(ID);

1907 assert(VarLocIDs[Idx].usesReg(SrcReg) && "Broken VarLocSet?");

1908 VarLoc::MachineLocValue Loc;

1909 Loc.RegNo = SrcReg;

1910 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};

1911 insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, Idx,

1912 TransferKind::TransferCopy, MLoc, DestReg);

1913

1914

1915 return;

1916 }

1917}

1918

1919

1920bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,

1921 OpenRangesSet &OpenRanges,

1922 VarLocInMBB &OutLocs,

1923 const VarLocMap &VarLocIDs) {

1926 VarVec VarLocs;

1927 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);

1928 for (VarLoc &VL : VarLocs) {

1929

1930 dbgs() << "Add to OutLocs in MBB #" << CurMBB->getNumber() << ": ";

1932 }

1933 });

1934 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);

1935 Changed = VLS != OpenRanges.getVarLocs();

1936

1937

1939 VLS = OpenRanges.getVarLocs();

1940 OpenRanges.clear();

1942}

1943

1944

1945

1946

1947

1948

1949

1950

1951

1952

1953

1954void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &MI,

1955 VarToFragments &SeenFragments,

1957 DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),

1958 MI.getDebugLoc()->getInlinedAt());

1959 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();

1960

1961

1962

1963

1964 auto [SeenIt, Inserted] = SeenFragments.try_emplace(MIVar.getVariable());

1965 if (Inserted) {

1966 SeenIt->second.insert(ThisFragment);

1967

1968 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});

1969 return;

1970 }

1971

1972

1973

1974 auto IsInOLapMap =

1975 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});

1976 if (!IsInOLapMap.second)

1977 return;

1978

1979 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;

1980 auto &AllSeenFragments = SeenIt->second;

1981

1982

1983

1984

1985 for (const auto &ASeenFragment : AllSeenFragments) {

1986

1988

1989 ThisFragmentsOverlaps.push_back(ASeenFragment);

1990

1991

1992 auto ASeenFragmentsOverlaps =

1993 OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});

1994 assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&

1995 "Previously seen var fragment has no vector of overlaps");

1996 ASeenFragmentsOverlaps->second.push_back(ThisFragment);

1997 }

1998 }

1999

2000 AllSeenFragments.insert(ThisFragment);

2001}

2002

2003

2004void VarLocBasedLDV::process(MachineInstr &MI, OpenRangesSet &OpenRanges,

2005 VarLocMap &VarLocIDs, TransferMap &Transfers,

2006 InstToEntryLocMap &EntryValTransfers,

2007 RegDefToInstMap &RegSetInstrs) {

2008 if (MI.isDebugInstr())

2009 LastNonDbgMI = &MI;

2010 transferDebugValue(MI, OpenRanges, VarLocIDs, EntryValTransfers,

2011 RegSetInstrs);

2012 transferRegisterDef(MI, OpenRanges, VarLocIDs, EntryValTransfers,

2013 RegSetInstrs);

2014 transferWasmDef(MI, OpenRanges, VarLocIDs);

2015 transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);

2016 transferSpillOrRestoreInst(MI, OpenRanges, VarLocIDs, Transfers);

2017}

2018

2019

2020

2021

2022bool VarLocBasedLDV::join(

2023 MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,

2024 const VarLocMap &VarLocIDs,

2025 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,

2026 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks) {

2028

2029 VarLocSet InLocsT(Alloc);

2030

2031

2032

2033 int NumVisited = 0;

2035

2036

2037

2038

2039

2040 if (!Visited.count(p)) {

2041 LLVM_DEBUG(dbgs() << " ignoring unvisited pred MBB: " << p->getNumber()

2042 << "\n");

2043 continue;

2044 }

2045 auto OL = OutLocs.find(p);

2046

2047 if (OL == OutLocs.end())

2048 return false;

2049

2050

2051

2052 VarLocSet &OutLocVLS = *OL->second;

2053 if (!NumVisited)

2054 InLocsT = OutLocVLS;

2055 else

2056 InLocsT &= OutLocVLS;

2057

2059 if (!InLocsT.empty()) {

2060 VarVec VarLocs;

2061 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);

2062 for (const VarLoc &VL : VarLocs)

2063 dbgs() << " gathered candidate incoming var: "

2064 << VL.Var.getVariable()->getName() << "\n";

2065 }

2066 });

2067

2068 NumVisited++;

2069 }

2070

2071

2072 VarLocSet KillSet(Alloc);

2073 bool IsArtificial = ArtificialBlocks.count(&MBB);

2074 if (!IsArtificial) {

2075 for (uint64_t ID : InLocsT) {

2076 LocIndex Idx = LocIndex::fromRawInteger(ID);

2078 KillSet.set(ID);

2080 auto Name = VarLocIDs[Idx].Var.getVariable()->getName();

2081 dbgs() << " killing " << Name << ", it doesn't dominate MBB\n";

2082 });

2083 }

2084 }

2085 }

2086 InLocsT.intersectWithComplement(KillSet);

2087

2088

2089

2090

2092 "Should have processed at least one predecessor");

2093

2094 VarLocSet &ILS = getVarLocsInMBB(&MBB, InLocs);

2096 if (ILS != InLocsT) {

2097 ILS = InLocsT;

2099 }

2100

2102}

2103

2104void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,

2105 VarLocMap &VarLocIDs) {

2106

2107

2108 for (auto &Iter : PendingInLocs) {

2109

2110 auto &MBB = const_cast<MachineBasicBlock &>(*Iter.first);

2111 VarLocSet &Pending = *Iter.second;

2112

2113 SmallVector<VarLoc, 32> VarLocs;

2114 collectAllVarLocs(VarLocs, Pending, VarLocIDs);

2115

2116 for (VarLoc DiffIt : VarLocs) {

2117

2118

2119 if (DiffIt.isEntryBackupLoc())

2120 continue;

2121 MachineInstr *MI = DiffIt.BuildDbgValue(*MBB.getParent());

2123

2124 (void)MI;

2126 }

2127 }

2128}

2129

2130bool VarLocBasedLDV::isEntryValueCandidate(

2131 const MachineInstr &MI, const DefinedRegsSet &DefinedRegs) const {

2132 assert(MI.isDebugValue() && "This must be DBG_VALUE.");

2133

2134

2135

2136

2137

2138 auto *DIVar = MI.getDebugVariable();

2139 if (!DIVar->isParameter())

2140 return false;

2141

2142

2143 if (MI.getDebugLoc()->getInlinedAt())

2144 return false;

2145

2146

2147

2148

2150 return false;

2151

2152

2153

2154

2155

2156 if (DefinedRegs.count(MI.getDebugOperand(0).getReg()))

2157 return false;

2158

2159

2160

2161

2162 const DIExpression *Expr = MI.getDebugExpression();

2164 return false;

2165

2166 return true;

2167}

2168

2169

2174 Regs.insert(MO.getReg());

2176 Regs.insert(*AI);

2177 }

2178 }

2179}

2180

2181

2182

2183

2184void VarLocBasedLDV::recordEntryValue(const MachineInstr &MI,

2185 const DefinedRegsSet &DefinedRegs,

2186 OpenRangesSet &OpenRanges,

2187 VarLocMap &VarLocIDs) {

2188 if (!ShouldEmitDebugEntryValues)

2189 return;

2190

2191 DebugVariable V(MI.getDebugVariable(), MI.getDebugExpression(),

2192 MI.getDebugLoc()->getInlinedAt());

2193

2194 if (!isEntryValueCandidate(MI, DefinedRegs) ||

2195 OpenRanges.getEntryValueBackup(V))

2196 return;

2197

2199

2200

2201

2202 DIExpression *NewExpr =

2204 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(MI, NewExpr);

2205 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);

2206 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);

2207}

2208

2209

2210

2211bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF,

2212 MachineDominatorTree *DomTree,

2213 bool ShouldEmitDebugEntryValues,

2215 unsigned InputDbgValLimit) {

2216 (void)DomTree;

2218

2220

2221 return false;

2222

2223

2226 return false;

2227

2232 this->ShouldEmitDebugEntryValues = ShouldEmitDebugEntryValues;

2233

2234 LS.scanFunction(MF);

2235

2237 bool OLChanged = false;

2238 bool MBBJoined = false;

2239

2240 VarLocMap VarLocIDs;

2241 OverlapMap OverlapFragments;

2242 OpenRangesSet OpenRanges(Alloc, OverlapFragments);

2243

2244 VarLocInMBB OutLocs;

2245 VarLocInMBB InLocs;

2246 TransferMap Transfers;

2247

2248

2249 InstToEntryLocMap EntryValTransfers;

2250

2251 RegDefToInstMap RegSetInstrs;

2252

2253 VarToFragments SeenFragments;

2254

2255

2256

2257 SmallPtrSet<const MachineBasicBlock *, 16> ArtificialBlocks;

2258

2259 DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;

2260 DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;

2261 std::priority_queue<unsigned int, std::vector,

2262 std::greater>

2263 Worklist;

2264 std::priority_queue<unsigned int, std::vector,

2265 std::greater>

2266 Pending;

2267

2268

2269

2270 DefinedRegsSet DefinedRegs;

2271

2272

2273

2274 MachineBasicBlock &First_MBB = *(MF.begin());

2275 for (auto &MI : First_MBB) {

2277 if (MI.isDebugValue())

2278 recordEntryValue(MI, DefinedRegs, OpenRanges, VarLocIDs);

2279 }

2280

2281

2282 for (auto &MBB : MF)

2283 for (auto &MI : MBB)

2284 if (MI.isDebugValue())

2285 accumulateFragmentMap(MI, SeenFragments, OverlapFragments);

2286

2287 auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool {

2289 return DL.getLine() != 0;

2290 return false;

2291 };

2292 for (auto &MBB : MF)

2295

2296 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,

2297 "OutLocs after initialization", dbgs()));

2298

2299 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);

2300 unsigned int RPONumber = 0;

2301 for (MachineBasicBlock *MBB : RPOT) {

2302 OrderToBB[RPONumber] = MBB;

2303 BBToOrder[MBB] = RPONumber;

2304 Worklist.push(RPONumber);

2305 ++RPONumber;

2306 }

2307

2309 unsigned NumInputDbgValues = 0;

2310 for (auto &MBB : MF)

2311 for (auto &MI : MBB)

2312 if (MI.isDebugValue())

2313 ++NumInputDbgValues;

2314 if (NumInputDbgValues > InputDbgValLimit) {

2315 LLVM_DEBUG(dbgs() << "Disabling VarLocBasedLDV: " << MF.getName()

2316 << " has " << RPONumber << " basic blocks and "

2317 << NumInputDbgValues

2318 << " input DBG_VALUEs, exceeding limits.\n");

2319 return false;

2320 }

2321 }

2322

2323

2324

2325

2326

2327 SmallPtrSet<const MachineBasicBlock *, 16> Visited;

2328 while (!Worklist.empty() || !Pending.empty()) {

2329

2330

2331

2332 SmallPtrSet<MachineBasicBlock *, 16> OnPending;

2334 while (!Worklist.empty()) {

2335 MachineBasicBlock *MBB = OrderToBB[Worklist.top()];

2336 Worklist.pop();

2337 MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs, Visited,

2338 ArtificialBlocks);

2339 MBBJoined |= Visited.insert(MBB).second;

2340 if (MBBJoined) {

2341 MBBJoined = false;

2343

2344

2345

2346

2347 OpenRanges.insertFromLocSet(getVarLocsInMBB(MBB, InLocs), VarLocIDs);

2348 LastNonDbgMI = nullptr;

2349 RegSetInstrs.clear();

2350 for (auto &MI : *MBB)

2351 process(MI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,

2352 RegSetInstrs);

2353 OLChanged |= transferTerminator(MBB, OpenRanges, OutLocs, VarLocIDs);

2354

2355 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,

2356 "OutLocs after propagating", dbgs()));

2357 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,

2358 "InLocs after propagating", dbgs()));

2359

2360 if (OLChanged) {

2361 OLChanged = false;

2363 if (OnPending.insert(s).second) {

2364 Pending.push(BBToOrder[s]);

2365 }

2366 }

2367 }

2368 }

2369 Worklist.swap(Pending);

2370

2371

2372 assert(Pending.empty() && "Pending should be empty");

2373 }

2374

2375

2376 for (auto &TR : Transfers) {

2377 assert(!TR.TransferInst->isTerminator() &&

2378 "Cannot insert DBG_VALUE after terminator");

2379 MachineBasicBlock *MBB = TR.TransferInst->getParent();

2380 const VarLoc &VL = VarLocIDs[TR.LocationID];

2381 MachineInstr *MI = VL.BuildDbgValue(MF);

2383 }

2384 Transfers.clear();

2385

2386

2387 for (auto &TR : EntryValTransfers) {

2388 MachineInstr *TRInst = const_cast<MachineInstr *>(TR.first);

2390 "Cannot insert DBG_VALUE after terminator");

2391 MachineBasicBlock *MBB = TRInst->getParent();

2392 const VarLoc &VL = VarLocIDs[TR.second];

2393 MachineInstr *MI = VL.BuildDbgValue(MF);

2395 }

2396 EntryValTransfers.clear();

2397

2398

2399

2400 flushPendingLocs(InLocs, VarLocIDs);

2401

2402 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs()));

2403 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs()));

2405}

2406

2407LDVImpl *

2409{

2410 return new VarLocBasedLDV();

2411}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static bool isConstant(const MachineInstr &MI)

AMDGPU Prepare AGPR Alloc

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

A bitvector that uses an IntervalMap to coalesce adjacent elements into intervals.

This file defines the DenseMap class.

This file contains constants used for implementing Dwarf debug support.

const HexagonInstrInfo * TII

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

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)

static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)

Return the first DebugLoc that has line number information, given a range of instructions.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)

This file defines the SmallPtrSet class.

This file defines the SmallSet class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This file describes how to lower LLVM code to machine code.

static bool isRegOtherThanSPAndFP(const MachineOperand &Op, const MachineInstr &MI, const TargetRegisterInfo *TRI)

If Op is a stack or frame register return true, otherwise return false.

Definition VarLocBasedImpl.cpp:165

static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs, const TargetRegisterInfo *TRI)

Collect all register defines (including aliases) for the given instruction.

Definition VarLocBasedImpl.cpp:2170

bool test(unsigned Idx) const

A bitvector that, under the hood, relies on an IntervalMap to coalesce elements into intervals.

unsigned getNumElements() const

DbgVariableFragmentInfo FragmentInfo

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 isDeref() const

Return whether there is exactly one operator and it is a DW_OP_deref;.

static LLVM_ABI DIExpression * replaceArg(const DIExpression *Expr, uint64_t OldArg, uint64_t NewArg)

Create a copy of Expr with each instance of DW_OP_LLVM_arg, \p OldArg replaced with DW_OP_LLVM_arg,...

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 ...

bool isValidLocationForIntrinsic(const DILocation *DL) const

Check that a location is valid for this variable.

static bool isDefaultFragment(const FragmentInfo F)

const DILocation * getInlinedAt() const

FragmentInfo getFragmentOrDefault() const

const DILocalVariable * getVariable() const

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

DISubprogram * getSubprogram() const

Get the attached subprogram.

MCRegAliasIterator enumerates all registers aliasing Reg.

instr_iterator instr_begin()

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...

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

iterator_range< succ_iterator > successors()

iterator_range< pred_iterator > predecessors()

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,...

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

Function & getFunction()

Return the LLVM function that this machine code represents.

Representation of each machine instruction.

bool isTerminator(QueryType Type=AnyInBundle) const

Returns true if this instruction part of the terminator for a basic block.

const MachineBasicBlock * getParent() const

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isRegMask() const

isRegMask - Tests if this is a MO_RegisterMask operand.

Register getReg() const

getReg - Returns the register number.

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)

virtual void print(raw_ostream &OS, const Module *M) const

print - Print out the internal state of the pass.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

constexpr unsigned id() const

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

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.

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...

Register getStackPointerRegisterToSaveRestore() const

If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...

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

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

DenseMap< FragmentOfVar, SmallVector< DIExpression::FragmentInfo, 1 > > OverlapMap

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

bool operator<(int64_t V1, const APSInt &V2)

FunctionAddr VTableAddr Value

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

bool operator!=(uint64_t V1, const APInt &V2)

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)

void erase(Container &C, ValueType V)

Wrapper function to remove a value from a container:

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

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.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

LDVImpl * makeVarLocBasedLiveDebugValues()

Definition VarLocBasedImpl.cpp:2408

iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >

std::string join(IteratorT Begin, IteratorT End, StringRef Separator)

Joins the strings in the range [Begin, End), adding Separator between the elements.

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

void array_pod_sort(IteratorTy Start, IteratorTy End)

array_pod_sort - This sorts an array with the specified start and end extent.

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.