hans created this revision.

This adds two flags:

-fno-cygprofile-exit Don't insert any calls for function exit.
-fno-cygprofile-args Don't pass any arguments to the cygprofile functions (the 
implementer has to figure out the caller address themselves)

These are useful for reducing the size and run-time overhead of the 
instrumentation.


https://reviews.llvm.org/D39331

Files:
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/instrument-functions.c

Index: test/CodeGen/instrument-functions.c
===================================================================
--- test/CodeGen/instrument-functions.c
+++ test/CodeGen/instrument-functions.c
@@ -1,18 +1,27 @@
-// RUN: %clang_cc1 -S -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions | FileCheck %s
+// RUN: %clang_cc1 -S -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions | FileCheck --check-prefix=DEFAULT --check-prefix=CHECK %s
+// RUN: %clang_cc1 -S -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions -fno-cygprofile-exit | FileCheck --check-prefix=NOEXIT --check-prefix=CHECK %s
+// RUN: %clang_cc1 -S -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions -fno-cygprofile-args | FileCheck --check-prefix=NOARGS --check-prefix=CHECK %s
 
-// CHECK: @test1
+// CHECK-LABEL: @test1
 int test1(int x) {
-// CHECK: call void @__cyg_profile_func_enter({{.*}}, !dbg
-// CHECK: call void @__cyg_profile_func_exit({{.*}}, !dbg
-// CHECK: ret
+// DEFAULT: call void @__cyg_profile_func_enter(i8*{{.*}}, i8*{{.*}}){{.*}}, !dbg
+// DEFAULT: call void @__cyg_profile_func_exit(i8*{{.*}}, i8*{{.*}}){{.*}}, !dbg
+
+// NOEXIT: call void @__cyg_profile_func_enter(i8*{{.*}}, i8*{{.*}}){{.*}}, !dbg
+// NOEXIT-NOT: @__cyg_profile_func_exit
+
+// NOARGS: call void @__cyg_profile_func_enter(){{.*}}, !dbg
+// NOARGS: call void @__cyg_profile_func_exit(){{.*}}, !dbg
+
+// CHECK: ret i32 %0
   return x;
 }
 
-// CHECK: @test2
+// CHECK-LABEL: @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
+// CHECK: ret i32 %0
   return x;
 }
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -776,6 +776,8 @@
 
   Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type);
   Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+  Opts.CygProfileExit = !Args.hasArg(OPT_fno_cygprofile_exit);
+  Opts.CygProfileArgs = !Args.hasArg(OPT_fno_cygprofile_args);
   Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
   Opts.XRayInstructionThreshold =
       getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -3553,6 +3553,8 @@
     CmdArgs.push_back("-fno-unique-section-names");
 
   Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+  Args.AddAllArgs(CmdArgs, options::OPT_fno_cygprofile_exit);
+  Args.AddAllArgs(CmdArgs, options::OPT_fno_cygprofile_args);
 
   addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
 
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1773,17 +1773,20 @@
   void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type);
 
   /// ShouldInstrumentFunction - Return true if the current function should be
-  /// instrumented with __cyg_profile_func_* calls
-  bool ShouldInstrumentFunction();
+  /// instrumented with __cyg_profile_func_* calls. If true, sets CygProfileExit
+  /// and CygProfileArgs to indicate whether function exit should be
+  /// instrumented and whether the __cyg_profile calls take arguments,
+  /// respectively.
+  bool ShouldInstrumentFunction(bool *CygProfileExit, bool *CygProfileArgs);
 
   /// ShouldXRayInstrument - Return true if the current function should be
   /// instrumented with XRay nop sleds.
   bool ShouldXRayInstrumentFunction() const;
 
   /// EmitFunctionInstrumentation - Emit LLVM code to call the specified
-  /// instrumentation function with the current function and the call site, if
-  /// function instrumentation is enabled.
-  void EmitFunctionInstrumentation(const char *Fn);
+  /// instrumentation function with the current function and the call site.
+  /// If CygProfileArgs is false, don't pass any arguments to the function.
+  void EmitFunctionInstrumentation(const char *Fn, bool CygProfileArgs);
 
   /// EmitMCountInstrumentation - Emit call to .mcount.
   void EmitMCountInstrumentation();
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -352,8 +352,9 @@
   // Emit function epilog (to return).
   llvm::DebugLoc Loc = EmitReturnBlock();
 
-  if (ShouldInstrumentFunction())
-    EmitFunctionInstrumentation("__cyg_profile_func_exit");
+  bool CygProfileExit, CygProfileArgs;
+  if (ShouldInstrumentFunction(&CygProfileExit, &CygProfileArgs) && CygProfileExit)
+    EmitFunctionInstrumentation("__cyg_profile_func_exit", CygProfileArgs);
 
   // Emit debug descriptor for function end.
   if (CGDebugInfo *DI = getDebugInfo())
@@ -423,11 +424,16 @@
 
 /// ShouldInstrumentFunction - Return true if the current function should be
 /// instrumented with __cyg_profile_func_* calls
-bool CodeGenFunction::ShouldInstrumentFunction() {
+bool CodeGenFunction::ShouldInstrumentFunction(bool *CygProfileExit,
+                                               bool *CygProfileArgs) {
   if (!CGM.getCodeGenOpts().InstrumentFunctions)
     return false;
   if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
     return false;
+
+  *CygProfileExit = CGM.getCodeGenOpts().CygProfileExit;
+  *CygProfileArgs = CGM.getCodeGenOpts().CygProfileArgs;
+
   return true;
 }
 
@@ -477,8 +483,18 @@
 /// EmitFunctionInstrumentation - Emit LLVM code to call the specified
 /// instrumentation function with the current function and the call site, if
 /// function instrumentation is enabled.
-void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) {
+void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn,
+                                                  bool CygProfileArgs) {
   auto NL = ApplyDebugLocation::CreateArtificial(*this);
+
+  if (!CygProfileArgs) {
+    // Call the function without passing any arguments.
+    llvm::FunctionType *FunctionTy = llvm::FunctionType::get(VoidTy, false);
+    llvm::Constant *F = CGM.CreateRuntimeFunction(FunctionTy, Fn);
+    EmitNounwindRuntimeCall(F);
+    return;
+  }
+
   // void __cyg_profile_func_{enter,exit} (void *this_fn, void *call_site);
   llvm::PointerType *PointerTy = Int8PtrTy;
   llvm::Type *ProfileFuncArgs[] = { PointerTy, PointerTy };
@@ -987,8 +1003,9 @@
     DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
   }
 
-  if (ShouldInstrumentFunction())
-    EmitFunctionInstrumentation("__cyg_profile_func_enter");
+  bool CygProfileExit, CygProfileArgs;
+  if (ShouldInstrumentFunction(&CygProfileExit, &CygProfileArgs))
+    EmitFunctionInstrumentation("__cyg_profile_func_enter", CygProfileArgs);
 
   // Since emitting the mcount call here impacts optimizations such as function
   // inlining, we just add an attribute to insert a mcount call in backend.
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -76,7 +76,11 @@
 CODEGENOPT(FunctionSections  , 1, 0) ///< Set when -ffunction-sections is enabled.
 CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
                                        ///< enabled.
-
+CODEGENOPT(CygProfileExit , 1, 1)      ///< Whether to instrument function exits
+                                       ///< when using InstrumentFunctions.
+CODEGENOPT(CygProfileArgs , 1, 1)      ///< Whether to pass arguments to the
+                                       ///< __cyg_profile* functions when using
+                                       ///< InstrumentFunctions.
 CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
                                            ///< enabled.
 
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1025,6 +1025,10 @@
 def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
 def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Generate calls to instrument function entry and exit">;
+def fno_cygprofile_exit : Flag<["-"], "fno-cygprofile-exit">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"When using -finstrument-functions, don't instrument function exit">;
+def fno_cygprofile_args : Flag<["-"], "fno-cygprofile-args">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"When using -finstrument-functions, don't pass any arguments to the __cyg_profile* functions">;
 
 def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>,
   Flags<[CC1Option]>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to