Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
35271 views
//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"9#include "llvm/ADT/STLExtras.h"10#include "llvm/ADT/SmallSet.h"11#include "llvm/ADT/SmallVector.h"12#include "llvm/CodeGen/LexicalScopes.h"13#include "llvm/CodeGen/MachineBasicBlock.h"14#include "llvm/CodeGen/MachineFunction.h"15#include "llvm/CodeGen/MachineInstr.h"16#include "llvm/CodeGen/MachineOperand.h"17#include "llvm/CodeGen/TargetLowering.h"18#include "llvm/CodeGen/TargetRegisterInfo.h"19#include "llvm/CodeGen/TargetSubtargetInfo.h"20#include "llvm/IR/DebugInfoMetadata.h"21#include "llvm/IR/DebugLoc.h"22#include "llvm/MC/MCRegisterInfo.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/raw_ostream.h"25#include <cassert>26#include <map>27#include <optional>28#include <utility>2930using namespace llvm;3132#define DEBUG_TYPE "dwarfdebug"3334namespace {35using EntryIndex = DbgValueHistoryMap::EntryIndex;36}3738void InstructionOrdering::initialize(const MachineFunction &MF) {39// We give meta instructions the same ordinal as the preceding instruction40// because this class is written for the task of comparing positions of41// variable location ranges against scope ranges. To reflect what we'll see42// in the binary, when we look at location ranges we must consider all43// DBG_VALUEs between two real instructions at the same position. And a44// scope range which ends on a meta instruction should be considered to end45// at the last seen real instruction. E.g.46//47// 1 instruction p Both the variable location for x and for y start48// 1 DBG_VALUE for "x" after instruction p so we give them all the same49// 1 DBG_VALUE for "y" number. If a scope range ends at DBG_VALUE for "y",50// 2 instruction q we should treat it as ending after instruction p51// because it will be the last real instruction in the52// range. DBG_VALUEs at or after this position for53// variables declared in the scope will have no effect.54clear();55unsigned Position = 0;56for (const MachineBasicBlock &MBB : MF)57for (const MachineInstr &MI : MBB)58InstNumberMap[&MI] = MI.isMetaInstruction() ? Position : ++Position;59}6061bool InstructionOrdering::isBefore(const MachineInstr *A,62const MachineInstr *B) const {63assert(A->getParent() && B->getParent() && "Operands must have a parent");64assert(A->getMF() == B->getMF() &&65"Operands must be in the same MachineFunction");66return InstNumberMap.lookup(A) < InstNumberMap.lookup(B);67}6869bool DbgValueHistoryMap::startDbgValue(InlinedEntity Var,70const MachineInstr &MI,71EntryIndex &NewIndex) {72// Instruction range should start with a DBG_VALUE instruction for the73// variable.74assert(MI.isDebugValue() && "not a DBG_VALUE");75auto &Entries = VarEntries[Var];76if (!Entries.empty() && Entries.back().isDbgValue() &&77!Entries.back().isClosed() &&78Entries.back().getInstr()->isEquivalentDbgInstr(MI)) {79LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"80<< "\t" << Entries.back().getInstr() << "\t" << MI81<< "\n");82return false;83}84Entries.emplace_back(&MI, Entry::DbgValue);85NewIndex = Entries.size() - 1;86return true;87}8889EntryIndex DbgValueHistoryMap::startClobber(InlinedEntity Var,90const MachineInstr &MI) {91auto &Entries = VarEntries[Var];92// If an instruction clobbers multiple registers that the variable is93// described by, then we may have already created a clobbering instruction.94if (Entries.back().isClobber() && Entries.back().getInstr() == &MI)95return Entries.size() - 1;96Entries.emplace_back(&MI, Entry::Clobber);97return Entries.size() - 1;98}99100void DbgValueHistoryMap::Entry::endEntry(EntryIndex Index) {101// For now, instruction ranges are not allowed to cross basic block102// boundaries.103assert(isDbgValue() && "Setting end index for non-debug value");104assert(!isClosed() && "End index has already been set");105EndIndex = Index;106}107108/// Check if the instruction range [StartMI, EndMI] intersects any instruction109/// range in Ranges. EndMI can be nullptr to indicate that the range is110/// unbounded. Assumes Ranges is ordered and disjoint. Returns true and points111/// to the first intersecting scope range if one exists.112static std::optional<ArrayRef<InsnRange>::iterator>113intersects(const MachineInstr *StartMI, const MachineInstr *EndMI,114const ArrayRef<InsnRange> &Ranges,115const InstructionOrdering &Ordering) {116for (auto RangesI = Ranges.begin(), RangesE = Ranges.end();117RangesI != RangesE; ++RangesI) {118if (EndMI && Ordering.isBefore(EndMI, RangesI->first))119return std::nullopt;120if (EndMI && !Ordering.isBefore(RangesI->second, EndMI))121return RangesI;122if (Ordering.isBefore(StartMI, RangesI->second))123return RangesI;124}125return std::nullopt;126}127128void DbgValueHistoryMap::trimLocationRanges(129const MachineFunction &MF, LexicalScopes &LScopes,130const InstructionOrdering &Ordering) {131// The indices of the entries we're going to remove for each variable.132SmallVector<EntryIndex, 4> ToRemove;133// Entry reference count for each variable. Clobbers left with no references134// will be removed.135SmallVector<int, 4> ReferenceCount;136// Entries reference other entries by index. Offsets is used to remap these137// references if any entries are removed.138SmallVector<size_t, 4> Offsets;139140LLVM_DEBUG(dbgs() << "Trimming location ranges for function '" << MF.getName()141<< "'\n");142143for (auto &Record : VarEntries) {144auto &HistoryMapEntries = Record.second;145if (HistoryMapEntries.empty())146continue;147148InlinedEntity Entity = Record.first;149const DILocalVariable *LocalVar = cast<DILocalVariable>(Entity.first);150151LexicalScope *Scope = nullptr;152if (const DILocation *InlinedAt = Entity.second) {153Scope = LScopes.findInlinedScope(LocalVar->getScope(), InlinedAt);154} else {155Scope = LScopes.findLexicalScope(LocalVar->getScope());156// Ignore variables for non-inlined function level scopes. The scope157// ranges (from scope->getRanges()) will not include any instructions158// before the first one with a debug-location, which could cause us to159// incorrectly drop a location. We could introduce special casing for160// these variables, but it doesn't seem worth it because no out-of-scope161// locations have been observed for variables declared in function level162// scopes.163if (Scope &&164(Scope->getScopeNode() == Scope->getScopeNode()->getSubprogram()) &&165(Scope->getScopeNode() == LocalVar->getScope()))166continue;167}168169// If there is no scope for the variable then something has probably gone170// wrong.171if (!Scope)172continue;173174ToRemove.clear();175// Zero the reference counts.176ReferenceCount.assign(HistoryMapEntries.size(), 0);177// Index of the DBG_VALUE which marks the start of the current location178// range.179EntryIndex StartIndex = 0;180ArrayRef<InsnRange> ScopeRanges(Scope->getRanges());181for (auto EI = HistoryMapEntries.begin(), EE = HistoryMapEntries.end();182EI != EE; ++EI, ++StartIndex) {183// Only DBG_VALUEs can open location ranges so skip anything else.184if (!EI->isDbgValue())185continue;186187// Index of the entry which closes this range.188EntryIndex EndIndex = EI->getEndIndex();189// If this range is closed bump the reference count of the closing entry.190if (EndIndex != NoEntry)191ReferenceCount[EndIndex] += 1;192// Skip this location range if the opening entry is still referenced. It193// may close a location range which intersects a scope range.194// TODO: We could be 'smarter' and trim these kinds of ranges such that195// they do not leak out of the scope ranges if they partially overlap.196if (ReferenceCount[StartIndex] > 0)197continue;198199const MachineInstr *StartMI = EI->getInstr();200const MachineInstr *EndMI = EndIndex != NoEntry201? HistoryMapEntries[EndIndex].getInstr()202: nullptr;203// Check if the location range [StartMI, EndMI] intersects with any scope204// range for the variable.205if (auto R = intersects(StartMI, EndMI, ScopeRanges, Ordering)) {206// Adjust ScopeRanges to exclude ranges which subsequent location ranges207// cannot possibly intersect.208ScopeRanges = ArrayRef<InsnRange>(*R, ScopeRanges.end());209} else {210// If the location range does not intersect any scope range then the211// DBG_VALUE which opened this location range is usless, mark it for212// removal.213ToRemove.push_back(StartIndex);214// Because we'll be removing this entry we need to update the reference215// count of the closing entry, if one exists.216if (EndIndex != NoEntry)217ReferenceCount[EndIndex] -= 1;218LLVM_DEBUG(dbgs() << "Dropping value outside scope range of variable: ";219StartMI->print(llvm::dbgs()););220}221}222223// If there is nothing to remove then jump to next variable.224if (ToRemove.empty())225continue;226227// Mark clobbers that will no longer close any location ranges for removal.228for (size_t i = 0; i < HistoryMapEntries.size(); ++i)229if (ReferenceCount[i] <= 0 && HistoryMapEntries[i].isClobber())230ToRemove.push_back(i);231232llvm::sort(ToRemove);233234// Build an offset map so we can update the EndIndex of the remaining235// entries.236// Zero the offsets.237Offsets.assign(HistoryMapEntries.size(), 0);238size_t CurOffset = 0;239auto ToRemoveItr = ToRemove.begin();240for (size_t EntryIdx = *ToRemoveItr; EntryIdx < HistoryMapEntries.size();241++EntryIdx) {242// Check if this is an entry which will be removed.243if (ToRemoveItr != ToRemove.end() && *ToRemoveItr == EntryIdx) {244++ToRemoveItr;245++CurOffset;246}247Offsets[EntryIdx] = CurOffset;248}249250// Update the EndIndex of the entries to account for those which will be251// removed.252for (auto &Entry : HistoryMapEntries)253if (Entry.isClosed())254Entry.EndIndex -= Offsets[Entry.EndIndex];255256// Now actually remove the entries. Iterate backwards so that our remaining257// ToRemove indices are valid after each erase.258for (EntryIndex Idx : llvm::reverse(ToRemove))259HistoryMapEntries.erase(HistoryMapEntries.begin() + Idx);260LLVM_DEBUG(llvm::dbgs() << "New HistoryMap('" << LocalVar->getName()261<< "') size: " << HistoryMapEntries.size() << "\n");262}263}264265bool DbgValueHistoryMap::hasNonEmptyLocation(const Entries &Entries) const {266for (const auto &Entry : Entries) {267if (!Entry.isDbgValue())268continue;269270const MachineInstr *MI = Entry.getInstr();271assert(MI->isDebugValue());272// A DBG_VALUE $noreg is an empty variable location273if (MI->isUndefDebugValue())274continue;275276return true;277}278279return false;280}281282void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) {283assert(MI.isDebugLabel() && "not a DBG_LABEL");284LabelInstr[Label] = &MI;285}286287namespace {288289// Maps physreg numbers to the variables they describe.290using InlinedEntity = DbgValueHistoryMap::InlinedEntity;291using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;292293// Keeps track of the debug value entries that are currently live for each294// inlined entity. As the history map entries are stored in a SmallVector, they295// may be moved at insertion of new entries, so store indices rather than296// pointers.297using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>;298299} // end anonymous namespace300301// Claim that @Var is not described by @RegNo anymore.302static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,303InlinedEntity Var) {304const auto &I = RegVars.find(RegNo);305assert(RegNo != 0U && I != RegVars.end());306auto &VarSet = I->second;307const auto &VarPos = llvm::find(VarSet, Var);308assert(VarPos != VarSet.end());309VarSet.erase(VarPos);310// Don't keep empty sets in a map to keep it as small as possible.311if (VarSet.empty())312RegVars.erase(I);313}314315// Claim that @Var is now described by @RegNo.316static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,317InlinedEntity Var) {318assert(RegNo != 0U);319auto &VarSet = RegVars[RegNo];320assert(!is_contained(VarSet, Var));321VarSet.push_back(Var);322}323324/// Create a clobbering entry and end all open debug value entries325/// for \p Var that are described by \p RegNo using that entry. Inserts into \p326/// FellowRegisters the set of Registers that were also used to describe \p Var327/// alongside \p RegNo.328static void clobberRegEntries(InlinedEntity Var, unsigned RegNo,329const MachineInstr &ClobberingInstr,330DbgValueEntriesMap &LiveEntries,331DbgValueHistoryMap &HistMap,332SmallVectorImpl<Register> &FellowRegisters) {333EntryIndex ClobberIndex = HistMap.startClobber(Var, ClobberingInstr);334// Close all entries whose values are described by the register.335SmallVector<EntryIndex, 4> IndicesToErase;336// If a given register appears in a live DBG_VALUE_LIST for Var alongside the337// clobbered register, and never appears in a live DBG_VALUE* for Var without338// the clobbered register, then it is no longer linked to the variable.339SmallSet<Register, 4> MaybeRemovedRegisters;340SmallSet<Register, 4> KeepRegisters;341for (auto Index : LiveEntries[Var]) {342auto &Entry = HistMap.getEntry(Var, Index);343assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");344if (Entry.getInstr()->isDebugEntryValue())345continue;346if (Entry.getInstr()->hasDebugOperandForReg(RegNo)) {347IndicesToErase.push_back(Index);348Entry.endEntry(ClobberIndex);349for (const auto &MO : Entry.getInstr()->debug_operands())350if (MO.isReg() && MO.getReg() && MO.getReg() != RegNo)351MaybeRemovedRegisters.insert(MO.getReg());352} else {353for (const auto &MO : Entry.getInstr()->debug_operands())354if (MO.isReg() && MO.getReg())355KeepRegisters.insert(MO.getReg());356}357}358359for (Register Reg : MaybeRemovedRegisters)360if (!KeepRegisters.contains(Reg))361FellowRegisters.push_back(Reg);362363// Drop all entries that have ended.364for (auto Index : IndicesToErase)365LiveEntries[Var].erase(Index);366}367368/// Add a new debug value for \p Var. Closes all overlapping debug values.369static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV,370RegDescribedVarsMap &RegVars,371DbgValueEntriesMap &LiveEntries,372DbgValueHistoryMap &HistMap) {373EntryIndex NewIndex;374if (HistMap.startDbgValue(Var, DV, NewIndex)) {375SmallDenseMap<unsigned, bool, 4> TrackedRegs;376377// If we have created a new debug value entry, close all preceding378// live entries that overlap.379SmallVector<EntryIndex, 4> IndicesToErase;380const DIExpression *DIExpr = DV.getDebugExpression();381for (auto Index : LiveEntries[Var]) {382auto &Entry = HistMap.getEntry(Var, Index);383assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");384const MachineInstr &DV = *Entry.getInstr();385bool Overlaps = DIExpr->fragmentsOverlap(DV.getDebugExpression());386if (Overlaps) {387IndicesToErase.push_back(Index);388Entry.endEntry(NewIndex);389}390if (!DV.isDebugEntryValue())391for (const MachineOperand &Op : DV.debug_operands())392if (Op.isReg() && Op.getReg())393TrackedRegs[Op.getReg()] |= !Overlaps;394}395396// If the new debug value is described by a register, add tracking of397// that register if it is not already tracked.398if (!DV.isDebugEntryValue()) {399for (const MachineOperand &Op : DV.debug_operands()) {400if (Op.isReg() && Op.getReg()) {401Register NewReg = Op.getReg();402if (!TrackedRegs.count(NewReg))403addRegDescribedVar(RegVars, NewReg, Var);404LiveEntries[Var].insert(NewIndex);405TrackedRegs[NewReg] = true;406}407}408}409410// Drop tracking of registers that are no longer used.411for (auto I : TrackedRegs)412if (!I.second)413dropRegDescribedVar(RegVars, I.first, Var);414415// Drop all entries that have ended, and mark the new entry as live.416for (auto Index : IndicesToErase)417LiveEntries[Var].erase(Index);418LiveEntries[Var].insert(NewIndex);419}420}421422// Terminate the location range for variables described by register at423// @I by inserting @ClobberingInstr to their history.424static void clobberRegisterUses(RegDescribedVarsMap &RegVars,425RegDescribedVarsMap::iterator I,426DbgValueHistoryMap &HistMap,427DbgValueEntriesMap &LiveEntries,428const MachineInstr &ClobberingInstr) {429// Iterate over all variables described by this register and add this430// instruction to their history, clobbering it. All registers that also431// describe the clobbered variables (i.e. in variadic debug values) will have432// those Variables removed from their DescribedVars.433for (const auto &Var : I->second) {434SmallVector<Register, 4> FellowRegisters;435clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap,436FellowRegisters);437for (Register RegNo : FellowRegisters)438dropRegDescribedVar(RegVars, RegNo, Var);439}440RegVars.erase(I);441}442443// Terminate the location range for variables described by register444// @RegNo by inserting @ClobberingInstr to their history.445static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,446DbgValueHistoryMap &HistMap,447DbgValueEntriesMap &LiveEntries,448const MachineInstr &ClobberingInstr) {449const auto &I = RegVars.find(RegNo);450if (I == RegVars.end())451return;452clobberRegisterUses(RegVars, I, HistMap, LiveEntries, ClobberingInstr);453}454455void llvm::calculateDbgEntityHistory(const MachineFunction *MF,456const TargetRegisterInfo *TRI,457DbgValueHistoryMap &DbgValues,458DbgLabelInstrMap &DbgLabels) {459const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();460Register SP = TLI->getStackPointerRegisterToSaveRestore();461Register FrameReg = TRI->getFrameRegister(*MF);462RegDescribedVarsMap RegVars;463DbgValueEntriesMap LiveEntries;464for (const auto &MBB : *MF) {465for (const auto &MI : MBB) {466if (MI.isDebugValue()) {467assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");468// Use the base variable (without any DW_OP_piece expressions)469// as index into History. The full variables including the470// piece expressions are attached to the MI.471const DILocalVariable *RawVar = MI.getDebugVariable();472assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) &&473"Expected inlined-at fields to agree");474InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt());475476handleNewDebugValue(Var, MI, RegVars, LiveEntries, DbgValues);477} else if (MI.isDebugLabel()) {478assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!");479const DILabel *RawLabel = MI.getDebugLabel();480assert(RawLabel->isValidLocationForIntrinsic(MI.getDebugLoc()) &&481"Expected inlined-at fields to agree");482// When collecting debug information for labels, there is no MCSymbol483// generated for it. So, we keep MachineInstr in DbgLabels in order484// to query MCSymbol afterward.485InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt());486DbgLabels.addInstr(L, MI);487}488489// Meta Instructions have no output and do not change any values and so490// can be safely ignored.491if (MI.isMetaInstruction())492continue;493494// Not a DBG_VALUE instruction. It may clobber registers which describe495// some variables.496for (const MachineOperand &MO : MI.operands()) {497if (MO.isReg() && MO.isDef() && MO.getReg()) {498// Ignore call instructions that claim to clobber SP. The AArch64499// backend does this for aggregate function arguments.500if (MI.isCall() && MO.getReg() == SP)501continue;502// If this is a virtual register, only clobber it since it doesn't503// have aliases.504if (MO.getReg().isVirtual())505clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries,506MI);507// If this is a register def operand, it may end a debug value508// range. Ignore frame-register defs in the epilogue and prologue,509// we expect debuggers to understand that stack-locations are510// invalid outside of the function body.511else if (MO.getReg() != FrameReg ||512(!MI.getFlag(MachineInstr::FrameDestroy) &&513!MI.getFlag(MachineInstr::FrameSetup))) {514for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();515++AI)516clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI);517}518} else if (MO.isRegMask()) {519// If this is a register mask operand, clobber all debug values in520// non-CSRs.521SmallVector<unsigned, 32> RegsToClobber;522// Don't consider SP to be clobbered by register masks.523for (auto It : RegVars) {524unsigned int Reg = It.first;525if (Reg != SP && Register::isPhysicalRegister(Reg) &&526MO.clobbersPhysReg(Reg))527RegsToClobber.push_back(Reg);528}529530for (unsigned Reg : RegsToClobber) {531clobberRegisterUses(RegVars, Reg, DbgValues, LiveEntries, MI);532}533}534} // End MO loop.535} // End instr loop.536537// Make sure locations for all variables are valid only until the end of538// the basic block (unless it's the last basic block, in which case let539// their liveness run off to the end of the function).540if (!MBB.empty() && &MBB != &MF->back()) {541// Iterate over all variables that have open debug values.542for (auto &Pair : LiveEntries) {543if (Pair.second.empty())544continue;545546// Create a clobbering entry.547EntryIndex ClobIdx = DbgValues.startClobber(Pair.first, MBB.back());548549// End all entries.550for (EntryIndex Idx : Pair.second) {551DbgValueHistoryMap::Entry &Ent = DbgValues.getEntry(Pair.first, Idx);552assert(Ent.isDbgValue() && !Ent.isClosed());553Ent.endEntry(ClobIdx);554}555}556557LiveEntries.clear();558RegVars.clear();559}560}561}562563#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)564LLVM_DUMP_METHOD void DbgValueHistoryMap::dump(StringRef FuncName) const {565dbgs() << "DbgValueHistoryMap('" << FuncName << "'):\n";566for (const auto &VarRangePair : *this) {567const InlinedEntity &Var = VarRangePair.first;568const Entries &Entries = VarRangePair.second;569570const DILocalVariable *LocalVar = cast<DILocalVariable>(Var.first);571const DILocation *Location = Var.second;572573dbgs() << " - " << LocalVar->getName() << " at ";574575if (Location)576dbgs() << Location->getFilename() << ":" << Location->getLine() << ":"577<< Location->getColumn();578else579dbgs() << "<unknown location>";580581dbgs() << " --\n";582583for (const auto &E : enumerate(Entries)) {584const auto &Entry = E.value();585dbgs() << " Entry[" << E.index() << "]: ";586if (Entry.isDbgValue())587dbgs() << "Debug value\n";588else589dbgs() << "Clobber\n";590dbgs() << " Instr: " << *Entry.getInstr();591if (Entry.isDbgValue()) {592if (Entry.getEndIndex() == NoEntry)593dbgs() << " - Valid until end of function\n";594else595dbgs() << " - Closed by Entry[" << Entry.getEndIndex() << "]\n";596}597dbgs() << "\n";598}599}600}601#endif602603604