diff --git a/include/llvm/CodeGen/MachineDebugInfo.h b/include/llvm/CodeGen/MachineDebugInfo.h index 39b24640723..7b6386730b7 100644 --- a/include/llvm/CodeGen/MachineDebugInfo.h +++ b/include/llvm/CodeGen/MachineDebugInfo.h @@ -969,8 +969,11 @@ private: // Lines - List of of source line correspondence. std::vector Lines; - // LabelID - Current number assigned to unique label numbers. - unsigned LabelID; + // LabelIDList - One entry per assigned label. Normally the entry is equal to + // the list index(+1). If the entry is zero then the label has been deleted. + // Any other value indicates the label has been deleted by is mapped to + // another label. + std::vector LabelIDList; // ScopeMap - Tracks the scopes in the current function. std::map ScopeMap; @@ -979,10 +982,6 @@ private: // DebugScope *RootScope; - // DeletedLabelIDs - Sorted list of label IDs that have been removed from the - // module. - std::vector DeletedLabelIDs; - // FrameMoves - List of moves done by a function's prolog. Used to construct // frame maps by debug consumers. std::vector FrameMoves; @@ -1026,7 +1025,11 @@ public: /// NextLabelID - Return the next unique label id. /// - unsigned NextLabelID() { return ++LabelID; } + unsigned NextLabelID() { + unsigned ID = LabelIDList.size() + 1; + LabelIDList.push_back(ID); + return ID; + } /// RecordLabel - Records location information and associates it with a /// debug label. Returns a unique label ID used to generate a label and @@ -1035,11 +1038,22 @@ public: /// InvalidateLabel - Inhibit use of the specified label # from /// MachineDebugInfo, for example because the code was deleted. - void InvalidateLabel(unsigned LabelID); + void InvalidateLabel(unsigned LabelID) { + // Remap to zero to indicate deletion. + RemapLabel(LabelID, 0); + } + + /// RemapLabel - Indicate that a label has been merged into another. + /// + void RemapLabel(unsigned OldLabelID, unsigned NewLabelID) { + LabelIDList[OldLabelID - 1] = NewLabelID; + } - /// isLabelValid - Check to make sure the label is still valid before - /// attempting to use. - bool isLabelValid(unsigned LabelID); + /// MappedLabel - Find out the label's final ID. Zero indicates deletion. + /// ID != Mapped ID indicates that the label was folded into another label. + unsigned MappedLabel(unsigned LabelID) const { + return LabelIDList[LabelID - 1]; + } /// RecordSource - Register a source file with debug info. Returns an source /// ID. diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 642039817f3..adccf531eb2 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -81,6 +81,11 @@ namespace llvm { /// branches. FunctionPass *createBranchFoldingPass(); + /// DebugLabelFoldingPass - This pass prunes out redundant debug labels. This + /// allows a debug emitter to determine if the range of two labels is empty, + /// by seeing if the labels map to the same reduced label. + FunctionPass *createDebugLabelFoldingPass(); + /// MachineCodeDeletion Pass - This pass deletes all of the machine code for /// the current function, which should happen after the function has been /// emitted to a .s file or to memory. diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index 81c8963e16d..c8a1333d6c4 100644 --- a/lib/CodeGen/DwarfWriter.cpp +++ b/lib/CodeGen/DwarfWriter.cpp @@ -1695,15 +1695,18 @@ private: return Unit; } + /// GetBaseCompileUnit - Get the main compile unit. + /// + CompileUnit *GetBaseCompileUnit() const { + CompileUnit *Unit = CompileUnits[0]; + assert(Unit && "Missing compile unit."); + return Unit; + } + /// FindCompileUnit - Get the compile unit for the given descriptor. /// CompileUnit *FindCompileUnit(CompileUnitDesc *UnitDesc) { -#if 1 - // FIXME - Using only one compile unit. Needs to me fixed at the FE. - CompileUnit *Unit = CompileUnits[0]; -#else CompileUnit *Unit = DescToUnitMap[UnitDesc]; -#endif assert(Unit && "Missing compile unit."); return Unit; } @@ -1859,13 +1862,12 @@ private: // FIXME - Ignore inlined functions for the time being. if (!Scope->getParent()) continue; - unsigned StartID = Scope->getStartLabelID(); - unsigned EndID = Scope->getEndLabelID(); + unsigned StartID = DebugInfo->MappedLabel(Scope->getStartLabelID()); + unsigned EndID = DebugInfo->MappedLabel(Scope->getEndLabelID()); - // Widen scope if label is discarded. - // FIXME - really need to find a GOOD label if a block is dead. - if (StartID && !DebugInfo->isLabelValid(StartID)) StartID = 0; - if (EndID && !DebugInfo->isLabelValid(EndID)) EndID = 0; + // Ignore empty scopes. + if (StartID == EndID && StartID != 0) continue; + if (Scope->getScopes().empty() && Scope->getVariables().empty()) continue; DIE *ScopeDie = new DIE(DW_TAG_lexical_block); @@ -2084,10 +2086,10 @@ private: std::vector &Moves) { for (unsigned i = 0, N = Moves.size(); i < N; ++i) { MachineMove *Move = Moves[i]; - unsigned LabelID = Move->getLabelID(); + unsigned LabelID = DebugInfo->MappedLabel(Move->getLabelID()); // Throw out move if the label is invalid. - if (LabelID && !DebugInfo->isLabelValid(LabelID)) continue; + if (!LabelID) continue; const MachineLocation &Dst = Move->getDestination(); const MachineLocation &Src = Move->getSource(); @@ -2307,9 +2309,8 @@ private: // Construct rows of the address, source, line, column matrix. for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) { const SourceLineInfo &LineInfo = LineInfos[i]; - unsigned LabelID = LineInfo.getLabelID(); - - // Source line labels are validated at the MachineDebugInfo level. + unsigned LabelID = DebugInfo->MappedLabel(LineInfo.getLabelID()); + if (!LabelID) continue; if (DwarfVerbose) { unsigned SourceID = LineInfo.getSourceID(); @@ -2420,6 +2421,7 @@ private: void EmitFunctionDebugFrame() { if (!TAI->getDwarfRequiresFrameSection()) return; + // Start the dwarf frame section. Asm->SwitchToDataSection(TAI->getDwarfFrameSection()); @@ -2588,7 +2590,8 @@ private: const UniqueVector CUW = DebugInfo->getCompileUnits(); for (unsigned i = 1, N = CUW.size(); i <= N; ++i) { - CompileUnit *Unit = NewCompileUnit(CUW[i], i); + unsigned ID = DebugInfo->RecordSource(CUW[i]); + CompileUnit *Unit = NewCompileUnit(CUW[i], ID); CompileUnits.push_back(Unit); } } diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index b12634ae281..ae13625c205 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -66,6 +66,9 @@ bool LLVMTargetMachine::addPassesToEmitFile(FunctionPassManager &PM, // Branch folding must be run after regalloc and prolog/epilog insertion. if (!Fast) PM.add(createBranchFoldingPass()); + + // Fold redundant debug labels. + PM.add(createDebugLabelFoldingPass()); if (PrintMachineCode) // Print the register-allocated code PM.add(createMachineFunctionPrinterPass(&std::cerr)); diff --git a/lib/CodeGen/MachineDebugInfo.cpp b/lib/CodeGen/MachineDebugInfo.cpp index 490e48d9262..bdbdd144fd7 100644 --- a/lib/CodeGen/MachineDebugInfo.cpp +++ b/lib/CodeGen/MachineDebugInfo.cpp @@ -10,7 +10,11 @@ #include "llvm/CodeGen/MachineDebugInfo.h" #include "llvm/Constants.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" @@ -1448,10 +1452,9 @@ MachineDebugInfo::MachineDebugInfo() , Directories() , SourceFiles() , Lines() -, LabelID(0) +, LabelIDList() , ScopeMap() , RootScope(NULL) -, DeletedLabelIDs() , FrameMoves() {} MachineDebugInfo::~MachineDebugInfo() { @@ -1544,35 +1547,6 @@ unsigned MachineDebugInfo::RecordLabel(unsigned Line, unsigned Column, return ID; } -static bool LabelUIDComparison(const SourceLineInfo &LI, unsigned UID) { - return LI.getLabelID() < UID; -} - -/// InvalidateLabel - Inhibit use of the specified label # from -/// MachineDebugInfo, for example because the code was deleted. -void MachineDebugInfo::InvalidateLabel(unsigned LabelID) { - // Check source line list first. SourceLineInfo is sorted by LabelID. - std::vector::iterator I = - std::lower_bound(Lines.begin(), Lines.end(), LabelID, LabelUIDComparison); - if (I != Lines.end() && I->getLabelID() == LabelID) { - Lines.erase(I); - return; - } - - // Otherwise add for use by isLabelValid. - std::vector::iterator J = - std::lower_bound(DeletedLabelIDs.begin(), DeletedLabelIDs.end(), LabelID); - DeletedLabelIDs.insert(J, LabelID); -} - -/// isLabelValid - Check to make sure the label is still valid before -/// attempting to use. -bool MachineDebugInfo::isLabelValid(unsigned LabelID) { - std::vector::iterator I = - std::lower_bound(DeletedLabelIDs.begin(), DeletedLabelIDs.end(), LabelID); - return I == DeletedLabelIDs.end() || *I != LabelID; -} - /// RecordSource - Register a source file with debug info. Returns an source /// ID. unsigned MachineDebugInfo::RecordSource(const std::string &Directory, @@ -1642,4 +1616,70 @@ DebugScope *MachineDebugInfo::getOrCreateScope(DebugInfoDesc *ScopeDesc) { return Slot; } +//===----------------------------------------------------------------------===// +/// DebugLabelFolding pass - This pass prunes out redundant debug labels. This +/// allows a debug emitter to determine if the range of two labels is empty, +/// by seeing if the labels map to the same reduced label. + +namespace llvm { + +struct DebugLabelFolder : public MachineFunctionPass { + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "Debug Label Folder"; } +}; + +bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) { + // Get machine debug info. + MachineDebugInfo *MDI = getAnalysisToUpdate(); + if (!MDI) return false; + // Get target instruction info. + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + if (!TII) return false; + // Get target version of the debug label opcode. + unsigned DWARF_LABELOpc = TII->getDWARF_LABELOpcode(); + if (!DWARF_LABELOpc) return false; + + // Track if change is made. + bool MadeChange = false; + // No prior label to begin. + unsigned PriorLabel = 0; + + // Iterate through basic blocks. + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); + BB != E; ++BB) { + // Iterate through instructions. + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { + // Is it a debug label. + if ((unsigned)I->getOpcode() == DWARF_LABELOpc) { + // The label ID # is always operand #0, an immediate. + unsigned NextLabel = I->getOperand(0).getImm(); + + // If there was an immediate prior label. + if (PriorLabel) { + // Remap the current label to prior label. + MDI->RemapLabel(NextLabel, PriorLabel); + // Delete the current label. + I = BB->erase(I); + // Indicate a change has been made. + MadeChange = true; + continue; + } else { + // Start a new round. + PriorLabel = NextLabel; + } + } else { + // No consecutive labels. + PriorLabel = 0; + } + + ++I; + } + } + + return MadeChange; +} + +FunctionPass *createDebugLabelFoldingPass() { return new DebugLabelFolder(); } + +}