]> granicus.if.org Git - clang/commitdiff
InstrProf: Emit runtime hook directly in IRGen
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 28 Mar 2014 17:53:22 +0000 (17:53 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 28 Mar 2014 17:53:22 +0000 (17:53 +0000)
-u behaviour is apparently not portable between linkers (see cfe-commits
discussions for r204379 and r205012).  I've moved the logic to IRGen,
where it should have been in the first place.

I don't have a Linux system to test this on, so it's possible this logic
*still* doesn't pull in the instrumented profiling runtime on Linux.

I'm in the process of getting tests going on the compiler-rt side
(llvm-commits "[PATCH] InstrProf: Add initial compiler-rt test").  Once
we have tests for the full flow there, the runtime logic should get a
whole lot less brittle.

<rdar://problem/16458307>

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

lib/CodeGen/CodeGenPGO.cpp
lib/Driver/ToolChains.cpp
lib/Driver/Tools.cpp
test/Profile/c-linkage.c
test/Profile/cxx-linkage.cpp

index 7b45650572ad9db8475688235b63f08ddbd13827..ef490ff6799bbd5a0a1d330a5093cbe7330e9f0e 100644 (file)
@@ -814,6 +814,35 @@ namespace {
   };
 }
 
+static void emitRuntimeHook(CodeGenModule &CGM) {
+  constexpr const char *RuntimeVarName = "__llvm_profile_runtime";
+  constexpr const char *RuntimeUserName = "__llvm_profile_runtime_user";
+  if (CGM.getModule().getGlobalVariable(RuntimeVarName))
+    return;
+
+  // Declare the runtime hook.
+  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
+  auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false,
+                                       llvm::GlobalValue::ExternalLinkage,
+                                       nullptr, RuntimeVarName);
+
+  // Make a function that uses it.
+  auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false),
+                                      llvm::GlobalValue::LinkOnceODRLinkage,
+                                      RuntimeUserName, &CGM.getModule());
+  User->addFnAttr(llvm::Attribute::NoInline);
+  if (CGM.getCodeGenOpts().DisableRedZone)
+    User->addFnAttr(llvm::Attribute::NoRedZone);
+  CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User));
+  auto *Load = Builder.CreateLoad(Var);
+  Builder.CreateRet(Load);
+
+  // Create a use of the function.  Now the definition of the runtime variable
+  // should get pulled in, along with any static initializears.
+  CGM.addUsedGlobal(User);
+}
+
 void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
   bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
   PGOProfileData *PGOData = CGM.getPGOData();
@@ -839,8 +868,10 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
   }
 
   mapRegionCounters(D);
-  if (InstrumentRegions)
+  if (InstrumentRegions) {
+    emitRuntimeHook(CGM);
     emitCounterVariables();
+  }
   if (PGOData) {
     loadRegionCounts(PGOData);
     computeRegionCounts(D);
index b348d6c24d60bd383c27cd61f02c33f57a84a137..4bb8332ea7dc57a72690a8aa45a6f3b0536f798a 100644 (file)
@@ -325,13 +325,6 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
       Args.hasArg(options::OPT_fprofile_instr_generate) ||
       Args.hasArg(options::OPT_fcreate_profile) ||
       Args.hasArg(options::OPT_coverage)) {
-    // Pull in runtime for -fprofile-inst-generate.  This is required since
-    // there are no calls to the runtime in the code.
-    if (Args.hasArg(options::OPT_fprofile_instr_generate)) {
-      CmdArgs.push_back("-u");
-      CmdArgs.push_back("___llvm_profile_runtime");
-    }
-
     // Select the appropriate runtime library for the target.
     if (isTargetIOSBased())
       AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
index 2141cc9656bdbf2672ab79afd72c4b88c9809757..9a31eb9f9d6e1482dcabc5639118e0cdbaae5161 100644 (file)
@@ -1817,13 +1817,6 @@ static void addProfileRT(
         Args.hasArg(options::OPT_coverage)))
     return;
 
-  // Pull in runtime for -fprofile-inst-generate.  This is required since there
-  // are no calls to the runtime in the code.
-  if (Args.hasArg(options::OPT_fprofile_instr_generate)) {
-    CmdArgs.push_back("-u");
-    CmdArgs.push_back("___llvm_profile_runtime");
-  }
-
   SmallString<128> LibProfile = getCompilerRTLibDir(TC);
   llvm::sys::path::append(LibProfile,
       Twine("libclang_rt.profile-") + getArchNameForCompilerRTLib(TC) + ".a");
index a688197d494a9dcd58f3137c2695821c2b089b94..72eae1f0f3267cef5ec28e3d1a8651c3e3a0175d 100644 (file)
@@ -1,6 +1,7 @@
 // Check the data structures emitted by instrumentation.
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage.c %s -o - -emit-llvm -fprofile-instr-generate | FileCheck %s
 
+// CHECK: @__llvm_profile_runtime = external global i32
 // CHECK: @__llvm_profile_counters_foo = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
 // CHECK: @__llvm_profile_name_foo = constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1
 // CHECK: @__llvm_profile_data_foo = constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
@@ -28,4 +29,9 @@ int main(void) {
 // CHECK: @__llvm_profile_data_foo_internal = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 3, i8* getelementptr inbounds ([24 x i8]* @__llvm_profile_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_profile_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
 static void foo_internal(void) { if (0){} if (0){} }
 
-// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_internal to i8*)], section "llvm.metadata"
+// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_internal to i8*)], section "llvm.metadata"
+
+// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
+// CHECK:   %[[REG:.*]] = load i32* @__llvm_profile_runtime
+// CHECK:   ret i32 %[[REG]]
+// CHECK: }
index 16f84a68b0243741a713b643a43596bdc0569c4d..44c1983c8498f8952ffe40ea6a45923aad011910 100644 (file)
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -emit-llvm -main-file-name cxx-linkage.cpp %s -o - -fprofile-instr-generate | FileCheck %s
 
+// CHECK: @__llvm_profile_runtime = external global i32
 // CHECK: @__llvm_profile_counters__Z3foov = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
 // CHECK: @__llvm_profile_name__Z3foov = constant [7 x i8] c"_Z3foov", section "__DATA,__llvm_prf_names", align 1
 // CHECK: @__llvm_profile_data__Z3foov = constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 1, i8* getelementptr inbounds ([7 x i8]* @__llvm_profile_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
@@ -27,4 +28,9 @@ int main(void) {
 // CHECK: @__llvm_profile_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 7, i8* getelementptr inbounds ([15 x i8]* @__llvm_profile_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_profile_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
 inline void foo_inline(void) { if (0){} if (0){} if (0){} if (0){} if (0){} if (0){}}
 
-// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"
+// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"
+
+// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
+// CHECK:   %[[REG:.*]] = load i32* @__llvm_profile_runtime
+// CHECK:   ret i32 %[[REG]]
+// CHECK: }