17d523365SDimitry Andric //===------ LiveDebugValues.cpp - Tracking Debug Value MIs ----------------===// 27d523365SDimitry Andric // 37d523365SDimitry Andric // The LLVM Compiler Infrastructure 47d523365SDimitry Andric // 57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source 67d523365SDimitry Andric // License. See LICENSE.TXT for details. 77d523365SDimitry Andric // 87d523365SDimitry Andric //===----------------------------------------------------------------------===// 97d523365SDimitry Andric /// 107d523365SDimitry Andric /// This pass implements a data flow analysis that propagates debug location 117d523365SDimitry Andric /// information by inserting additional DBG_VALUE instructions into the machine 127d523365SDimitry Andric /// instruction stream. The pass internally builds debug location liveness 137d523365SDimitry Andric /// ranges to determine the points where additional DBG_VALUEs need to be 147d523365SDimitry Andric /// inserted. 157d523365SDimitry Andric /// 167d523365SDimitry Andric /// This is a separate pass from DbgValueHistoryCalculator to facilitate 177d523365SDimitry Andric /// testing and improve modularity. 187d523365SDimitry Andric /// 197d523365SDimitry Andric //===----------------------------------------------------------------------===// 207d523365SDimitry Andric 21444ed5c5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 22444ed5c5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 233ca95b02SDimitry Andric #include "llvm/ADT/SparseBitVector.h" 243ca95b02SDimitry Andric #include "llvm/ADT/Statistic.h" 253ca95b02SDimitry Andric #include "llvm/ADT/UniqueVector.h" 267d523365SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 277d523365SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 287d523365SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 297d523365SDimitry Andric #include "llvm/CodeGen/Passes.h" 303ca95b02SDimitry Andric #include "llvm/IR/DebugInfo.h" 317d523365SDimitry Andric #include "llvm/Support/Debug.h" 327d523365SDimitry Andric #include "llvm/Support/raw_ostream.h" 337d523365SDimitry Andric #include "llvm/Target/TargetInstrInfo.h" 343ca95b02SDimitry Andric #include "llvm/Target/TargetLowering.h" 357d523365SDimitry Andric #include "llvm/Target/TargetRegisterInfo.h" 367d523365SDimitry Andric #include "llvm/Target/TargetSubtargetInfo.h" 377d523365SDimitry Andric #include <list> 383ca95b02SDimitry Andric #include <queue> 397d523365SDimitry Andric 407d523365SDimitry Andric using namespace llvm; 417d523365SDimitry Andric 427d523365SDimitry Andric #define DEBUG_TYPE "live-debug-values" 437d523365SDimitry Andric 447d523365SDimitry Andric STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted"); 457d523365SDimitry Andric 467d523365SDimitry Andric namespace { 477d523365SDimitry Andric 483ca95b02SDimitry Andric // \brief If @MI is a DBG_VALUE with debug value described by a defined 493ca95b02SDimitry Andric // register, returns the number of this register. In the other case, returns 0. 503ca95b02SDimitry Andric static unsigned isDbgValueDescribedByReg(const MachineInstr &MI) { 513ca95b02SDimitry Andric assert(MI.isDebugValue() && "expected a DBG_VALUE"); 523ca95b02SDimitry Andric assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE"); 533ca95b02SDimitry Andric // If location of variable is described using a register (directly 543ca95b02SDimitry Andric // or indirectly), this register is always a first operand. 553ca95b02SDimitry Andric return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; 563ca95b02SDimitry Andric } 573ca95b02SDimitry Andric 587d523365SDimitry Andric class LiveDebugValues : public MachineFunctionPass { 597d523365SDimitry Andric 607d523365SDimitry Andric private: 617d523365SDimitry Andric const TargetRegisterInfo *TRI; 627d523365SDimitry Andric const TargetInstrInfo *TII; 637d523365SDimitry Andric 643ca95b02SDimitry Andric /// Based on std::pair so it can be used as an index into a DenseMap. 657d523365SDimitry Andric typedef std::pair<const DILocalVariable *, const DILocation *> 663ca95b02SDimitry Andric DebugVariableBase; 677d523365SDimitry Andric /// A potentially inlined instance of a variable. 683ca95b02SDimitry Andric struct DebugVariable : public DebugVariableBase { 693ca95b02SDimitry Andric DebugVariable(const DILocalVariable *Var, const DILocation *InlinedAt) 703ca95b02SDimitry Andric : DebugVariableBase(Var, InlinedAt) {} 717d523365SDimitry Andric 723ca95b02SDimitry Andric const DILocalVariable *getVar() const { return this->first; }; 733ca95b02SDimitry Andric const DILocation *getInlinedAt() const { return this->second; }; 747d523365SDimitry Andric 753ca95b02SDimitry Andric bool operator<(const DebugVariable &DV) const { 763ca95b02SDimitry Andric if (getVar() == DV.getVar()) 773ca95b02SDimitry Andric return getInlinedAt() < DV.getInlinedAt(); 783ca95b02SDimitry Andric return getVar() < DV.getVar(); 797d523365SDimitry Andric } 807d523365SDimitry Andric }; 817d523365SDimitry Andric 823ca95b02SDimitry Andric /// A pair of debug variable and value location. 837d523365SDimitry Andric struct VarLoc { 843ca95b02SDimitry Andric const DebugVariable Var; 853ca95b02SDimitry Andric const MachineInstr &MI; ///< Only used for cloning a new DBG_VALUE. 867d523365SDimitry Andric 873ca95b02SDimitry Andric enum { InvalidKind = 0, RegisterKind } Kind; 887d523365SDimitry Andric 893ca95b02SDimitry Andric /// The value location. Stored separately to avoid repeatedly 903ca95b02SDimitry Andric /// extracting it from MI. 913ca95b02SDimitry Andric union { 923ca95b02SDimitry Andric struct { 933ca95b02SDimitry Andric uint32_t RegNo; 943ca95b02SDimitry Andric uint32_t Offset; 953ca95b02SDimitry Andric } RegisterLoc; 963ca95b02SDimitry Andric uint64_t Hash; 973ca95b02SDimitry Andric } Loc; 983ca95b02SDimitry Andric 993ca95b02SDimitry Andric VarLoc(const MachineInstr &MI) 1003ca95b02SDimitry Andric : Var(MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()), MI(MI), 1013ca95b02SDimitry Andric Kind(InvalidKind) { 1023ca95b02SDimitry Andric static_assert((sizeof(Loc) == sizeof(uint64_t)), 1033ca95b02SDimitry Andric "hash does not cover all members of Loc"); 1043ca95b02SDimitry Andric assert(MI.isDebugValue() && "not a DBG_VALUE"); 1053ca95b02SDimitry Andric assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE"); 1063ca95b02SDimitry Andric if (int RegNo = isDbgValueDescribedByReg(MI)) { 1073ca95b02SDimitry Andric Kind = RegisterKind; 1083ca95b02SDimitry Andric Loc.RegisterLoc.RegNo = RegNo; 1093ca95b02SDimitry Andric uint64_t Offset = 1103ca95b02SDimitry Andric MI.isIndirectDebugValue() ? MI.getOperand(1).getImm() : 0; 1113ca95b02SDimitry Andric // We don't support offsets larger than 4GiB here. They are 1123ca95b02SDimitry Andric // slated to be replaced with DIExpressions anyway. 1133ca95b02SDimitry Andric if (Offset >= (1ULL << 32)) 1143ca95b02SDimitry Andric Kind = InvalidKind; 1153ca95b02SDimitry Andric else 1163ca95b02SDimitry Andric Loc.RegisterLoc.Offset = Offset; 1173ca95b02SDimitry Andric } 1183ca95b02SDimitry Andric } 1193ca95b02SDimitry Andric 1203ca95b02SDimitry Andric /// If this variable is described by a register, return it, 1213ca95b02SDimitry Andric /// otherwise return 0. 1223ca95b02SDimitry Andric unsigned isDescribedByReg() const { 1233ca95b02SDimitry Andric if (Kind == RegisterKind) 1243ca95b02SDimitry Andric return Loc.RegisterLoc.RegNo; 1253ca95b02SDimitry Andric return 0; 1263ca95b02SDimitry Andric } 1273ca95b02SDimitry Andric 1283ca95b02SDimitry Andric void dump() const { MI.dump(); } 1293ca95b02SDimitry Andric 1303ca95b02SDimitry Andric bool operator==(const VarLoc &Other) const { 1313ca95b02SDimitry Andric return Var == Other.Var && Loc.Hash == Other.Loc.Hash; 1323ca95b02SDimitry Andric } 1333ca95b02SDimitry Andric 1343ca95b02SDimitry Andric /// This operator guarantees that VarLocs are sorted by Variable first. 1353ca95b02SDimitry Andric bool operator<(const VarLoc &Other) const { 1363ca95b02SDimitry Andric if (Var == Other.Var) 1373ca95b02SDimitry Andric return Loc.Hash < Other.Loc.Hash; 1383ca95b02SDimitry Andric return Var < Other.Var; 1393ca95b02SDimitry Andric } 1407d523365SDimitry Andric }; 1417d523365SDimitry Andric 1423ca95b02SDimitry Andric typedef UniqueVector<VarLoc> VarLocMap; 1433ca95b02SDimitry Andric typedef SparseBitVector<> VarLocSet; 1443ca95b02SDimitry Andric typedef SmallDenseMap<const MachineBasicBlock *, VarLocSet> VarLocInMBB; 1457d523365SDimitry Andric 1463ca95b02SDimitry Andric /// This holds the working set of currently open ranges. For fast 1473ca95b02SDimitry Andric /// access, this is done both as a set of VarLocIDs, and a map of 1483ca95b02SDimitry Andric /// DebugVariable to recent VarLocID. Note that a DBG_VALUE ends all 1493ca95b02SDimitry Andric /// previous open ranges for the same variable. 1503ca95b02SDimitry Andric class OpenRangesSet { 1513ca95b02SDimitry Andric VarLocSet VarLocs; 1523ca95b02SDimitry Andric SmallDenseMap<DebugVariableBase, unsigned, 8> Vars; 1537d523365SDimitry Andric 1543ca95b02SDimitry Andric public: 1553ca95b02SDimitry Andric const VarLocSet &getVarLocs() const { return VarLocs; } 1563ca95b02SDimitry Andric 1573ca95b02SDimitry Andric /// Terminate all open ranges for Var by removing it from the set. 1583ca95b02SDimitry Andric void erase(DebugVariable Var) { 1593ca95b02SDimitry Andric auto It = Vars.find(Var); 1603ca95b02SDimitry Andric if (It != Vars.end()) { 1613ca95b02SDimitry Andric unsigned ID = It->second; 1623ca95b02SDimitry Andric VarLocs.reset(ID); 1633ca95b02SDimitry Andric Vars.erase(It); 1643ca95b02SDimitry Andric } 1653ca95b02SDimitry Andric } 1663ca95b02SDimitry Andric 1673ca95b02SDimitry Andric /// Terminate all open ranges listed in \c KillSet by removing 1683ca95b02SDimitry Andric /// them from the set. 1693ca95b02SDimitry Andric void erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs) { 1703ca95b02SDimitry Andric VarLocs.intersectWithComplement(KillSet); 1713ca95b02SDimitry Andric for (unsigned ID : KillSet) 1723ca95b02SDimitry Andric Vars.erase(VarLocIDs[ID].Var); 1733ca95b02SDimitry Andric } 1743ca95b02SDimitry Andric 1753ca95b02SDimitry Andric /// Insert a new range into the set. 1763ca95b02SDimitry Andric void insert(unsigned VarLocID, DebugVariableBase Var) { 1773ca95b02SDimitry Andric VarLocs.set(VarLocID); 1783ca95b02SDimitry Andric Vars.insert({Var, VarLocID}); 1793ca95b02SDimitry Andric } 1803ca95b02SDimitry Andric 1813ca95b02SDimitry Andric /// Empty the set. 1823ca95b02SDimitry Andric void clear() { 1833ca95b02SDimitry Andric VarLocs.clear(); 1843ca95b02SDimitry Andric Vars.clear(); 1853ca95b02SDimitry Andric } 1863ca95b02SDimitry Andric 1873ca95b02SDimitry Andric /// Return whether the set is empty or not. 1883ca95b02SDimitry Andric bool empty() const { 1893ca95b02SDimitry Andric assert(Vars.empty() == VarLocs.empty() && "open ranges are inconsistent"); 1903ca95b02SDimitry Andric return VarLocs.empty(); 1913ca95b02SDimitry Andric } 1923ca95b02SDimitry Andric }; 1933ca95b02SDimitry Andric 1943ca95b02SDimitry Andric void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges, 1953ca95b02SDimitry Andric VarLocMap &VarLocIDs); 1963ca95b02SDimitry Andric void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges, 1973ca95b02SDimitry Andric const VarLocMap &VarLocIDs); 1983ca95b02SDimitry Andric bool transferTerminatorInst(MachineInstr &MI, OpenRangesSet &OpenRanges, 1993ca95b02SDimitry Andric VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs); 2003ca95b02SDimitry Andric bool transfer(MachineInstr &MI, OpenRangesSet &OpenRanges, 2013ca95b02SDimitry Andric VarLocInMBB &OutLocs, VarLocMap &VarLocIDs); 2023ca95b02SDimitry Andric 2033ca95b02SDimitry Andric bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs, 2043ca95b02SDimitry Andric const VarLocMap &VarLocIDs); 2057d523365SDimitry Andric 2067d523365SDimitry Andric bool ExtendRanges(MachineFunction &MF); 2077d523365SDimitry Andric 2087d523365SDimitry Andric public: 2097d523365SDimitry Andric static char ID; 2107d523365SDimitry Andric 2117d523365SDimitry Andric /// Default construct and initialize the pass. 2127d523365SDimitry Andric LiveDebugValues(); 2137d523365SDimitry Andric 2147d523365SDimitry Andric /// Tell the pass manager which passes we depend on and what 2157d523365SDimitry Andric /// information we preserve. 2167d523365SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 2177d523365SDimitry Andric 2183ca95b02SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 2193ca95b02SDimitry Andric return MachineFunctionProperties().set( 2203ca95b02SDimitry Andric MachineFunctionProperties::Property::AllVRegsAllocated); 2213ca95b02SDimitry Andric } 2223ca95b02SDimitry Andric 2237d523365SDimitry Andric /// Print to ostream with a message. 2243ca95b02SDimitry Andric void printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V, 2253ca95b02SDimitry Andric const VarLocMap &VarLocIDs, const char *msg, 2267d523365SDimitry Andric raw_ostream &Out) const; 2277d523365SDimitry Andric 2287d523365SDimitry Andric /// Calculate the liveness information for the given machine function. 2297d523365SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 2307d523365SDimitry Andric }; 2317d523365SDimitry Andric } // namespace 2327d523365SDimitry Andric 2337d523365SDimitry Andric //===----------------------------------------------------------------------===// 2347d523365SDimitry Andric // Implementation 2357d523365SDimitry Andric //===----------------------------------------------------------------------===// 2367d523365SDimitry Andric 2377d523365SDimitry Andric char LiveDebugValues::ID = 0; 2387d523365SDimitry Andric char &llvm::LiveDebugValuesID = LiveDebugValues::ID; 2397d523365SDimitry Andric INITIALIZE_PASS(LiveDebugValues, "livedebugvalues", "Live DEBUG_VALUE analysis", 2407d523365SDimitry Andric false, false) 2417d523365SDimitry Andric 2427d523365SDimitry Andric /// Default construct and initialize the pass. 2437d523365SDimitry Andric LiveDebugValues::LiveDebugValues() : MachineFunctionPass(ID) { 2447d523365SDimitry Andric initializeLiveDebugValuesPass(*PassRegistry::getPassRegistry()); 2457d523365SDimitry Andric } 2467d523365SDimitry Andric 2477d523365SDimitry Andric /// Tell the pass manager which passes we depend on and what information we 2487d523365SDimitry Andric /// preserve. 2497d523365SDimitry Andric void LiveDebugValues::getAnalysisUsage(AnalysisUsage &AU) const { 2503ca95b02SDimitry Andric AU.setPreservesCFG(); 2517d523365SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 2527d523365SDimitry Andric } 2537d523365SDimitry Andric 2547d523365SDimitry Andric //===----------------------------------------------------------------------===// 2557d523365SDimitry Andric // Debug Range Extension Implementation 2567d523365SDimitry Andric //===----------------------------------------------------------------------===// 2577d523365SDimitry Andric 2583ca95b02SDimitry Andric void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF, 2593ca95b02SDimitry Andric const VarLocInMBB &V, 2603ca95b02SDimitry Andric const VarLocMap &VarLocIDs, 2613ca95b02SDimitry Andric const char *msg, 2627d523365SDimitry Andric raw_ostream &Out) const { 2633ca95b02SDimitry Andric for (const MachineBasicBlock &BB : MF) { 2643ca95b02SDimitry Andric const auto &L = V.lookup(&BB); 2653ca95b02SDimitry Andric Out << "MBB: " << BB.getName() << ":\n"; 2663ca95b02SDimitry Andric for (unsigned VLL : L) { 2673ca95b02SDimitry Andric const VarLoc &VL = VarLocIDs[VLL]; 2683ca95b02SDimitry Andric Out << " Var: " << VL.Var.getVar()->getName(); 2697d523365SDimitry Andric Out << " MI: "; 2703ca95b02SDimitry Andric VL.dump(); 2717d523365SDimitry Andric Out << "\n"; 2727d523365SDimitry Andric } 2737d523365SDimitry Andric } 2747d523365SDimitry Andric Out << "\n"; 2757d523365SDimitry Andric } 2767d523365SDimitry Andric 2777d523365SDimitry Andric /// End all previous ranges related to @MI and start a new range from @MI 2787d523365SDimitry Andric /// if it is a DBG_VALUE instr. 2793ca95b02SDimitry Andric void LiveDebugValues::transferDebugValue(const MachineInstr &MI, 2803ca95b02SDimitry Andric OpenRangesSet &OpenRanges, 2813ca95b02SDimitry Andric VarLocMap &VarLocIDs) { 2827d523365SDimitry Andric if (!MI.isDebugValue()) 2837d523365SDimitry Andric return; 2843ca95b02SDimitry Andric const DILocalVariable *Var = MI.getDebugVariable(); 2853ca95b02SDimitry Andric const DILocation *DebugLoc = MI.getDebugLoc(); 2863ca95b02SDimitry Andric const DILocation *InlinedAt = DebugLoc->getInlinedAt(); 2873ca95b02SDimitry Andric assert(Var->isValidLocationForIntrinsic(DebugLoc) && 2887d523365SDimitry Andric "Expected inlined-at fields to agree"); 2897d523365SDimitry Andric 2907d523365SDimitry Andric // End all previous ranges of Var. 2913ca95b02SDimitry Andric DebugVariable V(Var, InlinedAt); 2923ca95b02SDimitry Andric OpenRanges.erase(V); 2937d523365SDimitry Andric 2943ca95b02SDimitry Andric // Add the VarLoc to OpenRanges from this DBG_VALUE. 2957d523365SDimitry Andric // TODO: Currently handles DBG_VALUE which has only reg as location. 2963ca95b02SDimitry Andric if (isDbgValueDescribedByReg(MI)) { 2973ca95b02SDimitry Andric VarLoc VL(MI); 2983ca95b02SDimitry Andric unsigned ID = VarLocIDs.insert(VL); 2993ca95b02SDimitry Andric OpenRanges.insert(ID, VL.Var); 3007d523365SDimitry Andric } 3017d523365SDimitry Andric } 3027d523365SDimitry Andric 3037d523365SDimitry Andric /// A definition of a register may mark the end of a range. 3047d523365SDimitry Andric void LiveDebugValues::transferRegisterDef(MachineInstr &MI, 3053ca95b02SDimitry Andric OpenRangesSet &OpenRanges, 3063ca95b02SDimitry Andric const VarLocMap &VarLocIDs) { 3073ca95b02SDimitry Andric MachineFunction *MF = MI.getParent()->getParent(); 3083ca95b02SDimitry Andric const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); 3093ca95b02SDimitry Andric unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); 3103ca95b02SDimitry Andric SparseBitVector<> KillSet; 3117d523365SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 3123ca95b02SDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg() && 3133ca95b02SDimitry Andric TRI->isPhysicalRegister(MO.getReg())) { 3147d523365SDimitry Andric // Remove ranges of all aliased registers. 3157d523365SDimitry Andric for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) 3163ca95b02SDimitry Andric for (unsigned ID : OpenRanges.getVarLocs()) 3173ca95b02SDimitry Andric if (VarLocIDs[ID].isDescribedByReg() == *RAI) 3183ca95b02SDimitry Andric KillSet.set(ID); 3193ca95b02SDimitry Andric } else if (MO.isRegMask()) { 3203ca95b02SDimitry Andric // Remove ranges of all clobbered registers. Register masks don't usually 3213ca95b02SDimitry Andric // list SP as preserved. While the debug info may be off for an 3223ca95b02SDimitry Andric // instruction or two around callee-cleanup calls, transferring the 3233ca95b02SDimitry Andric // DEBUG_VALUE across the call is still a better user experience. 3243ca95b02SDimitry Andric for (unsigned ID : OpenRanges.getVarLocs()) { 3253ca95b02SDimitry Andric unsigned Reg = VarLocIDs[ID].isDescribedByReg(); 3263ca95b02SDimitry Andric if (Reg && Reg != SP && MO.clobbersPhysReg(Reg)) 3273ca95b02SDimitry Andric KillSet.set(ID); 3287d523365SDimitry Andric } 3297d523365SDimitry Andric } 3303ca95b02SDimitry Andric } 3313ca95b02SDimitry Andric OpenRanges.erase(KillSet, VarLocIDs); 3323ca95b02SDimitry Andric } 3337d523365SDimitry Andric 3347d523365SDimitry Andric /// Terminate all open ranges at the end of the current basic block. 335444ed5c5SDimitry Andric bool LiveDebugValues::transferTerminatorInst(MachineInstr &MI, 3363ca95b02SDimitry Andric OpenRangesSet &OpenRanges, 3373ca95b02SDimitry Andric VarLocInMBB &OutLocs, 3383ca95b02SDimitry Andric const VarLocMap &VarLocIDs) { 339444ed5c5SDimitry Andric bool Changed = false; 3407d523365SDimitry Andric const MachineBasicBlock *CurMBB = MI.getParent(); 3417d523365SDimitry Andric if (!(MI.isTerminator() || (&MI == &CurMBB->instr_back()))) 342444ed5c5SDimitry Andric return false; 3437d523365SDimitry Andric 3447d523365SDimitry Andric if (OpenRanges.empty()) 345444ed5c5SDimitry Andric return false; 3467d523365SDimitry Andric 3473ca95b02SDimitry Andric DEBUG(for (unsigned ID : OpenRanges.getVarLocs()) { 3487d523365SDimitry Andric // Copy OpenRanges to OutLocs, if not already present. 3493ca95b02SDimitry Andric dbgs() << "Add to OutLocs: "; VarLocIDs[ID].dump(); 3503ca95b02SDimitry Andric }); 3513ca95b02SDimitry Andric VarLocSet &VLS = OutLocs[CurMBB]; 3523ca95b02SDimitry Andric Changed = VLS |= OpenRanges.getVarLocs(); 3537d523365SDimitry Andric OpenRanges.clear(); 354444ed5c5SDimitry Andric return Changed; 3557d523365SDimitry Andric } 3567d523365SDimitry Andric 3577d523365SDimitry Andric /// This routine creates OpenRanges and OutLocs. 3583ca95b02SDimitry Andric bool LiveDebugValues::transfer(MachineInstr &MI, OpenRangesSet &OpenRanges, 3593ca95b02SDimitry Andric VarLocInMBB &OutLocs, VarLocMap &VarLocIDs) { 360444ed5c5SDimitry Andric bool Changed = false; 3613ca95b02SDimitry Andric transferDebugValue(MI, OpenRanges, VarLocIDs); 3623ca95b02SDimitry Andric transferRegisterDef(MI, OpenRanges, VarLocIDs); 3633ca95b02SDimitry Andric Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs); 364444ed5c5SDimitry Andric return Changed; 3657d523365SDimitry Andric } 3667d523365SDimitry Andric 3677d523365SDimitry Andric /// This routine joins the analysis results of all incoming edges in @MBB by 3687d523365SDimitry Andric /// inserting a new DBG_VALUE instruction at the start of the @MBB - if the same 3697d523365SDimitry Andric /// source variable in all the predecessors of @MBB reside in the same location. 370444ed5c5SDimitry Andric bool LiveDebugValues::join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, 3713ca95b02SDimitry Andric VarLocInMBB &InLocs, const VarLocMap &VarLocIDs) { 3727d523365SDimitry Andric DEBUG(dbgs() << "join MBB: " << MBB.getName() << "\n"); 373444ed5c5SDimitry Andric bool Changed = false; 3747d523365SDimitry Andric 3753ca95b02SDimitry Andric VarLocSet InLocsT; // Temporary incoming locations. 3767d523365SDimitry Andric 3773ca95b02SDimitry Andric // For all predecessors of this MBB, find the set of VarLocs that 3783ca95b02SDimitry Andric // can be joined. 3797d523365SDimitry Andric for (auto p : MBB.predecessors()) { 3807d523365SDimitry Andric auto OL = OutLocs.find(p); 3817d523365SDimitry Andric // Join is null in case of empty OutLocs from any of the pred. 3827d523365SDimitry Andric if (OL == OutLocs.end()) 383444ed5c5SDimitry Andric return false; 3847d523365SDimitry Andric 3857d523365SDimitry Andric // Just copy over the Out locs to incoming locs for the first predecessor. 3867d523365SDimitry Andric if (p == *MBB.pred_begin()) { 3877d523365SDimitry Andric InLocsT = OL->second; 3887d523365SDimitry Andric continue; 3897d523365SDimitry Andric } 3907d523365SDimitry Andric // Join with this predecessor. 3913ca95b02SDimitry Andric InLocsT &= OL->second; 3927d523365SDimitry Andric } 3937d523365SDimitry Andric 3947d523365SDimitry Andric if (InLocsT.empty()) 395444ed5c5SDimitry Andric return false; 3967d523365SDimitry Andric 3973ca95b02SDimitry Andric VarLocSet &ILS = InLocs[&MBB]; 3987d523365SDimitry Andric 3997d523365SDimitry Andric // Insert DBG_VALUE instructions, if not already inserted. 4003ca95b02SDimitry Andric VarLocSet Diff = InLocsT; 4013ca95b02SDimitry Andric Diff.intersectWithComplement(ILS); 4023ca95b02SDimitry Andric for (auto ID : Diff) { 4037d523365SDimitry Andric // This VarLoc is not found in InLocs i.e. it is not yet inserted. So, a 4047d523365SDimitry Andric // new range is started for the var from the mbb's beginning by inserting 4057d523365SDimitry Andric // a new DBG_VALUE. transfer() will end this range however appropriate. 4063ca95b02SDimitry Andric const VarLoc &DiffIt = VarLocIDs[ID]; 4073ca95b02SDimitry Andric const MachineInstr *DMI = &DiffIt.MI; 4087d523365SDimitry Andric MachineInstr *MI = 4097d523365SDimitry Andric BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), 4107d523365SDimitry Andric DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), 0, 4117d523365SDimitry Andric DMI->getDebugVariable(), DMI->getDebugExpression()); 4127d523365SDimitry Andric if (DMI->isIndirectDebugValue()) 4137d523365SDimitry Andric MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); 4147d523365SDimitry Andric DEBUG(dbgs() << "Inserted: "; MI->dump();); 4153ca95b02SDimitry Andric ILS.set(ID); 4167d523365SDimitry Andric ++NumInserted; 417444ed5c5SDimitry Andric Changed = true; 4187d523365SDimitry Andric } 419444ed5c5SDimitry Andric return Changed; 4207d523365SDimitry Andric } 4217d523365SDimitry Andric 4227d523365SDimitry Andric /// Calculate the liveness information for the given machine function and 4237d523365SDimitry Andric /// extend ranges across basic blocks. 4247d523365SDimitry Andric bool LiveDebugValues::ExtendRanges(MachineFunction &MF) { 4257d523365SDimitry Andric 4267d523365SDimitry Andric DEBUG(dbgs() << "\nDebug Range Extension\n"); 4277d523365SDimitry Andric 4287d523365SDimitry Andric bool Changed = false; 429444ed5c5SDimitry Andric bool OLChanged = false; 430444ed5c5SDimitry Andric bool MBBJoined = false; 4317d523365SDimitry Andric 4323ca95b02SDimitry Andric VarLocMap VarLocIDs; // Map VarLoc<>unique ID for use in bitvectors. 4333ca95b02SDimitry Andric OpenRangesSet OpenRanges; // Ranges that are open until end of bb. 4347d523365SDimitry Andric VarLocInMBB OutLocs; // Ranges that exist beyond bb. 4357d523365SDimitry Andric VarLocInMBB InLocs; // Ranges that are incoming after joining. 4367d523365SDimitry Andric 437444ed5c5SDimitry Andric DenseMap<unsigned int, MachineBasicBlock *> OrderToBB; 438444ed5c5SDimitry Andric DenseMap<MachineBasicBlock *, unsigned int> BBToOrder; 439444ed5c5SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>, 4403ca95b02SDimitry Andric std::greater<unsigned int>> 4413ca95b02SDimitry Andric Worklist; 442444ed5c5SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>, 4433ca95b02SDimitry Andric std::greater<unsigned int>> 4443ca95b02SDimitry Andric Pending; 4453ca95b02SDimitry Andric 4467d523365SDimitry Andric // Initialize every mbb with OutLocs. 4477d523365SDimitry Andric for (auto &MBB : MF) 4487d523365SDimitry Andric for (auto &MI : MBB) 4493ca95b02SDimitry Andric transfer(MI, OpenRanges, OutLocs, VarLocIDs); 4503ca95b02SDimitry Andric 4513ca95b02SDimitry Andric DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "OutLocs after initialization", 4523ca95b02SDimitry Andric dbgs())); 4537d523365SDimitry Andric 454444ed5c5SDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(&MF); 455444ed5c5SDimitry Andric unsigned int RPONumber = 0; 456444ed5c5SDimitry Andric for (auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) { 457444ed5c5SDimitry Andric OrderToBB[RPONumber] = *RI; 458444ed5c5SDimitry Andric BBToOrder[*RI] = RPONumber; 459444ed5c5SDimitry Andric Worklist.push(RPONumber); 460444ed5c5SDimitry Andric ++RPONumber; 461444ed5c5SDimitry Andric } 462444ed5c5SDimitry Andric // This is a standard "union of predecessor outs" dataflow problem. 463444ed5c5SDimitry Andric // To solve it, we perform join() and transfer() using the two worklist method 464444ed5c5SDimitry Andric // until the ranges converge. 465444ed5c5SDimitry Andric // Ranges have converged when both worklists are empty. 466444ed5c5SDimitry Andric while (!Worklist.empty() || !Pending.empty()) { 467444ed5c5SDimitry Andric // We track what is on the pending worklist to avoid inserting the same 468444ed5c5SDimitry Andric // thing twice. We could avoid this with a custom priority queue, but this 469444ed5c5SDimitry Andric // is probably not worth it. 470444ed5c5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 16> OnPending; 471444ed5c5SDimitry Andric while (!Worklist.empty()) { 472444ed5c5SDimitry Andric MachineBasicBlock *MBB = OrderToBB[Worklist.top()]; 473444ed5c5SDimitry Andric Worklist.pop(); 4743ca95b02SDimitry Andric MBBJoined = join(*MBB, OutLocs, InLocs, VarLocIDs); 4757d523365SDimitry Andric 4767d523365SDimitry Andric if (MBBJoined) { 477444ed5c5SDimitry Andric MBBJoined = false; 4787d523365SDimitry Andric Changed = true; 4797d523365SDimitry Andric for (auto &MI : *MBB) 4803ca95b02SDimitry Andric OLChanged |= transfer(MI, OpenRanges, OutLocs, VarLocIDs); 4813ca95b02SDimitry Andric 4823ca95b02SDimitry Andric DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, 4833ca95b02SDimitry Andric "OutLocs after propagating", dbgs())); 4843ca95b02SDimitry Andric DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, 4853ca95b02SDimitry Andric "InLocs after propagating", dbgs())); 4867d523365SDimitry Andric 4877d523365SDimitry Andric if (OLChanged) { 4887d523365SDimitry Andric OLChanged = false; 4897d523365SDimitry Andric for (auto s : MBB->successors()) 4903ca95b02SDimitry Andric if (OnPending.insert(s).second) { 491444ed5c5SDimitry Andric Pending.push(BBToOrder[s]); 4927d523365SDimitry Andric } 4937d523365SDimitry Andric } 4947d523365SDimitry Andric } 495444ed5c5SDimitry Andric } 496444ed5c5SDimitry Andric Worklist.swap(Pending); 497444ed5c5SDimitry Andric // At this point, pending must be empty, since it was just the empty 498444ed5c5SDimitry Andric // worklist 499444ed5c5SDimitry Andric assert(Pending.empty() && "Pending should be empty"); 500444ed5c5SDimitry Andric } 501444ed5c5SDimitry Andric 5023ca95b02SDimitry Andric DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "Final OutLocs", dbgs())); 5033ca95b02SDimitry Andric DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs, "Final InLocs", dbgs())); 5047d523365SDimitry Andric return Changed; 5057d523365SDimitry Andric } 5067d523365SDimitry Andric 5077d523365SDimitry Andric bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) { 5087d523365SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 5097d523365SDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 5107d523365SDimitry Andric 5117d523365SDimitry Andric bool Changed = false; 5127d523365SDimitry Andric 5137d523365SDimitry Andric Changed |= ExtendRanges(MF); 5147d523365SDimitry Andric 5157d523365SDimitry Andric return Changed; 5167d523365SDimitry Andric } 517