diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -182,6 +182,7 @@ WinEHPrepare.cpp XRayInstrumentation.cpp + LiveDebugValues/LiveDebugValues.cpp LiveDebugValues/VarLocBasedImpl.cpp ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.h @@ -0,0 +1,31 @@ +//===- LiveDebugValues.cpp - Tracking Debug Value MIs ---------*- C++ -*---===// +// +// 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/MachineFunction.h" +#include "llvm/CodeGen/TargetPassConfig.h" + +namespace llvm { + +// Inline namespace for types / symbols shared between different +// LiveDebugValues implementations. +inline namespace SharedLiveDebugValues { + +// Expose a base class for LiveDebugValues interfaces to inherit from. This +// allows the generic LiveDebugValues pass handles to call into the +// implementation. +class LDVImpl { +public: + virtual bool ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC) = 0; + virtual ~LDVImpl() {} +}; + +} // namespace SharedLiveDebugValues + +// Factory functions for LiveDebugValues implementations. +extern LDVImpl *makeVarLocBasedLiveDebugValues(); +} // namespace llvm diff --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp @@ -0,0 +1,78 @@ +//===- LiveDebugValues.cpp - Tracking Debug Value MIs ---------------------===// +// +// 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 "LiveDebugValues.h" + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" + +/// \file LiveDebugValues.cpp +/// +/// The LiveDebugValues pass extends the range of variable locations +/// (specified by DBG_VALUE instructions) from single blocks to successors +/// and any other code locations where the variable location is valid. +/// There are currently two implementations: the "VarLoc" implementation +/// explicitly tracks the location of a variable, while the "InstrRef" +/// implementation tracks the values defined by instructions through locations. +/// +/// This file implements neither; it merely registers the pass, allows the +/// user to pick which implementation will be used to propagate variable +/// locations. + +#define DEBUG_TYPE "livedebugvalues" + +using namespace llvm; + +/// Generic LiveDebugValues pass. Calls through to VarLocBasedLDV or +/// InstrRefBasedLDV to perform location propagation, via the LDVImpl +/// base class. +class LiveDebugValues : public MachineFunctionPass { +public: + static char ID; + + LiveDebugValues(); + ~LiveDebugValues() { delete TheImpl; } + + /// Calculate the liveness information for the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + +private: + LDVImpl *TheImpl; +}; + +char LiveDebugValues::ID = 0; + +char &llvm::LiveDebugValuesID = LiveDebugValues::ID; + +INITIALIZE_PASS(LiveDebugValues, DEBUG_TYPE, "Live DEBUG_VALUE analysis", false, + false) + +/// Default construct and initialize the pass. +LiveDebugValues::LiveDebugValues() : MachineFunctionPass(ID) { + initializeLiveDebugValuesPass(*PassRegistry::getPassRegistry()); + TheImpl = llvm::makeVarLocBasedLiveDebugValues(); +} + +bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) { + auto *TPC = getAnalysisIfAvailable(); + return TheImpl->ExtendRanges(MF, TPC); +} diff --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp @@ -1,4 +1,4 @@ -//===- LiveDebugValues.cpp - Tracking Debug Value MIs ---------------------===// +//===- VarLocBasedImpl.cpp - Tracking Debug Value MIs with VarLoc class----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// /// -/// \file LiveDebugValues.cpp +/// \file VarLocBasedImpl.cpp /// /// LiveDebugValues is an optimistic "available expressions" dataflow /// algorithm. The set of expressions is the set of machine locations @@ -17,6 +17,11 @@ /// DebugVariable, and continues until that location is clobbered or /// re-specified by a different DBG_VALUE for the same DebugVariable. /// +/// The output of LiveDebugValues is additional DBG_VALUE instructions, +/// placed to extend variable locations as far they're available. This file +/// and the VarLocBasedLDV class is an implementation that explicitly tracks +/// locations, using the VarLoc class. +/// /// The cannonical "available expressions" problem doesn't have expression /// clobbering, instead when a variable is re-assigned, any expressions using /// that variable get invalidated. LiveDebugValues can map onto "available @@ -101,6 +106,8 @@ /// //===----------------------------------------------------------------------===// +#include "LiveDebugValues.h" + #include "llvm/ADT/CoalescingBitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PostOrderIterator.h" @@ -264,11 +271,12 @@ } }; -class LiveDebugValues : public MachineFunctionPass { +class VarLocBasedLDV : public LDVImpl { private: const TargetRegisterInfo *TRI; const TargetInstrInfo *TII; const TargetFrameLowering *TFI; + TargetPassConfig *TPC; BitVector CalleeSavedRegs; LexicalScopes LS; VarLocSet::Allocator Alloc; @@ -457,7 +465,7 @@ llvm_unreachable( "Tried to produce DBG_VALUE for invalid or backup VarLoc"); } - llvm_unreachable("Unrecognized LiveDebugValues.VarLoc.Kind enum"); + llvm_unreachable("Unrecognized VarLocBasedLDV.VarLoc.Kind enum"); } /// Is the Loc field a constant or constant object? @@ -793,30 +801,18 @@ /// had their instruction creation deferred. void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs); - bool ExtendRanges(MachineFunction &MF); + bool ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC); public: - static char ID; - /// Default construct and initialize the pass. - LiveDebugValues(); + VarLocBasedLDV(); - /// Tell the pass manager which passes we depend on and what - /// information we preserve. - void getAnalysisUsage(AnalysisUsage &AU) const override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } + ~VarLocBasedLDV(); /// Print to ostream with a message. void printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V, const VarLocMap &VarLocIDs, const char *msg, raw_ostream &Out) const; - - /// Calculate the liveness information for the given machine function. - bool runOnMachineFunction(MachineFunction &MF) override; }; } // end anonymous namespace @@ -825,31 +821,16 @@ // Implementation //===----------------------------------------------------------------------===// -char LiveDebugValues::ID = 0; - -char &llvm::LiveDebugValuesID = LiveDebugValues::ID; - -INITIALIZE_PASS(LiveDebugValues, DEBUG_TYPE, "Live DEBUG_VALUE analysis", - false, false) - -/// Default construct and initialize the pass. -LiveDebugValues::LiveDebugValues() : MachineFunctionPass(ID) { - initializeLiveDebugValuesPass(*PassRegistry::getPassRegistry()); -} +VarLocBasedLDV::VarLocBasedLDV() { } -/// Tell the pass manager which passes we depend on and what information we -/// preserve. -void LiveDebugValues::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); -} +VarLocBasedLDV::~VarLocBasedLDV() { } /// Erase a variable from the set of open ranges, and additionally erase any /// fragments that may overlap it. If the VarLoc is a buckup location, erase /// the variable from the EntryValuesBackupVars set, indicating we should stop /// tracking its backup entry location. Otherwise, if the VarLoc is primary /// location, erase the variable from the Vars set. -void LiveDebugValues::OpenRangesSet::erase(const VarLoc &VL) { +void VarLocBasedLDV::OpenRangesSet::erase(const VarLoc &VL) { // Erasure helper. auto DoErase = [VL, this](DebugVariable VarToErase) { auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars; @@ -875,15 +856,15 @@ auto MapIt = OverlappingFragments.find({Var.getVariable(), ThisFragment}); if (MapIt != OverlappingFragments.end()) { for (auto Fragment : MapIt->second) { - LiveDebugValues::OptFragmentInfo FragmentHolder; + VarLocBasedLDV::OptFragmentInfo FragmentHolder; if (!DebugVariable::isDefaultFragment(Fragment)) - FragmentHolder = LiveDebugValues::OptFragmentInfo(Fragment); + FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment); DoErase({Var.getVariable(), FragmentHolder, Var.getInlinedAt()}); } } } -void LiveDebugValues::OpenRangesSet::erase(const VarLocSet &KillSet, +void VarLocBasedLDV::OpenRangesSet::erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs) { VarLocs.intersectWithComplement(KillSet); for (uint64_t ID : KillSet) { @@ -893,7 +874,7 @@ } } -void LiveDebugValues::OpenRangesSet::insert(LocIndex VarLocID, +void VarLocBasedLDV::OpenRangesSet::insert(LocIndex VarLocID, const VarLoc &VL) { auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars; VarLocs.set(VarLocID.getAsRawInteger()); @@ -903,7 +884,7 @@ /// Return the Loc ID of an entry value backup location, if it exists for the /// variable. llvm::Optional -LiveDebugValues::OpenRangesSet::getEntryValueBackup(DebugVariable Var) { +VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) { auto It = EntryValuesBackupVars.find(Var); if (It != EntryValuesBackupVars.end()) return It->second; @@ -911,7 +892,7 @@ return llvm::None; } -void LiveDebugValues::collectIDsForRegs(VarLocSet &Collected, +void VarLocBasedLDV::collectIDsForRegs(VarLocSet &Collected, const DefinedRegsSet &Regs, const VarLocSet &CollectFrom) const { assert(!Regs.empty() && "Nothing to collect"); @@ -937,7 +918,7 @@ } } -void LiveDebugValues::getUsedRegs(const VarLocSet &CollectFrom, +void VarLocBasedLDV::getUsedRegs(const VarLocSet &CollectFrom, SmallVectorImpl &UsedRegs) const { // All register-based VarLocs are assigned indices greater than or equal to // FirstRegIndex. @@ -967,7 +948,7 @@ //===----------------------------------------------------------------------===// #ifndef NDEBUG -void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF, +void VarLocBasedLDV::printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V, const VarLocMap &VarLocIDs, const char *msg, @@ -991,8 +972,8 @@ } #endif -LiveDebugValues::VarLoc::SpillLoc -LiveDebugValues::extractSpillBaseRegAndOffset(const MachineInstr &MI) { +VarLocBasedLDV::VarLoc::SpillLoc +VarLocBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) { assert(MI.hasOneMemOperand() && "Spill instruction does not have exactly one memory operand?"); auto MMOI = MI.memoperands_begin(); @@ -1009,7 +990,7 @@ /// Try to salvage the debug entry value if we encounter a new debug value /// describing the same parameter, otherwise stop tracking the value. Return /// true if we should stop tracking the entry value, otherwise return false. -bool LiveDebugValues::removeEntryValue(const MachineInstr &MI, +bool VarLocBasedLDV::removeEntryValue(const MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, const VarLoc &EntryVL) { @@ -1061,7 +1042,7 @@ /// End all previous ranges related to @MI and start a new range from @MI /// if it is a DBG_VALUE instr. -void LiveDebugValues::transferDebugValue(const MachineInstr &MI, +void VarLocBasedLDV::transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs) { if (!MI.isDebugValue()) @@ -1112,7 +1093,7 @@ } /// Turn the entry value backup locations into primary locations. -void LiveDebugValues::emitEntryValues(MachineInstr &MI, +void VarLocBasedLDV::emitEntryValues(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, TransferMap &Transfers, @@ -1150,7 +1131,7 @@ /// new VarLoc. If \p NewReg is different than default zero value then the /// new location will be register location created by the copy like instruction, /// otherwise it is variable's location on the stack. -void LiveDebugValues::insertTransferDebugPair( +void VarLocBasedLDV::insertTransferDebugPair( MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers, VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind, Register NewReg) { @@ -1217,7 +1198,7 @@ } /// A definition of a register may mark the end of a range. -void LiveDebugValues::transferRegisterDef( +void VarLocBasedLDV::transferRegisterDef( MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, TransferMap &Transfers) { @@ -1278,14 +1259,14 @@ collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs()); OpenRanges.erase(KillSet, VarLocIDs); - if (auto *TPC = getAnalysisIfAvailable()) { + if (TPC) { auto &TM = TPC->getTM(); if (TM.Options.ShouldEmitDebugEntryValues()) emitEntryValues(MI, OpenRanges, VarLocIDs, Transfers, KillSet); } } -bool LiveDebugValues::isSpillInstruction(const MachineInstr &MI, +bool VarLocBasedLDV::isSpillInstruction(const MachineInstr &MI, MachineFunction *MF) { // TODO: Handle multiple stores folded into one. if (!MI.hasOneMemOperand()) @@ -1298,7 +1279,7 @@ return true; } -bool LiveDebugValues::isLocationSpill(const MachineInstr &MI, +bool VarLocBasedLDV::isLocationSpill(const MachineInstr &MI, MachineFunction *MF, Register &Reg) { if (!isSpillInstruction(MI, MF)) return false; @@ -1338,8 +1319,8 @@ return false; } -Optional -LiveDebugValues::isRestoreInstruction(const MachineInstr &MI, +Optional +VarLocBasedLDV::isRestoreInstruction(const MachineInstr &MI, MachineFunction *MF, Register &Reg) { if (!MI.hasOneMemOperand()) return None; @@ -1360,7 +1341,7 @@ /// the DBG_VALUE without inserting it and keep track of it in \p Transfers. /// It will be inserted into the BB when we're done iterating over the /// instructions. -void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI, +void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, TransferMap &Transfers) { @@ -1449,7 +1430,7 @@ /// If \p MI is a register copy instruction, that copies a previously tracked /// value from one register to another register that is callee saved, we /// create new DBG_VALUE instruction described with copy destination register. -void LiveDebugValues::transferRegisterCopy(MachineInstr &MI, +void VarLocBasedLDV::transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, TransferMap &Transfers) { @@ -1519,7 +1500,7 @@ } /// Terminate all open ranges at the end of the current basic block. -bool LiveDebugValues::transferTerminator(MachineBasicBlock *CurMBB, +bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB, OpenRangesSet &OpenRanges, VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs) { @@ -1551,7 +1532,7 @@ /// Variable which are known to exist. /// \param OverlappingFragments The overlap map being constructed, from one /// Var/Fragment pair to a vector of fragments known to overlap. -void LiveDebugValues::accumulateFragmentMap(MachineInstr &MI, +void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &MI, VarToFragments &SeenFragments, OverlapMap &OverlappingFragments) { DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(), @@ -1603,7 +1584,7 @@ } /// This routine creates OpenRanges. -void LiveDebugValues::process(MachineInstr &MI, OpenRangesSet &OpenRanges, +void VarLocBasedLDV::process(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, TransferMap &Transfers) { transferDebugValue(MI, OpenRanges, VarLocIDs); transferRegisterDef(MI, OpenRanges, VarLocIDs, Transfers); @@ -1614,7 +1595,7 @@ /// This routine joins the analysis results of all incoming edges in @MBB by /// inserting a new DBG_VALUE instruction at the start of the @MBB - if the same /// source variable in all the predecessors of @MBB reside in the same location. -bool LiveDebugValues::join( +bool VarLocBasedLDV::join( MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs, const VarLocMap &VarLocIDs, SmallPtrSet &Visited, @@ -1697,7 +1678,7 @@ return Changed; } -void LiveDebugValues::flushPendingLocs(VarLocInMBB &PendingInLocs, +void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs) { // PendingInLocs records all locations propagated into blocks, which have // not had DBG_VALUE insts created. Go through and create those insts now. @@ -1721,7 +1702,7 @@ } } -bool LiveDebugValues::isEntryValueCandidate( +bool VarLocBasedLDV::isEntryValueCandidate( const MachineInstr &MI, const DefinedRegsSet &DefinedRegs) const { assert(MI.isDebugValue() && "This must be DBG_VALUE."); @@ -1770,11 +1751,11 @@ /// This routine records the entry values of function parameters. The values /// could be used as backup values. If we loose the track of some unmodified /// parameters, the backup values will be used as a primary locations. -void LiveDebugValues::recordEntryValue(const MachineInstr &MI, +void VarLocBasedLDV::recordEntryValue(const MachineInstr &MI, const DefinedRegsSet &DefinedRegs, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs) { - if (auto *TPC = getAnalysisIfAvailable()) { + if (TPC) { auto &TM = TPC->getTM(); if (!TM.Options.ShouldEmitDebugEntryValues()) return; @@ -1800,9 +1781,25 @@ /// Calculate the liveness information for the given machine function and /// extend ranges across basic blocks. -bool LiveDebugValues::ExtendRanges(MachineFunction &MF) { +bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF, TargetPassConfig *TPC) { LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n"); + if (!MF.getFunction().getSubprogram()) + // VarLocBaseLDV will already have removed all DBG_VALUEs. + return false; + + // Skip functions from NoDebug compilation units. + if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == + DICompileUnit::NoDebug) + return false; + + TRI = MF.getSubtarget().getRegisterInfo(); + TII = MF.getSubtarget().getInstrInfo(); + TFI = MF.getSubtarget().getFrameLowering(); + TFI->getCalleeSaves(MF, CalleeSavedRegs); + this->TPC = TPC; + LS.initialize(MF); + bool Changed = false; bool OLChanged = false; bool MBBJoined = false; @@ -1878,7 +1875,7 @@ if (MI.isDebugValue()) ++NumInputDbgValues; if (NumInputDbgValues > InputDbgValueLimit) { - LLVM_DEBUG(dbgs() << "Disabling LiveDebugValues: " << MF.getName() + LLVM_DEBUG(dbgs() << "Disabling VarLocBasedLDV: " << MF.getName() << " has " << RPONumber << " basic blocks and " << NumInputDbgValues << " input DBG_VALUEs, exceeding limits.\n"); @@ -1955,22 +1952,8 @@ return Changed; } -bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) { - if (!MF.getFunction().getSubprogram()) - // LiveDebugValues will already have removed all DBG_VALUEs. - return false; - - // Skip functions from NoDebug compilation units. - if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == - DICompileUnit::NoDebug) - return false; - - TRI = MF.getSubtarget().getRegisterInfo(); - TII = MF.getSubtarget().getInstrInfo(); - TFI = MF.getSubtarget().getFrameLowering(); - TFI->getCalleeSaves(MF, CalleeSavedRegs); - LS.initialize(MF); - - bool Changed = ExtendRanges(MF); - return Changed; +LDVImpl * +llvm::makeVarLocBasedLiveDebugValues() +{ + return new VarLocBasedLDV(); }