diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2306,6 +2306,14 @@ Note that these flags should appear after the corresponding profile flags to have an effect. +.. note:: + + When none of the translation units inside a binary is instrumented, in the + case of ELF and COFF binary format the profile runtime will not be linked + into the binary and no profile will be produced, while in the case of Mach-O + the profile runtime will be linked and profile will be produced but there + will not be any counters. + Instrumenting only selected files or functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h --- a/clang/lib/Driver/ToolChains/Fuchsia.h +++ b/clang/lib/Driver/ToolChains/Fuchsia.h @@ -71,9 +71,6 @@ SanitizerMask getSupportedSanitizers() const override; SanitizerMask getDefaultSanitizers() const override; - void addProfileRTLibs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const override; - RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; CXXStdlibType diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -394,13 +394,3 @@ } return Res; } - -void Fuchsia::addProfileRTLibs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { - // Add linker option -u__llvm_profile_runtime to cause runtime - // initialization module to be linked in. - if (needsProfileRT(Args)) - CmdArgs.push_back(Args.MakeArgString( - Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); - ToolChain::addProfileRTLibs(Args, CmdArgs); -} diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h --- a/clang/lib/Driver/ToolChains/Linux.h +++ b/clang/lib/Driver/ToolChains/Linux.h @@ -43,8 +43,6 @@ bool isNoExecStackDefault() const override; bool IsMathErrnoDefault() const override; SanitizerMask getSupportedSanitizers() const override; - void addProfileRTLibs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const override; std::string computeSysRoot() const override; std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -752,16 +752,6 @@ return Res; } -void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { - // Add linker option -u__llvm_profile_runtime to cause runtime - // initialization module to be linked in. - if (needsProfileRT(Args)) - CmdArgs.push_back(Args.MakeArgString( - Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); - ToolChain::addProfileRTLibs(Args, CmdArgs); -} - llvm::DenormalMode Linux::getDefaultDenormalModeForType(const llvm::opt::ArgList &DriverArgs, const JobAction &JA, diff --git a/clang/test/Driver/coverage-ld.c b/clang/test/Driver/coverage-ld.c --- a/clang/test/Driver/coverage-ld.c +++ b/clang/test/Driver/coverage-ld.c @@ -12,9 +12,7 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LINUX-I386 %s // -// CHECK-LINUX-I386-NOT: "-u__llvm_profile_runtime" // CHECK-LINUX-I386: /Inputs/resource_dir{{/|\\\\}}lib{{/|\\\\}}linux{{/|\\\\}}libclang_rt.profile-i386.a" -// CHECK-LINUX-I386-NOT: "-u__llvm_profile_runtime" // CHECK-LINUX-I386: "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ diff --git a/clang/test/Driver/fuchsia.c b/clang/test/Driver/fuchsia.c --- a/clang/test/Driver/fuchsia.c +++ b/clang/test/Driver/fuchsia.c @@ -249,7 +249,6 @@ // RUN: -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-PROFRT-AARCH64 // CHECK-PROFRT-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" -// CHECK-PROFRT-AARCH64: "-u__llvm_profile_runtime" // CHECK-PROFRT-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}libclang_rt.profile.a" // RUN: %clang %s -### --target=x86_64-fuchsia \ @@ -258,5 +257,4 @@ // RUN: -fuse-ld=lld 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-PROFRT-X86_64 // CHECK-PROFRT-X86_64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" -// CHECK-PROFRT-X86_64: "-u__llvm_profile_runtime" // CHECK-PROFRT-X86_64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}libclang_rt.profile.a" diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -543,8 +543,10 @@ UsedVars.clear(); TT = Triple(M.getTargetTriple()); - // Emit the runtime hook even if no counters are present. - bool MadeChange = emitRuntimeHook(); + bool MadeChange = false; + // Emit the runtime hook even if no counters are present in Mach-O. + if (TT.isOSBinFormatMachO()) + MadeChange = emitRuntimeHook(); // Improve compile time by avoiding linear scans when there is no work. GlobalVariable *CoverageNamesVar = @@ -584,6 +586,8 @@ emitVNodes(); emitNameData(); emitRegistration(); + if (!TT.isOSBinFormatMachO()) + emitRuntimeHook(); emitUses(); emitInitialization(); return true; @@ -1058,11 +1062,6 @@ } bool InstrProfiling::emitRuntimeHook() { - // We expect the linker to be invoked with -u flag for Linux or - // Fuchsia, in which case there is no need to emit the user function. - if (TT.isOSLinux() || TT.isOSFuchsia()) - return false; - // If the module's provided its own runtime, we don't need to do anything. if (M->getGlobalVariable(getInstrProfRuntimeHookVarName())) return false; @@ -1073,6 +1072,12 @@ new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, nullptr, getInstrProfRuntimeHookVarName()); + if (TT.isOSBinFormatELF()) { + // Mark the user variable as used so that it isn't stripped out. + CompilerUsedVars.push_back(Var); + return true; + } + // Make a function that uses it. auto *User = Function::Create(FunctionType::get(Int32Ty, false), GlobalValue::LinkOnceODRLinkage, @@ -1088,7 +1093,7 @@ auto *Load = IRB.CreateLoad(Int32Ty, Var); IRB.CreateRet(Load); - // Mark the user variable as used so that it isn't stripped out. + // Mark the function as used so that it isn't stripped out. CompilerUsedVars.push_back(User); return true; } diff --git a/llvm/test/Instrumentation/InstrProfiling/linkage.ll b/llvm/test/Instrumentation/InstrProfiling/linkage.ll --- a/llvm/test/Instrumentation/InstrProfiling/linkage.ll +++ b/llvm/test/Instrumentation/InstrProfiling/linkage.ll @@ -10,7 +10,6 @@ ; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF ; MACHO: @__llvm_profile_runtime = external global i32 -; ELF-NOT: @__llvm_profile_runtime = external global i32 ; ELF: $__profd_foo = comdat noduplicates ; ELF: $__profd_foo_weak = comdat noduplicates diff --git a/llvm/test/Instrumentation/InstrProfiling/profiling.ll b/llvm/test/Instrumentation/InstrProfiling/profiling.ll --- a/llvm/test/Instrumentation/InstrProfiling/profiling.ll +++ b/llvm/test/Instrumentation/InstrProfiling/profiling.ll @@ -1,14 +1,11 @@ ; RUN: opt < %s -mtriple=x86_64 -passes=instrprof -S | FileCheck %s --check-prefixes=CHECK,ELF,ELF_GENERIC ; RUN: opt < %s -mtriple=x86_64-linux -passes=instrprof -S | FileCheck %s --check-prefixes=CHECK,ELF_LINUX ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s --check-prefixes=CHECK,MACHO -; RUN: opt < %s -mtriple=x86_64-windows -passes=instrprof -S | FileCheck %s --check-prefixes=CHECK,WIN +; RUN: opt < %s -mtriple=x86_64-windows -passes=instrprof -S | FileCheck %s --check-prefixes=CHECK,COFF ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s -; ELF_GENERIC: @__llvm_profile_runtime = external global i32 -; ELF_LINUX-NOT: @__llvm_profile_runtime ; MACHO: @__llvm_profile_runtime = external global i32 -; WIN: @__llvm_profile_runtime = external global i32 @__profn_foo = hidden constant [3 x i8] c"foo" ; CHECK-NOT: __profn_foo @@ -21,8 +18,8 @@ ; ELF: @__profd_foo = hidden {{.*}}, section "__llvm_prf_data", comdat, align 8 ; MACHO: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 ; MACHO: @__profd_foo = hidden {{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8 -; WIN: @__profc_foo = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8 -; WIN: @__profd_foo = internal {{.*}}, section ".lprfd$M", align 8 +; COFF: @__profc_foo = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8 +; COFF: @__profd_foo = internal {{.*}}, section ".lprfd$M", align 8 define void @foo() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0) ret void @@ -32,8 +29,8 @@ ; ELF: @__profd_bar = hidden {{.*}}, section "__llvm_prf_data", comdat, align 8 ; MACHO: @__profc_bar = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 ; MACHO: @__profd_bar = hidden {{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8 -; WIN: @__profc_bar = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8 -; WIN: @__profd_bar = internal {{.*}}, section ".lprfd$M", align 8 +; COFF: @__profc_bar = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8 +; COFF: @__profd_bar = internal {{.*}}, section ".lprfd$M", align 8 define void @bar() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__profn_bar, i32 0, i32 0), i64 0, i32 1, i32 0) ret void @@ -43,8 +40,8 @@ ; ELF: @__profd_baz = hidden {{.*}}, section "__llvm_prf_data", comdat, align 8 ; MACHO: @__profc_baz = hidden global [3 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 ; MACHO: @__profd_baz = hidden {{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8 -; WIN: @__profc_baz = internal global [3 x i64] zeroinitializer, section ".lprfc$M", align 8 -; WIN: @__profd_baz = internal {{.*}}, section ".lprfd$M", align 8 +; COFF: @__profc_baz = internal global [3 x i64] zeroinitializer, section ".lprfc$M", align 8 +; COFF: @__profd_baz = internal {{.*}}, section ".lprfd$M", align 8 define void @baz() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_baz, i32 0, i32 0), i64 0, i32 3, i32 0) call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_baz, i32 0, i32 0), i64 0, i32 3, i32 1) @@ -54,9 +51,12 @@ declare void @llvm.instrprof.increment(i8*, i64, i32, i32) -; ELF: @llvm.compiler.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}} @__profd_bar {{.*}} @__profd_baz +; ELF: @__llvm_profile_runtime = external global i32 +; COFF: @__llvm_profile_runtime = external global i32 + +; ELF: @llvm.compiler.used = appending global {{.*}} @__profd_foo {{.*}} @__profd_bar {{.*}} @__profd_baz {{.*}} @__llvm_profile_runtime ; MACHO: @llvm.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}} @__profd_bar {{.*}} @__profd_baz -; WIN: @llvm.used = appending global {{.*}} @__llvm_profile_runtime_user {{.*}} @__profd_foo {{.*}} @__profd_bar {{.*}} @__profd_baz +; COFF: @llvm.used = appending global {{.*}} @__profd_foo {{.*}} @__profd_bar {{.*}} @__profd_baz {{.*}} @__llvm_profile_runtime_user ; ELF_GENERIC: define internal void @__llvm_profile_register_functions() unnamed_addr { ; ELF_GENERIC-NEXT: call void @__llvm_profile_register_function(i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_foo to i8*))