LLVM: lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

26#include

27#include

28#include

29

30using namespace llvm;

31

32#define DEBUG_TYPE "dwarfdebug"

33

34namespace {

36}

37

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

55 unsigned Position = 0;

58 InstNumberMap[&MI] = MI.isMetaInstruction() ? Position : ++Position;

59}

60

63 assert(A->getParent() && B->getParent() && "Operands must have a parent");

64 assert(A->getMF() == B->getMF() &&

65 "Operands must be in the same MachineFunction");

66 return InstNumberMap.lookup(A) < InstNumberMap.lookup(B);

67}

68

72

73

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

75 auto &Entries = VarEntries[Var];

76 if (Entries.empty() && Entries.back().isDbgValue() &&

77 Entries.back().isClosed() &&

78 Entries.back().getInstr()->isEquivalentDbgInstr(MI)) {

79 LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"

80 << "\t" << Entries.back().getInstr() << "\t" << MI

81 << "\n");

82 return false;

83 }

85 NewIndex = Entries.size() - 1;

86 return true;

87}

88

99

101

102

103 assert(isDbgValue() && "Setting end index for non-debug value");

104 assert(isClosed() && "End index has already been set");

105 EndIndex = Index;

106}

107

108

109

110

111

112static std::optional<ArrayRef::iterator>

115 for (auto RangesI = Ranges.begin(), RangesE = Ranges.end();

116 RangesI != RangesE; ++RangesI) {

117 if (EndMI && Ordering.isBefore(EndMI, RangesI->first))

118 return std::nullopt;

119 if (EndMI && !Ordering.isBefore(RangesI->second, EndMI))

120 return RangesI;

121 if (Ordering.isBefore(StartMI, RangesI->second))

122 return RangesI;

123 }

124 return std::nullopt;

125}

126

130

132

133

135

136

138

140 << "'\n");

141

142 for (auto &Record : VarEntries) {

143 auto &HistoryMapEntries = Record.second;

144 if (HistoryMapEntries.empty())

145 continue;

146

149

151 if (const DILocation *InlinedAt = Entity.second) {

152 Scope = LScopes.findInlinedScope(LocalVar->getScope(), InlinedAt);

153 } else {

155

156

157

158

159

160

161

162 if (Scope &&

163 (Scope->getScopeNode() == Scope->getScopeNode()->getSubprogram()) &&

164 (Scope->getScopeNode() == LocalVar->getScope()))

165 continue;

166 }

167

168

169

170 if (!Scope)

171 continue;

172

174

175 ReferenceCount.assign(HistoryMapEntries.size(), 0);

176

177

180 for (auto EI = HistoryMapEntries.begin(), EE = HistoryMapEntries.end();

181 EI != EE; ++EI, ++StartIndex) {

182

183 if (!EI->isDbgValue())

184 continue;

185

186

187 EntryIndex EndIndex = EI->getEndIndex();

188

190 ReferenceCount[EndIndex] += 1;

191

192

193

194

195 if (ReferenceCount[StartIndex] > 0)

196 continue;

197

198 const MachineInstr *StartMI = EI->getInstr();

200 ? HistoryMapEntries[EndIndex].getInstr()

201 : nullptr;

202

203

204 if (auto R = intersects(StartMI, EndMI, ScopeRanges, Ordering)) {

205

206

208 } else {

209

210

211

212 ToRemove.push_back(StartIndex);

213

214

216 ReferenceCount[EndIndex] -= 1;

217 LLVM_DEBUG(dbgs() << "Dropping value outside scope range of variable: ";

219 }

220 }

221

222

224 continue;

225

226

227 for (size_t i = 0; i < HistoryMapEntries.size(); ++i)

228 if (ReferenceCount[i] <= 0 && HistoryMapEntries[i].isClobber())

230

232

233

234

235

236 Offsets.assign(HistoryMapEntries.size(), 0);

237 size_t CurOffset = 0;

238 auto ToRemoveItr = ToRemove.begin();

239 for (size_t EntryIdx = *ToRemoveItr; EntryIdx < HistoryMapEntries.size();

240 ++EntryIdx) {

241

242 if (ToRemoveItr != ToRemove.end() && *ToRemoveItr == EntryIdx) {

243 ++ToRemoveItr;

244 ++CurOffset;

245 }

246 Offsets[EntryIdx] = CurOffset;

247 }

248

249

250

251 for (auto &Entry : HistoryMapEntries)

253 Entry.EndIndex -= Offsets[Entry.EndIndex];

254

255

256

258 HistoryMapEntries.erase(HistoryMapEntries.begin() + Idx);

260 << "') size: " << HistoryMapEntries.size() << "\n");

261 }

262}

263

267 continue;

268

271

272 if (MI->isUndefDebugValue())

273 continue;

274

275 return true;

276 }

277

278 return false;

279}

280

282 assert(MI.isDebugLabel() && "not a DBG_LABEL");

283 LabelInstr[Label] = &MI;

284}

285

286namespace {

287

288

290using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;

291

292

293

294

295

296using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>;

297

298}

299

300

303 const auto &I = RegVars.find(RegNo);

304 assert(RegNo != 0U && I != RegVars.end());

305 auto &VarSet = I->second;

306 const auto &VarPos = llvm::find(VarSet, Var);

307 assert(VarPos != VarSet.end());

308 VarSet.erase(VarPos);

309

310 if (VarSet.empty())

311 RegVars.erase(I);

312}

313

314

318 auto &VarSet = RegVars[RegNo];

320 VarSet.push_back(Var);

321}

322

323

324

325

326

329 DbgValueEntriesMap &LiveEntries,

333

335

336

337

340 for (auto Index : LiveEntries[Var]) {

341 auto &Entry = HistMap.getEntry(Var, Index);

342 assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");

343 if (Entry.getInstr()->isDebugEntryValue())

344 continue;

345 if (Entry.getInstr()->hasDebugOperandForReg(RegNo)) {

347 Entry.endEntry(ClobberIndex);

348 for (const auto &MO : Entry.getInstr()->debug_operands())

349 if (MO.isReg() && MO.getReg() && MO.getReg() != RegNo)

350 MaybeRemovedRegisters.insert(MO.getReg());

351 } else {

352 for (const auto &MO : Entry.getInstr()->debug_operands())

353 if (MO.isReg() && MO.getReg())

354 KeepRegisters.insert(MO.getReg());

355 }

356 }

357

358 for (Register Reg : MaybeRemovedRegisters)

361

362

363 auto &Entries = LiveEntries[Var];

364 for (auto Index : IndicesToErase)

366}

367

368

370 RegDescribedVarsMap &RegVars,

371 DbgValueEntriesMap &LiveEntries,

375

376

377

378

379

380

381

382

383

384

385

386

388

389

390

393 for (auto Index : LiveEntries[Var]) {

394 auto &Entry = HistMap.getEntry(Var, Index);

395 assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");

398 if (Overlaps) {

400 Entry.endEntry(NewIndex);

401 }

404 if (Op.isReg() && Op.getReg())

405 TrackedRegs[Op.getReg()] |= !Overlaps;

406 }

407

408

409

412 if (Op.isReg() && Op.getReg()) {

416 LiveEntries[Var].insert(NewIndex);

417 }

418 }

419 }

420

421

422 for (auto I : TrackedRegs)

423 if (I.second)

425

426

427 auto &Entries = LiveEntries[Var];

428 for (auto Index : IndicesToErase)

431 }

432}

433

434

435

437 RegDescribedVarsMap::iterator I,

439 DbgValueEntriesMap &LiveEntries,

441

442

443

444

445 for (const auto &Var : I->second) {

447 clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap,

448 FellowRegisters);

449 for (Register RegNo : FellowRegisters)

451 }

452 RegVars.erase(I);

453}

454

455

456

459 DbgValueEntriesMap &LiveEntries,

461 const auto &I = RegVars.find(RegNo);

462 if (I == RegVars.end())

463 return;

465}

466

473 Register FrameReg = TRI->getFrameRegister(*MF);

474 RegDescribedVarsMap RegVars;

475 DbgValueEntriesMap LiveEntries;

476 for (const auto &MBB : *MF) {

477 for (const auto &MI : MBB) {

478 if (MI.isDebugValue()) {

479 assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");

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

483 InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt());

484

486 } else if (MI.isDebugLabel()) {

487 assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!");

488 const DILabel *RawLabel = MI.getDebugLabel();

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

491

492

493

494 InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt());

496 }

497

498

499

500 if (MI.isMetaInstruction())

501 continue;

502

503

505 if (MO.isReg() && MO.isDef() && MO.getReg()) {

506

507

508 if (MI.isCall() && MO.getReg() == SP)

509 continue;

510

511

512 if (MO.getReg().isVirtual())

515

516

517

518

519 else if (MO.getReg() != FrameReg ||

523 ++AI)

525 }

526 } else if (MO.isRegMask()) {

527

528

530

531 for (auto It : RegVars) {

532 unsigned int Reg = It.first;

534 MO.clobbersPhysReg(Reg))

536 }

537

538 for (unsigned Reg : RegsToClobber) {

540 }

541 }

542 }

543 }

544

545

546

547

548 if (MBB.empty() && &MBB != &MF->back()) {

549

550 for (auto &Pair : LiveEntries) {

551 if (Pair.second.empty())

552 continue;

553

554

556

557

562 }

563 }

564

565 LiveEntries.clear();

566 RegVars.clear();

567 }

568 }

569}

570

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

573 dbgs() << "DbgValueHistoryMap('" << FuncName << "'):\n";

574 for (const auto &VarRangePair : *this) {

577

579 const DILocation *Location = Var.second;

580

581 dbgs() << " - " << LocalVar->getName() << " at ";

582

583 if (Location)

584 dbgs() << Location->getFilename() << ":" << Location->getLine() << ":"

585 << Location->getColumn();

586 else

587 dbgs() << "";

588

589 dbgs() << " --\n";

590

592 const auto &Entry = E.value();

593 dbgs() << " Entry[" << E.index() << "]: ";

595 dbgs() << "Debug value\n";

596 else

597 dbgs() << "Clobber\n";

601 dbgs() << " - Valid until end of function\n";

602 else

604 }

605 dbgs() << "\n";

606 }

607 }

608}

609#endif

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

ReachingDefInfo InstSet & ToRemove

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.

static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)

Definition DbgEntityHistoryCalculator.cpp:315

static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, const MachineInstr &ClobberingInstr, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap, SmallVectorImpl< Register > &FellowRegisters)

Create a clobbering entry and end all open debug value entries for Var that are described by RegNo us...

Definition DbgEntityHistoryCalculator.cpp:327

static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)

Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.

Definition DbgEntityHistoryCalculator.cpp:113

static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, RegDescribedVarsMap &RegVars, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap)

Add a new debug value for Var. Closes all overlapping debug values.

Definition DbgEntityHistoryCalculator.cpp:369

static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)

Definition DbgEntityHistoryCalculator.cpp:301

static void clobberRegisterUses(RegDescribedVarsMap &RegVars, RegDescribedVarsMap::iterator I, DbgValueHistoryMap &HistMap, DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr)

Definition DbgEntityHistoryCalculator.cpp:436

Register const TargetRegisterInfo * TRI

This file defines the SmallSet class.

This file defines the SmallVector class.

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)

Check if fragments overlap between a pair of FragmentInfos.

bool isValidLocationForIntrinsic(const DILocation *DL) const

Check that a location is valid for this label.

bool isValidLocationForIntrinsic(const DILocation *DL) const

Check that a location is valid for this variable.

For each inlined instance of a source-level label, keep the corresponding DBG_LABEL instruction.

std::pair< const DINode *, const DILocation * > InlinedEntity

void addInstr(InlinedEntity Label, const MachineInstr &MI)

Definition DbgEntityHistoryCalculator.cpp:281

Specifies a change in a variable's debug value history.

const MachineInstr * getInstr() const

EntryIndex getEndIndex() const

void endEntry(EntryIndex EndIndex)

Definition DbgEntityHistoryCalculator.cpp:100

For each user variable, keep a list of instruction ranges where this variable is accessible.

bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, EntryIndex &NewIndex)

Definition DbgEntityHistoryCalculator.cpp:69

void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, const InstructionOrdering &Ordering)

Drop location ranges which exist entirely outside each variable's scope.

Definition DbgEntityHistoryCalculator.cpp:127

size_t EntryIndex

Index in the entry vector.

EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI)

Definition DbgEntityHistoryCalculator.cpp:89

SmallVector< Entry, 4 > Entries

Entry & getEntry(InlinedEntity Var, EntryIndex Index)

LLVM_DUMP_METHOD void dump(StringRef FuncName) const

Definition DbgEntityHistoryCalculator.cpp:572

static const EntryIndex NoEntry

Special value to indicate that an entry is valid until the end of the function.

bool hasNonEmptyLocation(const Entries &Entries) const

Test whether a vector of entries features any non-empty locations.

Definition DbgEntityHistoryCalculator.cpp:264

std::pair< const DINode *, const DILocation * > InlinedEntity

std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)

Record instruction ordering so we can query their relative positions within a function.

void initialize(const MachineFunction &MF)

Definition DbgEntityHistoryCalculator.cpp:38

bool isBefore(const MachineInstr *A, const MachineInstr *B) const

Check if instruction A comes before B, where A and B both belong to the MachineFunction passed to ini...

Definition DbgEntityHistoryCalculator.cpp:61

This class is used to track scope information.

This class provides interface to collect and use lexical scoping information from machine instruction...

LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)

Find lexical scope, either regular or inlined, for the given DebugLoc.

LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)

Find an inlined scope for the given scope/inlined-at.

MCRegAliasIterator enumerates all registers aliasing Reg.

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.

const MachineBasicBlock & back() const

Representation of each machine instruction.

mop_range debug_operands()

Returns all operands that are used to determine the variable location for this DBG_VALUE instruction.

LLVM_ABI const DIExpression * getDebugExpression() const

Return the complex address expression referenced by this DBG_VALUE instruction.

LLVM_ABI void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const

Print this MI to OS.

LLVM_ABI bool isDebugEntryValue() const

A DBG_VALUE is an entry value iff its debug expression contains the DW_OP_LLVM_entry_value operation.

MachineOperand class - Representation of each machine instruction operand.

Wrapper class representing virtual and physical registers.

static constexpr bool isPhysicalRegister(unsigned Reg)

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

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

bool contains(const T &V) const

Check if the SmallSet contains the given element.

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)

iterator erase(const_iterator CI)

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.

StringRef - Represent a constant reference to a string, i.e.

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 TargetLowering * getTargetLowering() const

This is an optimization pass for GlobalISel generic memory operations.

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

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

void calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels)

Definition DbgEntityHistoryCalculator.cpp:467

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

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.

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

decltype(auto) cast(const From &Val)

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

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

Returns true if Element is found in Range.