diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp | 354 |
1 files changed, 207 insertions, 147 deletions
diff --git a/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 09867822c30a..ddd60575b6c0 100644 --- a/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -1,15 +1,15 @@ //===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" @@ -31,51 +31,62 @@ using namespace llvm; #define DEBUG_TYPE "dwarfdebug" +namespace { +using EntryIndex = DbgValueHistoryMap::EntryIndex; +} + // If @MI is a DBG_VALUE with debug value described by a // defined register, returns the number of this register. // In the other case, returns 0. -static unsigned isDescribedByReg(const MachineInstr &MI) { +static Register isDescribedByReg(const MachineInstr &MI) { assert(MI.isDebugValue()); assert(MI.getNumOperands() == 4); + // If the location of variable is an entry value (DW_OP_entry_value) + // do not consider it as a register location. + if (MI.getDebugExpression()->isEntryValue()) + return 0; // If location of variable is described using a register (directly or // indirectly), this register is always a first operand. - return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; + return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : Register(); } -void DbgValueHistoryMap::startInstrRange(InlinedEntity Var, - const MachineInstr &MI) { +bool DbgValueHistoryMap::startDbgValue(InlinedEntity Var, + const MachineInstr &MI, + EntryIndex &NewIndex) { // Instruction range should start with a DBG_VALUE instruction for the // variable. assert(MI.isDebugValue() && "not a DBG_VALUE"); - auto &Ranges = VarInstrRanges[Var]; - if (!Ranges.empty() && Ranges.back().second == nullptr && - Ranges.back().first->isIdenticalTo(MI)) { + auto &Entries = VarEntries[Var]; + if (!Entries.empty() && Entries.back().isDbgValue() && + !Entries.back().isClosed() && + Entries.back().getInstr()->isIdenticalTo(MI)) { LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" - << "\t" << Ranges.back().first << "\t" << MI << "\n"); - return; + << "\t" << Entries.back().getInstr() << "\t" << MI + << "\n"); + return false; } - Ranges.push_back(std::make_pair(&MI, nullptr)); + Entries.emplace_back(&MI, Entry::DbgValue); + NewIndex = Entries.size() - 1; + return true; } -void DbgValueHistoryMap::endInstrRange(InlinedEntity Var, - const MachineInstr &MI) { - auto &Ranges = VarInstrRanges[Var]; - // Verify that the current instruction range is not yet closed. - assert(!Ranges.empty() && Ranges.back().second == nullptr); - // For now, instruction ranges are not allowed to cross basic block - // boundaries. - assert(Ranges.back().first->getParent() == MI.getParent()); - Ranges.back().second = &MI; +EntryIndex DbgValueHistoryMap::startClobber(InlinedEntity Var, + const MachineInstr &MI) { + auto &Entries = VarEntries[Var]; + // If an instruction clobbers multiple registers that the variable is + // described by, then we may have already created a clobbering instruction. + if (Entries.back().isClobber() && Entries.back().getInstr() == &MI) + return Entries.size() - 1; + Entries.emplace_back(&MI, Entry::Clobber); + return Entries.size() - 1; } -unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const { - const auto &I = VarInstrRanges.find(Var); - if (I == VarInstrRanges.end()) - return 0; - const auto &Ranges = I->second; - if (Ranges.empty() || Ranges.back().second != nullptr) - return 0; - return isDescribedByReg(*Ranges.back().first); +void DbgValueHistoryMap::Entry::endEntry(EntryIndex Index) { + // For now, instruction ranges are not allowed to cross basic block + // boundaries. + assert(isDbgValue() && "Setting end index for non-debug value"); + assert(!isClosed() && "End index has already been set"); + EndIndex = Index; } void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) { @@ -89,6 +100,12 @@ namespace { using InlinedEntity = DbgValueHistoryMap::InlinedEntity; using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>; +// Keeps track of the debug value entries that are currently live for each +// inlined entity. As the history map entries are stored in a SmallVector, they +// may be moved at insertion of new entries, so store indices rather than +// pointers. +using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>; + } // end anonymous namespace // Claim that @Var is not described by @RegNo anymore. @@ -114,16 +131,88 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, VarSet.push_back(Var); } +/// Create a clobbering entry and end all open debug value entries +/// for \p Var that are described by \p RegNo using that entry. +static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, + const MachineInstr &ClobberingInstr, + DbgValueEntriesMap &LiveEntries, + DbgValueHistoryMap &HistMap) { + EntryIndex ClobberIndex = HistMap.startClobber(Var, ClobberingInstr); + + // Close all entries whose values are described by the register. + SmallVector<EntryIndex, 4> IndicesToErase; + for (auto Index : LiveEntries[Var]) { + auto &Entry = HistMap.getEntry(Var, Index); + assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries"); + if (isDescribedByReg(*Entry.getInstr()) == RegNo) { + IndicesToErase.push_back(Index); + Entry.endEntry(ClobberIndex); + } + } + + // Drop all entries that have ended. + for (auto Index : IndicesToErase) + LiveEntries[Var].erase(Index); +} + +/// Add a new debug value for \p Var. Closes all overlapping debug values. +static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, + RegDescribedVarsMap &RegVars, + DbgValueEntriesMap &LiveEntries, + DbgValueHistoryMap &HistMap) { + EntryIndex NewIndex; + if (HistMap.startDbgValue(Var, DV, NewIndex)) { + SmallDenseMap<unsigned, bool, 4> TrackedRegs; + + // If we have created a new debug value entry, close all preceding + // live entries that overlap. + SmallVector<EntryIndex, 4> IndicesToErase; + const DIExpression *DIExpr = DV.getDebugExpression(); + for (auto Index : LiveEntries[Var]) { + auto &Entry = HistMap.getEntry(Var, Index); + assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries"); + const MachineInstr &DV = *Entry.getInstr(); + bool Overlaps = DIExpr->fragmentsOverlap(DV.getDebugExpression()); + if (Overlaps) { + IndicesToErase.push_back(Index); + Entry.endEntry(NewIndex); + } + if (unsigned Reg = isDescribedByReg(DV)) + TrackedRegs[Reg] |= !Overlaps; + } + + // If the new debug value is described by a register, add tracking of + // that register if it is not already tracked. + if (unsigned NewReg = isDescribedByReg(DV)) { + if (!TrackedRegs.count(NewReg)) + addRegDescribedVar(RegVars, NewReg, Var); + LiveEntries[Var].insert(NewIndex); + TrackedRegs[NewReg] = true; + } + + // Drop tracking of registers that are no longer used. + for (auto I : TrackedRegs) + if (!I.second) + dropRegDescribedVar(RegVars, I.first, Var); + + // Drop all entries that have ended, and mark the new entry as live. + for (auto Index : IndicesToErase) + LiveEntries[Var].erase(Index); + LiveEntries[Var].insert(NewIndex); + } +} + // Terminate the location range for variables described by register at // @I by inserting @ClobberingInstr to their history. static void clobberRegisterUses(RegDescribedVarsMap &RegVars, RegDescribedVarsMap::iterator I, DbgValueHistoryMap &HistMap, + DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr) { // Iterate over all variables described by this register and add this // instruction to their history, clobbering it. for (const auto &Var : I->second) - HistMap.endInstrRange(Var, ClobberingInstr); + clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap); RegVars.erase(I); } @@ -131,115 +220,25 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, // @RegNo by inserting @ClobberingInstr to their history. static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, DbgValueHistoryMap &HistMap, + DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr) { const auto &I = RegVars.find(RegNo); if (I == RegVars.end()) return; - clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr); -} - -// Returns the first instruction in @MBB which corresponds to -// the function epilogue, or nullptr if @MBB doesn't contain an epilogue. -static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) { - auto LastMI = MBB.getLastNonDebugInstr(); - if (LastMI == MBB.end() || !LastMI->isReturn()) - return nullptr; - // Assume that epilogue starts with instruction having the same debug location - // as the return instruction. - DebugLoc LastLoc = LastMI->getDebugLoc(); - auto Res = LastMI; - for (MachineBasicBlock::const_reverse_iterator I = LastMI.getReverse(), - E = MBB.rend(); - I != E; ++I) { - if (I->getDebugLoc() != LastLoc) - return &*Res; - Res = &*I; - } - // If all instructions have the same debug location, assume whole MBB is - // an epilogue. - return &*MBB.begin(); -} - -// Collect registers that are modified in the function body (their -// contents is changed outside of the prologue and epilogue). -static void collectChangingRegs(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - BitVector &Regs) { - for (const auto &MBB : *MF) { - auto FirstEpilogueInst = getFirstEpilogueInst(MBB); - - for (const auto &MI : MBB) { - // Avoid looking at prologue or epilogue instructions. - if (&MI == FirstEpilogueInst) - break; - if (MI.getFlag(MachineInstr::FrameSetup)) - continue; - - // Look for register defs and register masks. Register masks are - // typically on calls and they clobber everything not in the mask. - for (const MachineOperand &MO : MI.operands()) { - // Skip virtual registers since they are handled by the parent. - if (MO.isReg() && MO.isDef() && MO.getReg() && - !TRI->isVirtualRegister(MO.getReg())) { - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) - Regs.set(*AI); - } else if (MO.isRegMask()) { - Regs.setBitsNotInMask(MO.getRegMask()); - } - } - } - } + clobberRegisterUses(RegVars, I, HistMap, LiveEntries, ClobberingInstr); } void llvm::calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels) { - BitVector ChangingRegs(TRI->getNumRegs()); - collectChangingRegs(MF, TRI, ChangingRegs); - const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); + unsigned FrameReg = TRI->getFrameRegister(*MF); RegDescribedVarsMap RegVars; + DbgValueEntriesMap LiveEntries; for (const auto &MBB : *MF) { for (const auto &MI : MBB) { - if (!MI.isDebugInstr()) { - // Not a DBG_VALUE instruction. It may clobber registers which describe - // some variables. - for (const MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.isDef() && MO.getReg()) { - // Ignore call instructions that claim to clobber SP. The AArch64 - // backend does this for aggregate function arguments. - if (MI.isCall() && MO.getReg() == SP) - continue; - // If this is a virtual register, only clobber it since it doesn't - // have aliases. - if (TRI->isVirtualRegister(MO.getReg())) - clobberRegisterUses(RegVars, MO.getReg(), DbgValues, MI); - // If this is a register def operand, it may end a debug value - // range. - else { - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) - if (ChangingRegs.test(*AI)) - clobberRegisterUses(RegVars, *AI, DbgValues, MI); - } - } else if (MO.isRegMask()) { - // If this is a register mask operand, clobber all debug values in - // non-CSRs. - for (unsigned I : ChangingRegs.set_bits()) { - // Don't consider SP to be clobbered by register masks. - if (unsigned(I) != SP && TRI->isPhysicalRegister(I) && - MO.clobbersPhysReg(I)) { - clobberRegisterUses(RegVars, I, DbgValues, MI); - } - } - } - } - continue; - } - if (MI.isDebugValue()) { assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); // Use the base variable (without any DW_OP_piece expressions) @@ -250,13 +249,7 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, "Expected inlined-at fields to agree"); InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt()); - if (unsigned PrevReg = DbgValues.getRegisterForVar(Var)) - dropRegDescribedVar(RegVars, PrevReg, Var); - - DbgValues.startInstrRange(Var, MI); - - if (unsigned NewReg = isDescribedByReg(MI)) - addRegDescribedVar(RegVars, NewReg, Var); + handleNewDebugValue(Var, MI, RegVars, LiveEntries, DbgValues); } else if (MI.isDebugLabel()) { assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!"); const DILabel *RawLabel = MI.getDebugLabel(); @@ -268,18 +261,75 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt()); DbgLabels.addInstr(L, MI); } - } - // Make sure locations for register-described variables are valid only - // until the end of the basic block (unless it's the last basic block, in - // which case let their liveness run off to the end of the function). + if (MI.isDebugInstr()) + continue; + + // Not a DBG_VALUE instruction. It may clobber registers which describe + // some variables. + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.isDef() && MO.getReg()) { + // Ignore call instructions that claim to clobber SP. The AArch64 + // backend does this for aggregate function arguments. + if (MI.isCall() && MO.getReg() == SP) + continue; + // If this is a virtual register, only clobber it since it doesn't + // have aliases. + if (TRI->isVirtualRegister(MO.getReg())) + clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries, + MI); + // If this is a register def operand, it may end a debug value + // range. Ignore frame-register defs in the epilogue and prologue, + // we expect debuggers to understand that stack-locations are + // invalid outside of the function body. + else if (MO.getReg() != FrameReg || + (!MI.getFlag(MachineInstr::FrameDestroy) && + !MI.getFlag(MachineInstr::FrameSetup))) { + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); + ++AI) + clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI); + } + } else if (MO.isRegMask()) { + // If this is a register mask operand, clobber all debug values in + // non-CSRs. + SmallVector<unsigned, 32> RegsToClobber; + // Don't consider SP to be clobbered by register masks. + for (auto It : RegVars) { + unsigned int Reg = It.first; + if (Reg != SP && TRI->isPhysicalRegister(Reg) && + MO.clobbersPhysReg(Reg)) + RegsToClobber.push_back(Reg); + } + + for (unsigned Reg : RegsToClobber) { + clobberRegisterUses(RegVars, Reg, DbgValues, LiveEntries, MI); + } + } + } // End MO loop. + } // End instr loop. + + // Make sure locations for all variables are valid only until the end of + // the basic block (unless it's the last basic block, in which case let + // their liveness run off to the end of the function). if (!MBB.empty() && &MBB != &MF->back()) { - for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) { - auto CurElem = I++; // CurElem can be erased below. - if (TRI->isVirtualRegister(CurElem->first) || - ChangingRegs.test(CurElem->first)) - clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back()); + // Iterate over all variables that have open debug values. + for (auto &Pair : LiveEntries) { + if (Pair.second.empty()) + continue; + + // Create a clobbering entry. + EntryIndex ClobIdx = DbgValues.startClobber(Pair.first, MBB.back()); + + // End all entries. + for (EntryIndex Idx : Pair.second) { + DbgValueHistoryMap::Entry &Ent = DbgValues.getEntry(Pair.first, Idx); + assert(Ent.isDbgValue() && !Ent.isClosed()); + Ent.endEntry(ClobIdx); + } } + + LiveEntries.clear(); + RegVars.clear(); } } } @@ -289,7 +339,7 @@ LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const { dbgs() << "DbgValueHistoryMap:\n"; for (const auto &VarRangePair : *this) { const InlinedEntity &Var = VarRangePair.first; - const InstrRanges &Ranges = VarRangePair.second; + const Entries &Entries = VarRangePair.second; const DILocalVariable *LocalVar = cast<DILocalVariable>(Var.first); const DILocation *Location = Var.second; @@ -304,10 +354,20 @@ LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const { dbgs() << " --\n"; - for (const InstrRange &Range : Ranges) { - dbgs() << " Begin: " << *Range.first; - if (Range.second) - dbgs() << " End : " << *Range.second; + for (const auto &E : enumerate(Entries)) { + const auto &Entry = E.value(); + dbgs() << " Entry[" << E.index() << "]: "; + if (Entry.isDbgValue()) + dbgs() << "Debug value\n"; + else + dbgs() << "Clobber\n"; + dbgs() << " Instr: " << *Entry.getInstr(); + if (Entry.isDbgValue()) { + if (Entry.getEndIndex() == NoEntry) + dbgs() << " - Valid until end of function\n"; + else + dbgs() << " - Closed by Entry[" << Entry.getEndIndex() << "]\n"; + } dbgs() << "\n"; } } |