Index: lib/Transforms/Scalar/SampleProfile.cpp =================================================================== --- lib/Transforms/Scalar/SampleProfile.cpp +++ lib/Transforms/Scalar/SampleProfile.cpp @@ -630,6 +630,30 @@ } } +/// \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()) { + 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 @@ -642,21 +666,16 @@ /// \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 warn the user + // about the missed opportunity. F.getContext().diagnose(DiagnosticInfoSampleProfile( - "No debug information found in function " + F.getName())); + "No debug information found in function " + F.getName() + + ": Function profile not used", + DS_Warning)); return 0; } Index: test/Transforms/SampleProfile/calls.ll =================================================================== --- test/Transforms/SampleProfile/calls.ll +++ test/Transforms/SampleProfile/calls.ll @@ -15,7 +15,12 @@ ; 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 @@ -84,7 +89,6 @@ declare i32 @printf(i8*, ...) #2 -!llvm.dbg.cu = !{!0} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} Index: test/Transforms/SampleProfile/syntax.ll =================================================================== --- test/Transforms/SampleProfile/syntax.ll +++ test/Transforms/SampleProfile/syntax.ll @@ -1,4 +1,4 @@ -; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/syntax.prof 2>&1 | FileCheck -check-prefix=NO-DEBUG %s +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/syntax.prof 2>&1 | FileCheck -check-prefix=NO-DEBUG %s ; RUN: not opt < %s -sample-profile -sample-profile-file=missing.prof 2>&1 | FileCheck -check-prefix=MISSING-FILE %s ; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/bad_fn_header.prof 2>&1 | FileCheck -check-prefix=BAD-FN-HEADER %s ; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/bad_sample_line.prof 2>&1 | FileCheck -check-prefix=BAD-SAMPLE-LINE %s @@ -11,7 +11,7 @@ entry: ret void } -; NO-DEBUG: error: No debug information found in function empty +; NO-DEBUG: warning: No debug information found in function empty: Function profile not used ; MISSING-FILE: error: missing.prof: ; BAD-FN-HEADER: error: {{.*}}bad_fn_header.prof:1: Expected 'mangled_name:NUM:NUM', found 3empty:100:BAD ; BAD-SAMPLE-LINE: error: {{.*}}bad_sample_line.prof:3: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1: BAD