Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -19,6 +19,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunction.h" @@ -43,6 +44,36 @@ namespace { +// \brief 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) { + assert(MI.isDebugValue()); + assert(MI.getNumOperands() == 4); + // If location of variable is described using a register (directly or + // indirecltly), this register is always a first operand. + return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; +} + +// \brief This function takes two DBG_VALUE instructions and returns true +// if their offsets are equal; otherwise returns false. +static bool areOffsetsEqual(const MachineInstr &MI1, const MachineInstr &MI2) { + assert(MI1.isDebugValue()); + assert(MI1.getNumOperands() == 4); + + assert(MI2.isDebugValue()); + assert(MI2.getNumOperands() == 4); + + if (!MI1.isIndirectDebugValue() && !MI2.isIndirectDebugValue()) + return true; + + // Check if both MIs are indirect and they are equal. + if (MI1.isIndirectDebugValue() && MI2.isIndirectDebugValue()) + return MI1.getOperand(1).getImm() == MI2.getOperand(1).getImm(); + + return false; +} + + class LiveDebugValues : public MachineFunctionPass { private: @@ -60,9 +91,19 @@ DebugVariable(const DILocalVariable *_var, const DILocation *_inlinedAt) : Var(_var), InlinedAt(_inlinedAt) {} + bool operator<(const DebugVariable &DV) const { + if (Var == DV.Var) + return InlinedAt < DV.InlinedAt; + return Var < DV.Var; + } + bool operator==(const DebugVariable &DV) const { return (Var == DV.Var) && (InlinedAt == DV.InlinedAt); } + + static unsigned getHashValue(const DebugVariable &DV) { + return hash_combine(DV.Var, DV.InlinedAt); + } }; /// Member variables and functions for Range Extension across basic blocks. @@ -73,10 +114,25 @@ VarLoc(DebugVariable _var, const MachineInstr *_mi) : Var(_var), MI(_mi) {} bool operator==(const VarLoc &V) const; + bool operator<(const VarLoc &V) const { + if (*this == V) + return false; + if (Var == V.Var) + return MI < V.MI; + return Var < V.Var; + } + + static unsigned getHashValue(const VarLoc &V) { + return hash_combine( + V.Var.getHashValue(V.Var), hash_value(V.MI->getOperand(0)), + hash_value(V.MI->getOperand(1)), hash_value(V.MI->getOperand(2)), + hash_value(V.MI->getOperand(3))); + } }; typedef std::list VarLocList; - typedef SmallDenseMap VarLocInMBB; + typedef std::set VarLocSet; + typedef SmallDenseMap VarLocInMBB; void transferDebugValue(MachineInstr &MI, VarLocList &OpenRanges); void transferRegisterDef(MachineInstr &MI, VarLocList &OpenRanges); @@ -104,8 +160,8 @@ } /// Print to ostream with a message. - void printVarLocInMBB(const VarLocInMBB &V, const char *msg, - raw_ostream &Out) const; + void printVarLocInMBB(const MachineFunction &MF, const VarLocInMBB &V, + const char *msg, raw_ostream &Out) const; /// Calculate the liveness information for the given machine function. bool runOnMachineFunction(MachineFunction &MF) override; @@ -132,45 +188,17 @@ MachineFunctionPass::getAnalysisUsage(AU); } -// \brief 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) { - assert(MI.isDebugValue()); - assert(MI.getNumOperands() == 4); - // If location of variable is described using a register (directly or - // indirecltly), this register is always a first operand. - return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; -} - -// \brief This function takes two DBG_VALUE instructions and returns true -// if their offsets are equal; otherwise returns false. -static bool areOffsetsEqual(const MachineInstr &MI1, const MachineInstr &MI2) { - assert(MI1.isDebugValue()); - assert(MI1.getNumOperands() == 4); - - assert(MI2.isDebugValue()); - assert(MI2.getNumOperands() == 4); - - if (!MI1.isIndirectDebugValue() && !MI2.isIndirectDebugValue()) - return true; - - // Check if both MIs are indirect and they are equal. - if (MI1.isIndirectDebugValue() && MI2.isIndirectDebugValue()) - return MI1.getOperand(1).getImm() == MI2.getOperand(1).getImm(); - - return false; -} - //===----------------------------------------------------------------------===// // Debug Range Extension Implementation //===----------------------------------------------------------------------===// -void LiveDebugValues::printVarLocInMBB(const VarLocInMBB &V, const char *msg, +void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF, + const VarLocInMBB &V, const char *msg, raw_ostream &Out) const { - Out << "Printing " << msg << ":\n"; - for (const auto &L : V) { - Out << "MBB: " << L.first->getName() << ":\n"; - for (const auto &VLL : L.second) { + for (const MachineBasicBlock &BB : MF) { + const auto &L = V.lookup(&BB); + Out << "MBB: " << BB.getName() << ":\n"; + for (const auto &VLL : L) { Out << " Var: " << VLL.Var.Var->getName(); Out << " MI: "; (*VLL.MI).dump(); @@ -255,17 +283,14 @@ if (OpenRanges.empty()) return false; - VarLocList &VLL = OutLocs[CurMBB]; + VarLocSet &VLS = OutLocs[CurMBB]; for (auto OR : OpenRanges) { // Copy OpenRanges to OutLocs, if not already present. assert(OR.MI->isDebugValue()); DEBUG(dbgs() << "Add to OutLocs: "; OR.MI->dump();); - if (std::find_if(VLL.begin(), VLL.end(), - [&](const VarLoc &V) { return (OR == V); }) == VLL.end()) { - VLL.push_back(std::move(OR)); - Changed = true; - } + auto result = VLS.insert(std::move(OR)); + Changed |= result.second; } OpenRanges.clear(); return Changed; @@ -289,7 +314,7 @@ DEBUG(dbgs() << "join MBB: " << MBB.getName() << "\n"); bool Changed = false; - VarLocList InLocsT; // Temporary incoming locations. + VarLocSet InLocsT; // Temporary incoming locations. // For all predecessors of this MBB, find the set of VarLocs that can be // joined. @@ -304,44 +329,37 @@ InLocsT = OL->second; continue; } - // Join with this predecessor. - VarLocList &VLL = OL->second; - InLocsT.erase( - std::remove_if(InLocsT.begin(), InLocsT.end(), [&](VarLoc &ILT) { - return (std::find_if(VLL.begin(), VLL.end(), [&](const VarLoc &V) { - return (ILT == V); - }) == VLL.end()); - }), InLocsT.end()); + VarLocSet &VLS = OL->second; + set_intersect(InLocsT, VLS); } if (InLocsT.empty()) return false; - VarLocList &ILL = InLocs[&MBB]; - + VarLocSet &ILS = InLocs[&MBB]; + // Insert DBG_VALUE instructions, if not already inserted. - for (auto ILT : InLocsT) { - if (std::find_if(ILL.begin(), ILL.end(), [&](const VarLoc &I) { - return (ILT == I); - }) == ILL.end()) { - // This VarLoc is not found in InLocs i.e. it is not yet inserted. So, a - // new range is started for the var from the mbb's beginning by inserting - // a new DBG_VALUE. transfer() will end this range however appropriate. - const MachineInstr *DMI = ILT.MI; - MachineInstr *MI = - BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), - DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), 0, - DMI->getDebugVariable(), DMI->getDebugExpression()); - if (DMI->isIndirectDebugValue()) - MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); - DEBUG(dbgs() << "Inserted: "; MI->dump();); - ++NumInserted; - Changed = true; - - VarLoc V(ILT.Var, MI); - ILL.push_back(std::move(V)); - } + VarLocSet Diff; + std::set_difference(InLocsT.begin(), InLocsT.end(), ILS.begin(), ILS.end(), + inserter(Diff, Diff.end())); + for (auto DiffIt : Diff) { + // This VarLoc is not found in InLocs i.e. it is not yet inserted. So, a + // new range is started for the var from the mbb's beginning by + // inserting + // a new DBG_VALUE. transfer() will end this range however appropriate. + const MachineInstr *DMI = DiffIt.MI; + MachineInstr *MI = + BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), + DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), 0, + DMI->getDebugVariable(), DMI->getDebugExpression()); + if (DMI->isIndirectDebugValue()) + MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); + DEBUG(dbgs() << "Inserted: "; MI->dump();); + VarLoc V(DiffIt.Var, MI); + ILS.insert(std::move(V)); + ++NumInserted; + Changed = true; } return Changed; } @@ -370,7 +388,7 @@ for (auto &MBB : MF) for (auto &MI : MBB) transfer(MI, OpenRanges, OutLocs); - DEBUG(printVarLocInMBB(OutLocs, "OutLocs after initialization", dbgs())); + DEBUG(printVarLocInMBB(MF, OutLocs, "OutLocs after initialization", dbgs())); ReversePostOrderTraversal RPOT(&MF); unsigned int RPONumber = 0; @@ -400,8 +418,8 @@ Changed = true; for (auto &MI : *MBB) OLChanged |= transfer(MI, OpenRanges, OutLocs); - DEBUG(printVarLocInMBB(OutLocs, "OutLocs after propagating", dbgs())); - DEBUG(printVarLocInMBB(InLocs, "InLocs after propagating", dbgs())); + DEBUG(printVarLocInMBB(MF, OutLocs, "OutLocs after propagating", dbgs())); + DEBUG(printVarLocInMBB(MF, InLocs, "InLocs after propagating", dbgs())); if (OLChanged) { OLChanged = false; @@ -419,8 +437,8 @@ assert(Pending.empty() && "Pending should be empty"); } - DEBUG(printVarLocInMBB(OutLocs, "Final OutLocs", dbgs())); - DEBUG(printVarLocInMBB(InLocs, "Final InLocs", dbgs())); + DEBUG(printVarLocInMBB(MF, OutLocs, "Final OutLocs", dbgs())); + DEBUG(printVarLocInMBB(MF, InLocs, "Final InLocs", dbgs())); return Changed; } Index: test/DebugInfo/COFF/register-variables.ll =================================================================== --- test/DebugInfo/COFF/register-variables.ll +++ test/DebugInfo/COFF/register-variables.ll @@ -38,10 +38,10 @@ ; ASM: testl %esi, %esi ; ASM: je .LBB0_2 ; ASM: # BB#1: # %if.then -; ASM: #DEBUG_VALUE: c <- %EAX -; ASM: #DEBUG_VALUE: inlineinc:a <- %EAX -; ASM: #DEBUG_VALUE: a <- %EAX -; ASM: #DEBUG_VALUE: f:p <- %ESI +; ASM-DAG: #DEBUG_VALUE: c <- %EAX +; ASM-DAG: #DEBUG_VALUE: inlineinc:a <- %EAX +; ASM-DAG: #DEBUG_VALUE: a <- %EAX +; ASM-DAG: #DEBUG_VALUE: f:p <- %ESI ; ASM: incl %eax ; ASM: [[after_inc_eax:\.Ltmp.*]]: ; ASM: #DEBUG_VALUE: inlineinc:b <- %EAX Index: test/DebugInfo/MIR/X86/live-debug-values-3preds.mir =================================================================== --- test/DebugInfo/MIR/X86/live-debug-values-3preds.mir +++ test/DebugInfo/MIR/X86/live-debug-values-3preds.mir @@ -27,10 +27,10 @@ # DBG_VALUE for variables "x", "y" and "z" are extended into BB#9 from its # predecessors BB#0, BB#2 and BB#8. # CHECK: bb.9.for.end: -# CHECK: DBG_VALUE debug-use %edx, debug-use _, !13, !16, debug-location !20 -# CHECK-NEXT: DBG_VALUE debug-use %esi, debug-use _, !12, !16, debug-location !18 -# CHECK-NEXT: DBG_VALUE debug-use %edi, debug-use _, !11, !16, debug-location !17 - +# CHECK-DAG: DBG_VALUE debug-use %edi, debug-use _, !11, !16, debug-location !17 +# CHECK-DAG: DBG_VALUE debug-use %edx, debug-use _, !13, !16, debug-location !20 +# CHECK-DAG: DBG_VALUE debug-use %esi, debug-use _, !12, !16, debug-location !18 +# CHECK: RET --- | ; ModuleID = 'live-debug-values-3preds.ll'