Index: test/CodeGenCXX/instrument-functions-exclude-path.h
===================================================================
--- test/CodeGenCXX/instrument-functions-exclude-path.h	(revision 0)
+++ test/CodeGenCXX/instrument-functions-exclude-path.h	(revision 0)
@@ -0,0 +1,2 @@
+
+int test1();
Index: test/CodeGenCXX/instrument-functions-exclude-function.cpp
===================================================================
--- test/CodeGenCXX/instrument-functions-exclude-function.cpp	(revision 0)
+++ test/CodeGenCXX/instrument-functions-exclude-function.cpp	(revision 0)
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions -finstrument-functions-exclude-function-list="test4(" | FileCheck %s
+
+// CHECK: @_Z5test1i
+int test1(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @_Z5test2i
+int test2(int) __attribute__((no_instrument_function));
+int test2(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @_Z5test3i
+int test3(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @_Z5test4i
+int test4(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// This test case previously crashed code generation.  It exists solely
+// to test -finstrument-function does not crash codegen for this trivial
+// case.
+namespace rdar9445102 {
+  class Rdar9445102 {
+    public:
+      Rdar9445102();
+  };
+}
+static rdar9445102::Rdar9445102 s_rdar9445102Initializer;
Index: test/CodeGenCXX/instrument-functions-exclude-path.cpp
===================================================================
--- test/CodeGenCXX/instrument-functions-exclude-path.cpp	(revision 0)
+++ test/CodeGenCXX/instrument-functions-exclude-path.cpp	(revision 0)
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions -finstrument-functions-exclude-file-list=exclude-path.h | FileCheck %s
+
+#include "instrument-functions-exclude-path.h"
+
+// CHECK: @_Z5test1i
+int test1(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @_Z5test2i
+int test2(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
Index: test/CodeGen/instrument-functions-exclude-path.c
===================================================================
--- test/CodeGen/instrument-functions-exclude-path.c	(revision 0)
+++ test/CodeGen/instrument-functions-exclude-path.c	(revision 0)
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions -finstrument-functions-exclude-file-list=test3 | FileCheck %s
+
+// CHECK: @test1
+int test1(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @test2
+int test2(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
Index: test/CodeGen/instrument-functions-exclude-path.h
===================================================================
--- test/CodeGen/instrument-functions-exclude-path.h	(revision 0)
+++ test/CodeGen/instrument-functions-exclude-path.h	(revision 0)
@@ -0,0 +1,2 @@
+
+int test1();
Index: test/CodeGen/instrument-functions-exclude-function.c
===================================================================
--- test/CodeGen/instrument-functions-exclude-function.c	(revision 0)
+++ test/CodeGen/instrument-functions-exclude-function.c	(revision 0)
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions -finstrument-functions-exclude-function-list=test3 | FileCheck %s
+
+// CHECK: @test1
+int test1(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @test2
+int test2(int) __attribute__((no_instrument_function));
+int test2(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
+
+// CHECK: @test3
+int test3(int x) {
+// CHECK-NOT: __cyg_profile_func_enter
+// CHECK-NOT: __cyg_profile_func_exit
+// CHECK: ret
+  return x;
+}
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h	(revision 176795)
+++ include/clang/Frontend/CodeGenOptions.h	(working copy)
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <vector>
+#include <set>
 
 namespace clang {
 
@@ -122,6 +123,12 @@
   /// A list of command-line options to forward to the LLVM backend.
   std::vector<std::string> BackendOptions;
 
+  /// Functions to exclude from function instrumentation.
+  std::set<std::string> InstrumentFunctionExclusionsFunctions;
+
+  /// Path segments to exclude from function instrumentation, eg, '/bits'
+  std::set<std::string> InstrumentFunctionExclusionsPathSegments;
+
 public:
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td	(revision 176795)
+++ include/clang/Driver/Options.td	(working copy)
@@ -473,6 +473,12 @@
 def findirect_virtual_calls : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
 def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_f_Group>;
 def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
+def finstrument_functions_exclude_function_list : CommaJoined<["-"],
+  "finstrument-functions-exclude-function-list=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Exclude given (mangled, if C++) functions from function instrumentation.">;
+def finstrument_functions_exclude_file_list : CommaJoined<["-"],
+  "finstrument-functions-exclude-file-list=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Exclude given path segments from function instrumentation.">;
 def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Generate calls to instrument function entry and exit">;
 def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group<clang_ignored_f_Group>;
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp	(revision 176795)
+++ lib/Frontend/CompilerInvocation.cpp	(working copy)
@@ -403,6 +403,19 @@
   }
 
   Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+  if (Opts.InstrumentFunctions) {
+    std::vector<std::string> TempVector;
+    TempVector =
+      Args.getAllArgValues(OPT_finstrument_functions_exclude_function_list);
+    Opts.InstrumentFunctionExclusionsFunctions =
+      std::set<std::string>(TempVector.begin(), TempVector.end());
+
+    TempVector =
+      Args.getAllArgValues(OPT_finstrument_functions_exclude_file_list);
+    Opts.InstrumentFunctionExclusionsPathSegments =
+      std::set<std::string>(TempVector.begin(), TempVector.end());
+  }
+
   Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
   Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
   Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 176795)
+++ lib/Driver/Tools.cpp	(working copy)
@@ -2319,6 +2319,12 @@
   Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
 
   Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+  if (Args.hasArg(options::OPT_finstrument_functions)) {
+    Args.AddAllArgs(CmdArgs,
+                    options::OPT_finstrument_functions_exclude_file_list);
+    Args.AddAllArgs(CmdArgs,
+                    options::OPT_finstrument_functions_exclude_function_list);
+  }
 
   if (Args.hasArg(options::OPT_ftest_coverage) ||
       Args.hasArg(options::OPT_coverage))
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp	(revision 176795)
+++ lib/CodeGen/CodeGenFunction.cpp	(working copy)
@@ -195,7 +195,7 @@
   // Emit function epilog (to return).
   EmitReturnBlock();
 
-  if (ShouldInstrumentFunction())
+  if (ShouldInstrumentFunction(CurFn))
     EmitFunctionInstrumentation("__cyg_profile_func_exit");
 
   // Emit debug descriptor for function end.
@@ -240,13 +240,93 @@
     EmitDeclMetadata();
 }
 
+/// Offers comparison logic for std::find_if for finding a needle in a
+/// container of haystacks.
+class CheckForSubstringInString {
+  public:
+    CheckForSubstringInString(const std::string &StringForCheck) :
+      Check(StringForCheck)
+    {
+    }
+
+    bool operator() (const std::string &Substring) {
+      return Check.find(Substring) != std::string::npos;
+    }
+
+  private:
+    const std::string &Check;
+};
+
+#if !defined(_MSC_VER)
+// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
+extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
+                                size_t *length, int *status);
+#endif
+
 /// ShouldInstrumentFunction - Return true if the current function should be
 /// instrumented with __cyg_profile_func_* calls
-bool CodeGenFunction::ShouldInstrumentFunction() {
+bool CodeGenFunction::ShouldInstrumentFunction(llvm::Function *Fn) {
   if (!CGM.getCodeGenOpts().InstrumentFunctions)
     return false;
   if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
     return false;
+
+  // Inline functions that are not externally visible mustn't be instrumented.
+  // They create a named reference to the inlined function, as the first
+  // parameter to __cyg_profile_* functions, which a linker will never be able
+  // to resolve.
+  if (const FunctionDecl *ActualFuncDecl =
+        dyn_cast<FunctionDecl>(CurFuncDecl)) {
+    if (ActualFuncDecl->isInlined() &&
+        !ActualFuncDecl->isInlineDefinitionExternallyVisible())
+      return false;
+  }
+
+  SourceLocation SLoc = CurFuncDecl->getLocation();
+  std::set<std::string>::const_iterator Iterator;
+
+  if (SLoc.isFileID()) {
+    ASTContext &ctx = CurFuncDecl->getASTContext();
+    const SourceManager &SM = ctx.getSourceManager();
+
+    PresumedLoc PLoc = SM.getPresumedLoc(SLoc);
+    std::string FunctionDeclPath = PLoc.getFilename();
+
+    // Unsure of an 'optimal' way to do this - we have (potentially) many
+    // haystacks but only one needle here - maybe this shouldn't be a set
+    // and should just be string with the full, comma separated, value?
+    const std::set<std::string> &PathSearch =
+      CGM.getCodeGenOpts().InstrumentFunctionExclusionsPathSegments;
+    Iterator = std::find_if(PathSearch.begin(), PathSearch.end(),
+                            CheckForSubstringInString(FunctionDeclPath));
+    if (Iterator != PathSearch.end()) {
+      return false;
+    }
+  }
+
+  // We need to demangle the name if it's mangled, but we also need to handle
+  // unmangled names. And Windows doesn't have libcxxabi. Yay!
+  std::string FunctionName = Fn->getName();
+#if !defined(_MSC_VER)
+  int status = 0;
+  char *result = __cxa_demangle(Fn->getName().str().c_str(), 0, 0, &status);
+
+  assert((status == 0 || status == -2) && "Couldn't demangle name.");
+
+  if (status == 0) {
+    FunctionName = result;
+    free(result);
+  }
+#endif
+
+  const std::set<std::string> &FunctionSearch =
+    CGM.getCodeGenOpts().InstrumentFunctionExclusionsFunctions;
+  Iterator = std::find_if(FunctionSearch.begin(), FunctionSearch.end(),
+                          CheckForSubstringInString(FunctionName));
+  if (Iterator != FunctionSearch.end()) {
+    return false;
+  }
+
   return true;
 }
 
@@ -434,7 +514,7 @@
     DI->EmitFunctionStart(GD, FnType, CurFn, Builder);
   }
 
-  if (ShouldInstrumentFunction())
+  if (ShouldInstrumentFunction(CurFn))
     EmitFunctionInstrumentation("__cyg_profile_func_enter");
 
   if (CGM.getCodeGenOpts().InstrumentForProfiling)
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h	(revision 176795)
+++ lib/CodeGen/CodeGenFunction.h	(working copy)
@@ -1479,7 +1479,7 @@
 
   /// ShouldInstrumentFunction - Return true if the current function should be
   /// instrumented with __cyg_profile_func_* calls
-  bool ShouldInstrumentFunction();
+  bool ShouldInstrumentFunction(llvm::Function *Fn);
 
   /// EmitFunctionInstrumentation - Emit LLVM code to call the specified
   /// instrumentation function with the current function and the call site, if
