Support using sample profiles with partial debug info.
authorDiego Novillo <dnovillo@google.com>
Wed, 22 Oct 2014 12:59:00 +0000 (12:59 +0000)
committerDiego Novillo <dnovillo@google.com>
Wed, 22 Oct 2014 12:59:00 +0000 (12:59 +0000)
Summary:
When using a profile, we used to require the use -gmlt so that we could
get access to the line locations. This is used to match line numbers in
the input profile to the line numbers in the function's IR.

But this is actually not necessary. The driver can provide source
location tracking without the emission of debug information. In these
cases, the annotation 'llvm.dbg.cu' is missing from the IR, but the
actual line location annotations are still present.

This patch adds a new way of looking for the start of the current
function. Instead of looking through the compile units in llvm.dbg.cu,
we can walk up the scope for the first instruction in the function with
a debug loc. If that describes the function, we use it. Otherwise, we
keep looking until we find one.

If no such instruction is found, we then give up and produce an error.

Reviewers: echristo, dblaikie

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D5887

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220382 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/SampleProfile.cpp
test/Transforms/SampleProfile/calls.ll

index 5c24f1c8dac22acff0c32105dff7c0c07cbd63dc..211e5920ec35d4792e927a8ab3a640c7c02e6825 100644 (file)
@@ -630,6 +630,30 @@ void SampleProfileLoader::propagateWeights(Function &F) {
   }
 }
 
   }
 }
 
+/// \brief Locate the DISubprogram for F.
+///
+/// We look for the first instruction that has a debug annotation
+/// leading back to \p F.
+///
+/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty
+/// DISubprogram.
+static const DISubprogram getDISubprogram(Function &F, const LLVMContext &Ctx) {
+  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
+    BasicBlock *B = I;
+    for (BasicBlock::iterator BI = B->begin(), BE = B->end(); BI != BE; ++BI) {
+      Instruction &Inst = *BI;
+      DebugLoc DLoc = Inst.getDebugLoc();
+      if (DLoc.isUnknown())
+        continue;
+      const MDNode *Scope = DLoc.getScopeNode(Ctx);
+      DISubprogram Subprogram = getDISubprogram(Scope);
+      return Subprogram.describes(&F) ? Subprogram : DISubprogram();
+    }
+  }
+
+  return DISubprogram();
+}
+
 /// \brief Get the line number for the function header.
 ///
 /// This looks up function \p F in the current compilation unit and
 /// \brief Get the line number for the function header.
 ///
 /// This looks up function \p F in the current compilation unit and
@@ -642,19 +666,12 @@ void SampleProfileLoader::propagateWeights(Function &F) {
 /// \returns the line number where \p F is defined. If it returns 0,
 ///          it means that there is no debug information available for \p F.
 unsigned SampleProfileLoader::getFunctionLoc(Function &F) {
 /// \returns the line number where \p F is defined. If it returns 0,
 ///          it means that there is no debug information available for \p F.
 unsigned SampleProfileLoader::getFunctionLoc(Function &F) {
-  NamedMDNode *CUNodes = F.getParent()->getNamedMetadata("llvm.dbg.cu");
-  if (CUNodes) {
-    for (unsigned I = 0, E1 = CUNodes->getNumOperands(); I != E1; ++I) {
-      DICompileUnit CU(CUNodes->getOperand(I));
-      DIArray Subprograms = CU.getSubprograms();
-      for (unsigned J = 0, E2 = Subprograms.getNumElements(); J != E2; ++J) {
-        DISubprogram Subprogram(Subprograms.getElement(J));
-        if (Subprogram.describes(&F))
-          return Subprogram.getLineNumber();
-      }
-    }
-  }
+  const DISubprogram &S = getDISubprogram(F, *Ctx);
+  if (S.isSubprogram())
+    return S.getLineNumber();
 
 
+  // If could not find the start of \p F, emit a diagnostic to inform the user
+  // about the missed opportunity.
   F.getContext().diagnose(DiagnosticInfoSampleProfile(
       "No debug information found in function " + F.getName()));
   return 0;
   F.getContext().diagnose(DiagnosticInfoSampleProfile(
       "No debug information found in function " + F.getName()));
   return 0;
index a80eb95652754935f2b8b07a9c868f5652167baf..c39472bf906365e5bf6cc5bc6a80bac3080ce490 100644 (file)
 ;   printf("sum is %d\n", s);
 ;   return 0;
 ; }
 ;   printf("sum is %d\n", s);
 ;   return 0;
 ; }
-
+;
+; Note that this test is missing the llvm.dbg.cu annotation. This emulates
+; the effect of the user having only used -fprofile-sample-use without
+; -gmlt when invoking the driver. In those cases, we need to track source
+; location information but we do not have to generate debug info in the
+; final binary.
 @.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1
 
 ; Function Attrs: nounwind uwtable
 @.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1
 
 ; Function Attrs: nounwind uwtable
@@ -84,7 +89,6 @@ while.end:                                        ; preds = %while.cond
 
 declare i32 @printf(i8*, ...) #2
 
 
 declare i32 @printf(i8*, ...) #2
 
-!llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!8, !9}
 !llvm.ident = !{!10}
 
 !llvm.module.flags = !{!8, !9}
 !llvm.ident = !{!10}