[llvm-commits] [llvm] r76102 - in /llvm/trunk: include/llvm/CodeGen/MachineCodeEmitter.h include/llvm/ExecutionEngine/JITEventListener.h include/llvm/Support/DebugLoc.h lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp lib/ExecutionEngine/JIT/JITEmitter.cpp lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp lib/Target/X86/X86CodeEmitter.cpp

Jeffrey Yasskin jyasskin at google.com
Thu Jul 16 14:07:28 PDT 2009


Author: jyasskin
Date: Thu Jul 16 16:07:26 2009
New Revision: 76102

URL: http://llvm.org/viewvc/llvm-project?rev=76102&view=rev
Log:
Add line numbers to OProfile. To do this, I added a processDebugLoc()
call to the MachineCodeEmitter interface and made copying the start
line of a function not conditional on whether we're emitting Dwarf
debug information. I'll propagate the processDebugLoc() calls to the
non-X86 targets in a followup patch.

In the long run, it'll probably be better to gather this information
through the DwarfWriter, but the DwarfWriter currently depends on the
AsmPrinter and TargetAsmInfo, and fixing that would be out of the way
for this patch.

There's a bug in OProfile 0.9.4 that makes it ignore line numbers for
addresses above 4G, and a patch fixing it at
http://thread.gmane.org/gmane.linux.oprofile/7634

Sample output:

$ sudo opcontrol --reset; sudo opcontrol --start-daemon; sudo opcontrol --start; `pwd`/Debug/bin/lli fib.bc; sudo opcontrol --stop
Signalling daemon... done
Profiler running.
fib(40) == 165580141
Stopping profiling.

$ opreport -g -d -l `pwd`/Debug/bin/lli|head -60
Overflow stats not available
CPU: Core 2, speed 1998 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
vma      samples  %        linenr info                 image name               symbol name
00007f67a30370b0 25489    61.2554  fib.c:24                    10946.jo                 fib_left
  00007f67a30370b0 1634      6.4106  fib.c:24
  00007f67a30370b1 83        0.3256  fib.c:24
  00007f67a30370b9 1997      7.8348  fib.c:24
  00007f67a30370c6 2080      8.1604  fib.c:27
  00007f67a30370c8 988       3.8762  fib.c:27
  00007f67a30370cd 1315      5.1591  fib.c:27
  00007f67a30370cf 251       0.9847  fib.c:27
  00007f67a30370d3 1191      4.6726  fib.c:27
  00007f67a30370d6 975       3.8252  fib.c:27
  00007f67a30370db 1010      3.9625  fib.c:27
  00007f67a30370dd 242       0.9494  fib.c:27
  00007f67a30370e1 2782     10.9145  fib.c:28
  00007f67a30370e5 3768     14.7828  fib.c:28
  00007f67a30370eb 615       2.4128  (no location information)
  00007f67a30370f3 6558     25.7287  (no location information)
00007f67a3037100 15603    37.4973  fib.c:29                    10946.jo                 fib_right
  00007f67a3037100 1646     10.5493  fib.c:29
  00007f67a3037101 45        0.2884  fib.c:29
  00007f67a3037109 2372     15.2022  fib.c:29
  00007f67a3037116 2234     14.3178  fib.c:32
  00007f67a3037118 612       3.9223  fib.c:32
  00007f67a303711d 622       3.9864  fib.c:32
  00007f67a303711f 385       2.4675  fib.c:32
  00007f67a3037123 404       2.5892  fib.c:32
  00007f67a3037126 634       4.0633  fib.c:32
  00007f67a303712b 870       5.5759  fib.c:32
  00007f67a303712d 62        0.3974  fib.c:32
  00007f67a3037131 1848     11.8439  fib.c:33
  00007f67a3037135 2840     18.2016  fib.c:33
  00007f67a303713a 1         0.0064  fib.c:33
  00007f67a303713b 1023      6.5564  (no location information)
  00007f67a3037143 5         0.0320  (no location information)
000000000080c1e4 15        0.0360  MachineOperand.h:150        lli                      llvm::MachineOperand::isReg() const
  000000000080c1e4 6        40.0000  MachineOperand.h:150
  000000000080c1ec 2        13.3333  MachineOperand.h:150
..


Modified:
    llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h
    llvm/trunk/include/llvm/ExecutionEngine/JITEventListener.h
    llvm/trunk/include/llvm/Support/DebugLoc.h
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
    llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
    llvm/trunk/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
    llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp

Modified: llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h Thu Jul 16 16:07:26 2009
@@ -18,6 +18,7 @@
 #define LLVM_CODEGEN_MACHINECODEEMITTER_H
 
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/DebugLoc.h"
 
 namespace llvm {
 
@@ -232,7 +233,12 @@
       (*(uint64_t*)Addr) = (uint64_t)Value;
   }
   
-  
+  /// processDebugLoc - Records debug location information about a
+  /// MachineInstruction.  This is called before emitting any bytes associated
+  /// with the instruction.  Even if successive instructions have the same debug
+  /// location, this method will be called for each one.
+  virtual void processDebugLoc(DebugLoc DL) {}
+
   /// emitLabel - Emits a label
   virtual void emitLabel(uint64_t LabelID) = 0;
 

Modified: llvm/trunk/include/llvm/ExecutionEngine/JITEventListener.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITEventListener.h?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/JITEventListener.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/JITEventListener.h Thu Jul 16 16:07:26 2009
@@ -16,13 +16,28 @@
 #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H
 
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/DebugLoc.h"
+
+#include <vector>
 
 namespace llvm {
 class Function;
+class MachineFunction;
 
 /// Empty for now, but this object will contain all details about the
 /// generated machine code that a Listener might care about.
 struct JITEvent_EmittedFunctionDetails {
+  const MachineFunction *MF;
+
+  struct LineStart {
+    // The address at which the current line changes.
+    uintptr_t Address;
+    // The new location information.  These can be translated to
+    // DebugLocTuples using MF->getDebugLocTuple().
+    DebugLoc Loc;
+  };
+  // This holds line boundary information sorted by address.
+  std::vector<LineStart> LineStarts;
 };
 
 /// JITEventListener - This interface is used by the JIT to notify clients about

Modified: llvm/trunk/include/llvm/Support/DebugLoc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/DebugLoc.h?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/DebugLoc.h (original)
+++ llvm/trunk/include/llvm/Support/DebugLoc.h Thu Jul 16 16:07:26 2009
@@ -27,6 +27,9 @@
     GlobalVariable *CompileUnit;
     unsigned Line, Col;
 
+    DebugLocTuple()
+      : CompileUnit(0), Line(~0U), Col(~0U) {};
+
     DebugLocTuple(GlobalVariable *v, unsigned l, unsigned c)
       : CompileUnit(v), Line(l), Col(c) {};
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Thu Jul 16 16:07:26 2009
@@ -3918,8 +3918,7 @@
   case Intrinsic::dbg_func_start: {
     DwarfWriter *DW = DAG.getDwarfWriter();
     DbgFuncStartInst &FSI = cast<DbgFuncStartInst>(I);
-    if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None) || !DW
-        || !DW->ShouldEmitDwarfDebug()) 
+    if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None))
       return 0;
 
     MachineFunction &MF = DAG.getMachineFunction();
@@ -3940,6 +3939,8 @@
       // Record the source line.
       setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
       
+      if (!DW || !DW->ShouldEmitDwarfDebug())
+        return 0;
       DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
       DISubprogram SP(cast<GlobalVariable>(FSI.getSubprogram()));
       DICompileUnit CU(PrevLocTpl.CompileUnit);
@@ -3953,7 +3954,9 @@
 
     // This is a beginning of a new function.
     MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
-                    
+
+    if (!DW || !DW->ShouldEmitDwarfDebug())
+      return 0;
     // llvm.dbg.func_start also defines beginning of function scope.
     DW->RecordRegionStart(cast<GlobalVariable>(FSI.getSubprogram()));
     return 0;

Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Thu Jul 16 16:07:26 2009
@@ -473,7 +473,12 @@
     // CurFn - The llvm function being emitted.  Only valid during 
     // finishFunction().
     const Function *CurFn;
-    
+
+    /// Information about emitted code, which is passed to the
+    /// JITEventListeners.  This is reset in startFunction and used in
+    /// finishFunction.
+    JITEvent_EmittedFunctionDetails EmissionDetails;
+
     // CurFnStubUses - For a given Function, a vector of stubs that it
     // references.  This facilitates the JIT detecting that a stub is no
     // longer used, so that it may be deallocated.
@@ -488,6 +493,8 @@
     // in the JITResolver's ExternalFnToStubMap.
     StringMap<void *> ExtFnStubs;
 
+    DebugLocTuple PrevDLT;
+
   public:
     JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit), CurFn(0) {
       MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
@@ -567,6 +574,8 @@
     /// MachineRelocations that reference external functions by name.
     const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; }
     
+    virtual void processDebugLoc(DebugLoc DL);
+
     virtual void emitLabel(uint64_t LabelID) {
       if (LabelLocations.size() <= LabelID)
         LabelLocations.resize((LabelID+1)*2);
@@ -676,6 +685,21 @@
   FnRefs.insert(CurFn);
 }
 
+void JITEmitter::processDebugLoc(DebugLoc DL) {
+  if (!DL.isUnknown()) {
+    DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL);
+
+    if (CurDLT.CompileUnit != 0 && PrevDLT != CurDLT) {
+      JITEvent_EmittedFunctionDetails::LineStart NextLine;
+      NextLine.Address = getCurrentPCValue();
+      NextLine.Loc = DL;
+      EmissionDetails.LineStarts.push_back(NextLine);
+    }
+
+    PrevDLT = CurDLT;
+  }
+}
+
 static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP,
                                            const TargetData *TD) {
   const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
@@ -918,6 +942,9 @@
   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
 
   MBBLocations.clear();
+
+  EmissionDetails.MF = &F;
+  EmissionDetails.LineStarts.clear();
 }
 
 bool JITEmitter::finishFunction(MachineFunction &F) {
@@ -1028,9 +1055,8 @@
   // Invalidate the icache if necessary.
   sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart);
 
-  JITEvent_EmittedFunctionDetails Details;
   TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart,
-                                Details);
+                                EmissionDetails);
 
   DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart
        << "] Function: " << F.getFunction()->getName()

Modified: llvm/trunk/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp Thu Jul 16 16:07:26 2009
@@ -18,6 +18,8 @@
 
 #define DEBUG_TYPE "oprofile-jit-event-listener"
 #include "llvm/Function.h"
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/ExecutionEngine/JITEventListener.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/System/Errno.h"
@@ -64,10 +66,47 @@
   }
 }
 
+class FilenameCache {
+  // Holds the filename of each CompileUnit, so that we can pass the
+  // pointer into oprofile.  These char*s are freed in the destructor.
+  DenseMap<GlobalVariable*, char*> Filenames;
+  // Used as the scratch space in DICompileUnit::getFilename().
+  std::string TempFilename;
+
+ public:
+  const char* getFilename(GlobalVariable *CompileUnit) {
+    char *&Filename = Filenames[CompileUnit];
+    if (Filename == NULL) {
+      DICompileUnit CU(CompileUnit);
+      Filename = strdup(CU.getFilename(TempFilename).c_str());
+    }
+    return Filename;
+  }
+  ~FilenameCache() {
+    for (DenseMap<GlobalVariable*, char*>::iterator
+             I = Filenames.begin(), E = Filenames.end(); I != E;++I) {
+      free(I->second);
+    }
+  }
+};
+
+static debug_line_info LineStartToOProfileFormat(
+    const MachineFunction &MF, FilenameCache &Filenames,
+    uintptr_t Address, DebugLoc Loc) {
+  debug_line_info Result;
+  Result.vma = Address;
+  const DebugLocTuple& tuple = MF.getDebugLocTuple(Loc);
+  Result.lineno = tuple.Line;
+  Result.filename = Filenames.getFilename(tuple.CompileUnit);
+  DOUT << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
+       << Result.filename << ":" << Result.lineno << "\n";
+  return Result;
+}
+
 // Adds the just-emitted function to the symbol table.
 void OProfileJITEventListener::NotifyFunctionEmitted(
     const Function &F, void *FnStart, size_t FnSize,
-    const EmittedFunctionDetails &) {
+    const EmittedFunctionDetails &Details) {
   const char *const FnName = F.getNameStart();
   assert(FnName != 0 && FnStart != 0 && "Bad symbol to add");
   if (op_write_native_code(Agent, FnName,
@@ -75,6 +114,35 @@
                            FnStart, FnSize) == -1) {
     DOUT << "Failed to tell OProfile about native function " << FnName
          << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n";
+    return;
+  }
+
+  // Now we convert the line number information from the address/DebugLoc format
+  // in Details to the address/filename/lineno format that OProfile expects.
+  // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to
+  // ignore line numbers for addresses above 4G.
+  FilenameCache Filenames;
+  std::vector<debug_line_info> LineInfo;
+  LineInfo.reserve(1 + Details.LineStarts.size());
+  if (!Details.MF->getDefaultDebugLoc().isUnknown()) {
+    LineInfo.push_back(LineStartToOProfileFormat(
+        *Details.MF, Filenames,
+        reinterpret_cast<uintptr_t>(FnStart),
+        Details.MF->getDefaultDebugLoc()));
+  }
+  for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
+           I = Details.LineStarts.begin(), E = Details.LineStarts.end();
+       I != E; ++I) {
+    LineInfo.push_back(LineStartToOProfileFormat(
+        *Details.MF, Filenames, I->Address, I->Loc));
+  }
+  if (!LineInfo.empty()) {
+    if (op_write_debug_line_info(Agent, FnStart,
+                                 LineInfo.size(), &*LineInfo.begin()) == -1) {
+      DOUT << "Failed to tell OProfile about line numbers for native function "
+           << FnName << " at [" << FnStart << "-" << ((char*)FnStart + FnSize)
+           << "]\n";
+    }
   }
 }
 

Modified: llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=76102&r1=76101&r2=76102&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp Thu Jul 16 16:07:26 2009
@@ -465,6 +465,8 @@
                               const TargetInstrDesc *Desc) {
   DOUT << MI;
 
+  MCE.processDebugLoc(MI.getDebugLoc());
+
   unsigned Opcode = Desc->Opcode;
 
   // Emit the lock opcode prefix as needed.
@@ -816,4 +818,3 @@
     llvm_unreachable(0);
   }
 }
-





More information about the llvm-commits mailing list