Index: include/llvm/Transforms/InstrProfiling.h =================================================================== --- include/llvm/Transforms/InstrProfiling.h +++ include/llvm/Transforms/InstrProfiling.h @@ -100,23 +100,23 @@ GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc); /// Emit the section with compressed function names. - void emitNameData(); + bool emitNameData(); /// Emit value nodes section for value profiling. - void emitVNodes(); + bool emitVNodes(); /// Emit runtime registration functions for each profile data variable. - void emitRegistration(); + bool emitRegistration(); /// Emit the necessary plumbing to pull in the runtime initialization. - void emitRuntimeHook(); + bool emitRuntimeHook(); /// Add uses of our data variables and runtime hook. - void emitUses(); + bool emitUses(); /// Create a static initializer for our data, on platforms that need it, /// and for any profile output file that was specified. - void emitInitialization(); + bool emitInitialization(); }; } // end namespace llvm Index: lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- lib/Transforms/Instrumentation/InstrProfiling.cpp +++ lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -430,32 +430,8 @@ } } -/// Check if the module contains uses of any profiling intrinsics. -static bool containsProfilingIntrinsics(Module &M) { - if (auto *F = M.getFunction( - Intrinsic::getName(llvm::Intrinsic::instrprof_increment))) - if (!F->use_empty()) - return true; - if (auto *F = M.getFunction( - Intrinsic::getName(llvm::Intrinsic::instrprof_increment_step))) - if (!F->use_empty()) - return true; - if (auto *F = M.getFunction( - Intrinsic::getName(llvm::Intrinsic::instrprof_value_profile))) - if (!F->use_empty()) - return true; - return false; -} - bool InstrProfiling::run(Module &M, const TargetLibraryInfo &TLI) { - // Improve compile time by avoiding linear scans when there is no work. - GlobalVariable *CoverageNamesVar = - M.getNamedGlobal(getCoverageUnusedNamesVarName()); - if (!containsProfilingIntrinsics(M) && !CoverageNamesVar) - return false; - bool MadeChange = false; - this->M = &M; this->TLI = &TLI; NamesVar = nullptr; @@ -487,21 +463,19 @@ for (Function &F : M) MadeChange |= lowerIntrinsics(&F); - if (CoverageNamesVar) { + if (GlobalVariable *CoverageNamesVar = + M.getNamedGlobal(getCoverageUnusedNamesVarName())) { lowerCoverageData(CoverageNamesVar); MadeChange = true; } - if (!MadeChange) - return false; - - emitVNodes(); - emitNameData(); - emitRegistration(); - emitRuntimeHook(); - emitUses(); - emitInitialization(); - return true; + MadeChange |= emitVNodes(); + MadeChange |= emitNameData(); + MadeChange |= emitRegistration(); + MadeChange |= emitRuntimeHook(); + MadeChange |= emitUses(); + MadeChange |= emitInitialization(); + return MadeChange; } static Constant *getOrInsertValueProfilingCall(Module &M, @@ -801,15 +775,15 @@ return CounterPtr; } -void InstrProfiling::emitVNodes() { +bool InstrProfiling::emitVNodes() { if (!ValueProfileStaticAlloc) - return; + return false; // For now only support this on platforms that do // not require runtime registration to discover // named section start/end. if (needsRuntimeRegistrationOfSectionRange(*M)) - return; + return false; size_t TotalNS = 0; for (auto &PD : ProfileDataMap) { @@ -818,7 +792,7 @@ } if (!TotalNS) - return; + return false; uint64_t NumCounters = TotalNS * NumCountersPerValueSite; // Heuristic for small programs with very few total value sites. @@ -846,13 +820,14 @@ VNodesVar->setSection( getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat())); UsedVars.push_back(VNodesVar); + return true; } -void InstrProfiling::emitNameData() { +bool InstrProfiling::emitNameData() { std::string UncompressedData; if (ReferencedNames.empty()) - return; + return false; std::string CompressedNameStr; if (Error E = collectPGOFuncNameStrings(ReferencedNames, CompressedNameStr, @@ -873,11 +848,12 @@ for (auto *NamePtr : ReferencedNames) NamePtr->eraseFromParent(); + return true; } -void InstrProfiling::emitRegistration() { +bool InstrProfiling::emitRegistration() { if (!needsRuntimeRegistrationOfSectionRange(*M)) - return; + return false; // Construct the function. auto *VoidTy = Type::getVoidTy(M->getContext()); @@ -912,17 +888,18 @@ } IRB.CreateRetVoid(); + return true; } -void InstrProfiling::emitRuntimeHook() { +bool InstrProfiling::emitRuntimeHook() { // We expect the linker to be invoked with -u flag for linux, // for which case there is no need to emit the user function. if (Triple(M->getTargetTriple()).isOSLinux()) - return; + return false; // If the module's provided its own runtime, we don't need to do anything. if (M->getGlobalVariable(getInstrProfRuntimeHookVarName())) - return; + return false; // Declare an external variable that will pull in the runtime initialization. auto *Int32Ty = Type::getInt32Ty(M->getContext()); @@ -947,14 +924,19 @@ // Mark the user variable as used so that it isn't stripped out. UsedVars.push_back(User); + return true; } -void InstrProfiling::emitUses() { - if (!UsedVars.empty()) +bool InstrProfiling::emitUses() { + if (!UsedVars.empty()) { appendToUsed(*M, UsedVars); + return true; + } + return false; } -void InstrProfiling::emitInitialization() { +bool InstrProfiling::emitInitialization() { + bool MadeChange = false; StringRef InstrProfileOutput = Options.InstrProfileOutput; if (!InstrProfileOutput.empty()) { @@ -969,11 +951,12 @@ ProfileNameVar->setComdat(M->getOrInsertComdat( StringRef(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR)))); } + MadeChange = true; } Constant *RegisterF = M->getFunction(getInstrProfRegFuncsName()); if (!RegisterF) - return; + return MadeChange; // Create the initialization function. auto *VoidTy = Type::getVoidTy(M->getContext()); @@ -992,4 +975,6 @@ IRB.CreateRetVoid(); appendToGlobalCtors(*M, F, 0); + MadeChange = true; + return MadeChange; } Index: test/Instrumentation/InstrProfiling/early-exit.ll =================================================================== --- test/Instrumentation/InstrProfiling/early-exit.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -instrprof -S | FileCheck %s - -target triple = "x86_64-apple-macosx10.10.0" - -declare void @llvm.instrprof.increment(i8*, i64, i32, i32) - -declare void @llvm.instrprof.increment.step(i8*, i64, i32, i32, i64) - -@__profn_foo = hidden constant [3 x i8] c"foo" - -define void @foo() { -; CHECK: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 - call void @llvm.instrprof.increment.step(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0, i64 0) - ret void -} Index: test/Instrumentation/InstrProfiling/no-counters.ll =================================================================== --- test/Instrumentation/InstrProfiling/no-counters.ll +++ test/Instrumentation/InstrProfiling/no-counters.ll @@ -1,10 +1,10 @@ -;; No instrumentation should be emitted if there are no counter increments. +;; Emit the runtime hook even if there are no counter increments. -; RUN: opt < %s -instrprof -S | FileCheck %s -; RUN: opt < %s -passes=instrprof -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s ; CHECK-NOT: @__profc ; CHECK-NOT: @__profd -; CHECK-NOT: @__llvm_profile_runtime +; CHECK: @__llvm_profile_runtime define void @foo() { ret void