summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2014-04-30 21:34:11 +0000
committerAlexey Samsonov <samsonov@google.com>2014-04-30 21:34:11 +0000
commitd51ae643686e019b64da3f7a0a3e031e56844d68 (patch)
treeb8e02ff194c798f15592a1083342521e65708265 /lib
parentd96bbedc6acb02f90bbc0d74cb345abfc16f8e9a (diff)
downloadllvm-d51ae643686e019b64da3f7a0a3e031e56844d68.tar.gz
llvm-d51ae643686e019b64da3f7a0a3e031e56844d68.tar.bz2
llvm-d51ae643686e019b64da3f7a0a3e031e56844d68.tar.xz
Move logic for calculating DBG_VALUE history map into separate file/class.
Summary: No functionality change. Test Plan: llvm regression test suite. Reviewers: dblaikie Reviewed By: dblaikie Subscribers: echristo, llvm-commits Differential Revision: http://reviews.llvm.org/D3573 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207708 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp152
-rw-r--r--lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h34
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp137
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h7
5 files changed, 207 insertions, 124 deletions
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index a9afc84e84..b4ef185b0a 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_library(LLVMAsmPrinter
AsmPrinter.cpp
AsmPrinterDwarf.cpp
AsmPrinterInlineAsm.cpp
+ DbgValueHistoryCalculator.cpp
DIE.cpp
DIEHash.cpp
DwarfAccelTable.cpp
diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
new file mode 100644
index 0000000000..cae3e916cd
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
@@ -0,0 +1,152 @@
+//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DbgValueHistoryCalculator.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+
+#define DEBUG_TYPE "dwarfdebug"
+
+namespace llvm {
+
+// Return true if debug value, encoded by DBG_VALUE instruction, is in a
+// defined reg.
+static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
+ assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
+ return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
+ MI->getOperand(0).getReg() &&
+ (MI->getOperand(1).isImm() ||
+ (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
+}
+
+void calculateDbgValueHistory(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ DbgValueHistoryMap &Result) {
+ // LiveUserVar - Map physreg numbers to the MDNode they contain.
+ std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
+
+ for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E;
+ ++I) {
+ bool AtBlockEntry = true;
+ for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
+ II != IE; ++II) {
+ const MachineInstr *MI = II;
+
+ if (MI->isDebugValue()) {
+ assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
+
+ // Keep track of user variables.
+ const MDNode *Var = MI->getDebugVariable();
+
+ // Variable is in a register, we need to check for clobbers.
+ if (isDbgValueInDefinedReg(MI))
+ LiveUserVar[MI->getOperand(0).getReg()] = Var;
+
+ // Check the history of this variable.
+ SmallVectorImpl<const MachineInstr *> &History = Result[Var];
+ if (!History.empty()) {
+ // We have seen this variable before. Try to coalesce DBG_VALUEs.
+ const MachineInstr *Prev = History.back();
+ if (Prev->isDebugValue()) {
+ // Coalesce identical entries at the end of History.
+ if (History.size() >= 2 &&
+ Prev->isIdenticalTo(History[History.size() - 2])) {
+ DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
+ << "\t" << *Prev << "\t"
+ << *History[History.size() - 2] << "\n");
+ History.pop_back();
+ }
+
+ // Terminate old register assignments that don't reach MI;
+ MachineFunction::const_iterator PrevMBB = Prev->getParent();
+ if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) &&
+ isDbgValueInDefinedReg(Prev)) {
+ // Previous register assignment needs to terminate at the end of
+ // its basic block.
+ MachineBasicBlock::const_iterator LastMI =
+ PrevMBB->getLastNonDebugInstr();
+ if (LastMI == PrevMBB->end()) {
+ // Drop DBG_VALUE for empty range.
+ DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
+ << "\t" << *Prev << "\n");
+ History.pop_back();
+ } else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
+ // Terminate after LastMI.
+ History.push_back(LastMI);
+ }
+ }
+ }
+ History.push_back(MI);
+ } else {
+ // Not a DBG_VALUE instruction.
+ if (!MI->isPosition())
+ AtBlockEntry = false;
+
+ // Check if the instruction clobbers any registers with debug vars.
+ for (const MachineOperand &MO : MI->operands()) {
+ if (!MO.isReg() || !MO.isDef() || !MO.getReg())
+ continue;
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
+ ++AI) {
+ unsigned Reg = *AI;
+ const MDNode *Var = LiveUserVar[Reg];
+ if (!Var)
+ continue;
+ // Reg is now clobbered.
+ LiveUserVar[Reg] = nullptr;
+
+ // Was MD last defined by a DBG_VALUE referring to Reg?
+ auto HistI = Result.find(Var);
+ if (HistI == Result.end())
+ continue;
+ SmallVectorImpl<const MachineInstr *> &History = HistI->second;
+ if (History.empty())
+ continue;
+ const MachineInstr *Prev = History.back();
+ // Sanity-check: Register assignments are terminated at the end of
+ // their block.
+ if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
+ continue;
+ // Is the variable still in Reg?
+ if (!isDbgValueInDefinedReg(Prev) ||
+ Prev->getOperand(0).getReg() != Reg)
+ continue;
+ // Var is clobbered. Make sure the next instruction gets a label.
+ History.push_back(MI);
+ }
+ }
+ }
+ }
+ }
+
+ // Make sure the final register assignments are terminated.
+ for (auto &I : Result) {
+ SmallVectorImpl<const MachineInstr *> &History = I.second;
+ if (History.empty())
+ continue;
+
+ const MachineInstr *Prev = History.back();
+ if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
+ const MachineBasicBlock *PrevMBB = Prev->getParent();
+ MachineBasicBlock::const_iterator LastMI =
+ PrevMBB->getLastNonDebugInstr();
+ if (LastMI == PrevMBB->end())
+ // Drop DBG_VALUE for empty range.
+ History.pop_back();
+ else if (PrevMBB != &PrevMBB->getParent()->back()) {
+ // Terminate after LastMI.
+ History.push_back(LastMI);
+ }
+ }
+ }
+}
+
+}
diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
new file mode 100644
index 0000000000..d919522f9b
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
@@ -0,0 +1,34 @@
+//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_
+#define CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class MachineFunction;
+class MachineInstr;
+class MDNode;
+class TargetRegisterInfo;
+
+// For each user variable, keep a list of DBG_VALUE instructions in order.
+// The list can also contain normal instructions that clobber the previous
+// DBG_VALUE.
+typedef DenseMap<const MDNode *, SmallVector<const MachineInstr *, 4>>
+DbgValueHistoryMap;
+
+void calculateDbgValueHistory(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ DbgValueHistoryMap &Result);
+}
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index d9ef6c0428..e0bc4bd723 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1158,16 +1158,6 @@ void DwarfDebug::collectVariableInfoFromMMITable(
}
}
-// Return true if debug value, encoded by DBG_VALUE instruction, is in a
-// defined reg.
-static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
- assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
- return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
- MI->getOperand(0).getReg() &&
- (MI->getOperand(1).isImm() ||
- (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
-}
-
// Get .debug_loc entry for the instruction range starting at MI.
static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
const MDNode *Var = MI->getDebugVariable();
@@ -1449,138 +1439,47 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
- const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
- // LiveUserVar - Map physreg numbers to the MDNode they contain.
- std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
-
+ // Collect user variables, find the end of the prologue.
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E;
++I) {
- bool AtBlockEntry = true;
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MI = II;
-
if (MI->isDebugValue()) {
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
-
- // Keep track of user variables.
+ // Keep track of user variables in order of appearance. Store the set
+ // of variables we've already seen as a set of keys in DbgValues.
const MDNode *Var = MI->getDebugVariable();
-
- // Variable is in a register, we need to check for clobbers.
- if (isDbgValueInDefinedReg(MI))
- LiveUserVar[MI->getOperand(0).getReg()] = Var;
-
- // Check the history of this variable.
- SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
- if (History.empty()) {
+ auto IterPair = DbgValues.insert(
+ std::make_pair(Var, SmallVector<const MachineInstr *, 4>()));
+ if (IterPair.second)
UserVariables.push_back(Var);
- // The first mention of a function argument gets the FunctionBeginSym
- // label, so arguments are visible when breaking at function entry.
- DIVariable DV(Var);
- if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
- getDISubprogram(DV.getContext()).describes(MF->getFunction()))
- LabelsBeforeInsn[MI] = FunctionBeginSym;
- } else {
- // We have seen this variable before. Try to coalesce DBG_VALUEs.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue()) {
- // Coalesce identical entries at the end of History.
- if (History.size() >= 2 &&
- Prev->isIdenticalTo(History[History.size() - 2])) {
- DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
- << "\t" << *Prev << "\t"
- << *History[History.size() - 2] << "\n");
- History.pop_back();
- }
-
- // Terminate old register assignments that don't reach MI;
- MachineFunction::const_iterator PrevMBB = Prev->getParent();
- if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) &&
- isDbgValueInDefinedReg(Prev)) {
- // Previous register assignment needs to terminate at the end of
- // its basic block.
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end()) {
- // Drop DBG_VALUE for empty range.
- DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
- << "\t" << *Prev << "\n");
- History.pop_back();
- } else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- }
- History.push_back(MI);
} else {
- // Not a DBG_VALUE instruction.
- if (!MI->isPosition())
- AtBlockEntry = false;
-
// First known non-DBG_VALUE and non-frame setup location marks
// the beginning of the function body.
if (!MI->getFlag(MachineInstr::FrameSetup) &&
(PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
PrologEndLoc = MI->getDebugLoc();
-
- // Check if the instruction clobbers any registers with debug vars.
- for (const MachineOperand &MO : MI->operands()) {
- if (!MO.isReg() || !MO.isDef() || !MO.getReg())
- continue;
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
- ++AI) {
- unsigned Reg = *AI;
- const MDNode *Var = LiveUserVar[Reg];
- if (!Var)
- continue;
- // Reg is now clobbered.
- LiveUserVar[Reg] = nullptr;
-
- // Was MD last defined by a DBG_VALUE referring to Reg?
- DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
- if (HistI == DbgValues.end())
- continue;
- SmallVectorImpl<const MachineInstr *> &History = HistI->second;
- if (History.empty())
- continue;
- const MachineInstr *Prev = History.back();
- // Sanity-check: Register assignments are terminated at the end of
- // their block.
- if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
- continue;
- // Is the variable still in Reg?
- if (!isDbgValueInDefinedReg(Prev) ||
- Prev->getOperand(0).getReg() != Reg)
- continue;
- // Var is clobbered. Make sure the next instruction gets a label.
- History.push_back(MI);
- }
- }
}
}
}
+ // Calculate history for local variables.
+ calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues);
+
+ // Request labels for the full history.
for (auto &I : DbgValues) {
- SmallVectorImpl<const MachineInstr *> &History = I.second;
+ const SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
- // Make sure the final register assignments are terminated.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
- const MachineBasicBlock *PrevMBB = Prev->getParent();
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end())
- // Drop DBG_VALUE for empty range.
- History.pop_back();
- else if (PrevMBB != &PrevMBB->getParent()->back()) {
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- // Request labels for the full history.
+ // The first mention of a function argument gets the FunctionBeginSym
+ // label, so arguments are visible when breaking at function entry.
+ DIVariable DV(I.first);
+ if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
+ getDISubprogram(DV.getContext()).describes(MF->getFunction()))
+ LabelsBeforeInsn[History.front()] = FunctionBeginSym;
+
for (const MachineInstr *MI : History) {
if (MI->isDebugValue())
requestLabelBeforeInsn(MI);
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 16a314bdb3..e0d7ef4d89 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -17,6 +17,7 @@
#include "DwarfFile.h"
#include "AsmPrinterHandler.h"
#include "DIE.h"
+#include "DbgValueHistoryCalculator.h"
#include "DebugLocEntry.h"
#include "DebugLocList.h"
#include "DwarfAccelTable.h"
@@ -222,11 +223,7 @@ class DwarfDebug : public AsmPrinterHandler {
// appearance.
SmallVector<const MDNode *, 8> UserVariables;
- // For each user variable, keep a list of DBG_VALUE instructions in order.
- // The list can also contain normal instructions that clobber the previous
- // DBG_VALUE.
- typedef DenseMap<const MDNode *, SmallVector<const MachineInstr *, 4> >
- DbgValueHistoryMap;
+ // History of DBG_VALUE and clobber instructions for each user variable.
DbgValueHistoryMap DbgValues;
// Previous instruction's location information. This is used to determine