diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -451,24 +451,37 @@ /// Pair of instruction number and operand number. using DebugInstrOperandPair = std::pair; - /// Replacement definition for a debug instruction reference. Made up of an - /// instruction / operand pair, and a qualifying subregister indicating what - /// bits in the operand make up the substitution. For example, a debug user + /// Replacement definition for a debug instruction reference. Made up of a + /// source instruction / operand pair, destination pair, and a qualifying + /// subregister indicating what bits in the operand make up the substitution. + // For example, a debug user /// of %1: - /// %0:gr32 = someinst, debug-instr-number 2 - /// %1:gr16 = %0.some_16_bit_subreg - /// Would receive the substitution {{2, 0}, $subreg}, where $subreg is the - /// subregister number for some_16_bit_subreg. - struct DebugSubstitution { + /// %0:gr32 = someinst, debug-instr-number 1 + /// %1:gr16 = %0.some_16_bit_subreg, debug-instr-number 2 + /// Would receive the substitution {{2, 0}, {1, 0}, $subreg}, where $subreg is + /// the subregister number for some_16_bit_subreg. + class DebugSubstitution { + public: + DebugInstrOperandPair Src; ///< Source instruction / operand pair. DebugInstrOperandPair Dest; ///< Replacement instruction / operand pair. unsigned Subreg; ///< Qualifier for which part of Dest is read. + + DebugSubstitution(const DebugInstrOperandPair &Src, + const DebugInstrOperandPair &Dest, unsigned Subreg) + : Src(Src), Dest(Dest), Subreg(Subreg) {} + + /// Order only by source instruction / operand pair: there should never + /// be duplicate entries for the same source in any collection. + bool operator<(const DebugSubstitution &Other) const { + return Src < Other.Src; + } }; - /// Substitution map: from one pair identifying a value, - /// to a DebugSubstitution identifying another. Used to record changes in - /// where a value is defined, so that debug variable locations can find it - /// later. - std::map DebugValueSubstitutions; + /// Debug value substitutions: a collection of DebugSubstitution objects, + /// recording changes in where a value is defined. For example, when one + /// instruction is substituted for another. Keeping a record allows recovery + /// of variable locations after compilation finishes. + SmallVector DebugValueSubstitutions; /// Location of a PHI instruction that is also a debug-info variable value, /// for the duration of register allocation. Loaded by the PHI-elimination diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1827,16 +1827,22 @@ // Various optimizations may have happened to the value during codegen, // recorded in the value substitution table. Apply any substitutions to - // the instruction / operand number in this DBG_INSTR_REF. - auto Sub = MF.DebugValueSubstitutions.find(std::make_pair(InstNo, OpNo)); - // Collect any subregister extractions performed during optimization. + // the instruction / operand number in this DBG_INSTR_REF, and collect + // any subregister extractions performed during optimization. + + // Create dummy substitution with Src set, for lookup. + auto SoughtSub = + MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0); + SmallVector SeenSubregs; - while (Sub != MF.DebugValueSubstitutions.end()) { - std::tie(InstNo, OpNo) = Sub->second.Dest; - unsigned Subreg = Sub->second.Subreg; - if (Subreg) + auto LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub); + while (LowerBoundIt != MF.DebugValueSubstitutions.end() && + LowerBoundIt->Src == SoughtSub.Src) { + std::tie(InstNo, OpNo) = LowerBoundIt->Dest; + SoughtSub.Src = LowerBoundIt->Dest; + if (unsigned Subreg = LowerBoundIt->Subreg) SeenSubregs.push_back(Subreg); - Sub = MF.DebugValueSubstitutions.find(std::make_pair(InstNo, OpNo)); + LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub); } // Default machine value number is -- if no instruction defines @@ -3542,6 +3548,21 @@ BBNumToRPO[MBB->getNumber()] = RPONumber; ++RPONumber; } + + // Order value substitutions by their "source" operand pair, for quick lookup. + llvm::sort(MF.DebugValueSubstitutions); + +#ifdef EXPENSIVE_CHECKS + // As an expensive check, test whether there are any duplicate substitution + // sources in the collection. + if (MF.DebugValueSubstitutions.size() > 2) { + for (auto It = MF.DebugValueSubstitutions.begin(); + It != std::prev(MF.DebugValueSubstitutions.end()); ++It) { + assert(It->Src != std::next(It)->Src && "Duplicate variable location " + "substitution seen"); + } + } +#endif } /// Calculate the liveness information for the given machine function and diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -225,12 +225,12 @@ convertStackObjects(YamlMF, MF, MST); convertCallSiteObjects(YamlMF, MF, MST); for (const auto &Sub : MF.DebugValueSubstitutions) { - auto &SubSrc = Sub.first; - const MachineFunction::DebugSubstitution &SubDest = Sub.second; + const auto &SubSrc = Sub.Src; + const auto &SubDest = Sub.Dest; YamlMF.DebugValueSubstitutions.push_back({SubSrc.first, SubSrc.second, - SubDest.Dest.first, - SubDest.Dest.second, - SubDest.Subreg}); + SubDest.first, + SubDest.second, + Sub.Subreg}); } if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -973,9 +973,7 @@ unsigned Subreg) { // Catch any accidental self-loops. assert(A.first != B.first); - auto Result = DebugValueSubstitutions.insert({A, {B, Subreg}}); - (void)Result; - assert(Result.second && "Substitution for an already substituted value?"); + DebugValueSubstitutions.push_back({A, B, Subreg}); } void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,