Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -124,7 +124,7 @@ void initializeGCOVProfilerPass(PassRegistry&); void initializePGOInstrumentationGenPass(PassRegistry&); void initializePGOInstrumentationUsePass(PassRegistry&); -void initializeInstrProfilingPass(PassRegistry&); +void initializeInstrProfilingLegacyPassPass(PassRegistry &); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); Index: include/llvm/Transforms/InstrProfiling.h =================================================================== --- include/llvm/Transforms/InstrProfiling.h +++ include/llvm/Transforms/InstrProfiling.h @@ -0,0 +1,102 @@ +//===- Transforms/InstrProfiling.h - Instrumentation passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides the interface for LLVM's PGO Instrumentation lowering +/// pass. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRPROFILING_H +#define LLVM_TRANSFORMS_INSTRPROFILING_H + +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/PassManager.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Transforms/Instrumentation.h" + +namespace llvm { + +/// Instrumenation based profiling lowering pass. This pass lowers +/// the profile instrumented code generated by FE or the IR based +/// instrumentation pass. +struct InstrProfiling : PassInfoMixin { +public: + InstrProfiling() {} + InstrProfiling(const InstrProfOptions &Options) : Options(Options) {} + + PreservedAnalyses run(Module &M, AnalysisManager &AM); + bool run(Module &M); + +private: + InstrProfOptions Options; + Module *M; + typedef struct PerFunctionProfileData { + uint32_t NumValueSites[IPVK_Last + 1]; + GlobalVariable *RegionCounters; + GlobalVariable *DataVar; + PerFunctionProfileData() : RegionCounters(nullptr), DataVar(nullptr) { + memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last + 1)); + } + } PerFunctionProfileData; + DenseMap ProfileDataMap; + std::vector UsedVars; + std::vector ReferencedNames; + GlobalVariable *NamesVar; + size_t NamesSize; + + bool isMachO() const; + + /// Get the section name for the counter variables. + StringRef getCountersSection() const; + + /// Get the section name for the name variables. + StringRef getNameSection() const; + + /// Get the section name for the profile data variables. + StringRef getDataSection() const; + + /// Get the section name for the coverage mapping data. + StringRef getCoverageSection() const; + + /// Count the number of instrumented value sites for the function. + void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins); + + /// Replace instrprof_value_profile with a call to runtime library. + void lowerValueProfileInst(InstrProfValueProfileInst *Ins); + + /// Replace instrprof_increment with an increment of the appropriate value. + void lowerIncrement(InstrProfIncrementInst *Inc); + + /// Force emitting of name vars for unused functions. + void lowerCoverageData(GlobalVariable *CoverageNamesVar); + + /// Get the region counters for an increment, creating them if necessary. + /// + /// If the counter array doesn't yet exist, the profile data variables + /// referring to them will also be created. + GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc); + + /// Emit the section with compressed function names. + void emitNameData(); + + /// Emit runtime registration functions for each profile data variable. + void emitRegistration(); + + /// Emit the necessary plumbing to pull in the runtime initialization. + void emitRuntimeHook(); + + /// Add uses of our data variables and runtime hook. + void emitUses(); + + /// Create a static initializer for our data, on platforms that need it, + /// and for any profile output file that was specified. + void emitInitialization(); +}; + +} // End llvm namespace +#endif Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" #include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/InstrProfiling.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -37,6 +37,7 @@ #endif MODULE_PASS("forceattrs", ForceFunctionAttrsPass()) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) +MODULE_PASS("instrprof", InstrProfiling()) MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) MODULE_PASS("no-op-module", NoOpModulePass()) MODULE_PASS("print", PrintModulePass(dbgs())) Index: lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- lib/Transforms/Instrumentation/InstrProfiling.cpp +++ lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -18,7 +18,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/ProfileData/InstrProf.h" -#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/InstrProfiling.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; @@ -31,113 +31,68 @@ cl::desc("Enable name string compression"), cl::init(true)); -class InstrProfiling : public ModulePass { +class InstrProfilingLegacyPass : public ModulePass { + InstrProfiling InstrProf; + public: static char ID; - - InstrProfiling() : ModulePass(ID) {} - - InstrProfiling(const InstrProfOptions &Options) - : ModulePass(ID), Options(Options) {} - + InstrProfilingLegacyPass() : ModulePass(ID), InstrProf() {} + InstrProfilingLegacyPass(const InstrProfOptions &Options) + : ModulePass(ID), InstrProf(Options) {} const char *getPassName() const override { return "Frontend instrumentation-based coverage lowering"; } - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override { return InstrProf.run(M); } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); } +}; -private: - InstrProfOptions Options; - Module *M; - typedef struct PerFunctionProfileData { - uint32_t NumValueSites[IPVK_Last+1]; - GlobalVariable* RegionCounters; - GlobalVariable* DataVar; - PerFunctionProfileData() : RegionCounters(nullptr), DataVar(nullptr) { - memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last+1)); - } - } PerFunctionProfileData; - DenseMap ProfileDataMap; - std::vector UsedVars; - std::vector ReferencedNames; - GlobalVariable *NamesVar; - size_t NamesSize; - - bool isMachO() const { - return Triple(M->getTargetTriple()).isOSBinFormatMachO(); - } - - /// Get the section name for the counter variables. - StringRef getCountersSection() const { - return getInstrProfCountersSectionName(isMachO()); - } - - /// Get the section name for the name variables. - StringRef getNameSection() const { - return getInstrProfNameSectionName(isMachO()); - } - - /// Get the section name for the profile data variables. - StringRef getDataSection() const { - return getInstrProfDataSectionName(isMachO()); - } - - /// Get the section name for the coverage mapping data. - StringRef getCoverageSection() const { - return getInstrProfCoverageSectionName(isMachO()); - } - - /// Count the number of instrumented value sites for the function. - void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins); - - /// Replace instrprof_value_profile with a call to runtime library. - void lowerValueProfileInst(InstrProfValueProfileInst *Ins); - - /// Replace instrprof_increment with an increment of the appropriate value. - void lowerIncrement(InstrProfIncrementInst *Inc); - - /// Force emitting of name vars for unused functions. - void lowerCoverageData(GlobalVariable *CoverageNamesVar); +} // anonymous namespace - /// Get the region counters for an increment, creating them if necessary. - /// - /// If the counter array doesn't yet exist, the profile data variables - /// referring to them will also be created. - GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc); +PreservedAnalyses InstrProfiling::run(Module &M, AnalysisManager &AM) { + if (!run(M)) + return PreservedAnalyses::all(); - /// Emit the section with compressed function names. - void emitNameData(); + return PreservedAnalyses::none(); +} - /// Emit runtime registration functions for each profile data variable. - void emitRegistration(); +char InstrProfilingLegacyPass::ID = 0; +INITIALIZE_PASS(InstrProfilingLegacyPass, "instrprof", + "Frontend instrumentation-based coverage lowering.", false, + false) - /// Emit the necessary plumbing to pull in the runtime initialization. - void emitRuntimeHook(); +ModulePass *llvm::createInstrProfilingPass(const InstrProfOptions &Options) { + return new InstrProfilingLegacyPass(Options); +} - /// Add uses of our data variables and runtime hook. - void emitUses(); +bool InstrProfiling::isMachO() const { + return Triple(M->getTargetTriple()).isOSBinFormatMachO(); +} - /// Create a static initializer for our data, on platforms that need it, - /// and for any profile output file that was specified. - void emitInitialization(); -}; +/// Get the section name for the counter variables. +StringRef InstrProfiling::getCountersSection() const { + return getInstrProfCountersSectionName(isMachO()); +} -} // anonymous namespace +/// Get the section name for the name variables. +StringRef InstrProfiling::getNameSection() const { + return getInstrProfNameSectionName(isMachO()); +} -char InstrProfiling::ID = 0; -INITIALIZE_PASS(InstrProfiling, "instrprof", - "Frontend instrumentation-based coverage lowering.", false, - false) +/// Get the section name for the profile data variables. +StringRef InstrProfiling::getDataSection() const { + return getInstrProfDataSectionName(isMachO()); +} -ModulePass *llvm::createInstrProfilingPass(const InstrProfOptions &Options) { - return new InstrProfiling(Options); +/// Get the section name for the coverage mapping data. +StringRef InstrProfiling::getCoverageSection() const { + return getInstrProfCoverageSectionName(isMachO()); } -bool InstrProfiling::runOnModule(Module &M) { +bool InstrProfiling::run(Module &M) { bool MadeChange = false; this->M = &M; Index: lib/Transforms/Instrumentation/Instrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/Instrumentation.cpp +++ lib/Transforms/Instrumentation/Instrumentation.cpp @@ -62,7 +62,7 @@ initializeGCOVProfilerPass(Registry); initializePGOInstrumentationGenPass(Registry); initializePGOInstrumentationUsePass(Registry); - initializeInstrProfilingPass(Registry); + initializeInstrProfilingLegacyPassPass(Registry); initializeMemorySanitizerPass(Registry); initializeThreadSanitizerPass(Registry); initializeSanitizerCoverageModulePass(Registry); Index: test/Instrumentation/InstrProfiling/PR23499.ll =================================================================== --- test/Instrumentation/InstrProfiling/PR23499.ll +++ test/Instrumentation/InstrProfiling/PR23499.ll @@ -4,6 +4,7 @@ ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s ; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s ; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -instrprof -S | FileCheck %s --check-prefix=COFF $_Z3barIvEvv = comdat any Index: test/Instrumentation/InstrProfiling/linkage.ll =================================================================== --- test/Instrumentation/InstrProfiling/linkage.ll +++ test/Instrumentation/InstrProfiling/linkage.ll @@ -2,6 +2,8 @@ ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s --check-prefix=OTHER --check-prefix=COMMON ; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s --check-prefix=LINUX --check-prefix=COMMON +; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s --check-prefix=OTHER --check-prefix=COMMON +; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s --check-prefix=LINUX --check-prefix=COMMON @__profn_foo = hidden constant [3 x i8] c"foo" @__profn_foo_weak = weak hidden constant [8 x i8] c"foo_weak" Index: test/Instrumentation/InstrProfiling/no-counters.ll =================================================================== --- test/Instrumentation/InstrProfiling/no-counters.ll +++ test/Instrumentation/InstrProfiling/no-counters.ll @@ -1,6 +1,7 @@ ;; No instrumentation should be emitted if there are no counter increments. ; RUN: opt < %s -instrprof -S | FileCheck %s +; RUN: opt < %s -passes=instrprof -S | FileCheck %s ; CHECK-NOT: @__profc ; CHECK-NOT: @__profd ; CHECK-NOT: @__llvm_profile_runtime Index: test/Instrumentation/InstrProfiling/noruntime.ll =================================================================== --- test/Instrumentation/InstrProfiling/noruntime.ll +++ test/Instrumentation/InstrProfiling/noruntime.ll @@ -1,6 +1,7 @@ ;; Check that we don't emit the runtime hooks if the user provided them. ; RUN: opt < %s -instrprof -S | FileCheck %s +; RUN: opt < %s -passes=instrprof -S | FileCheck %s ; CHECK-NOT: define {{.*}} @__llvm_profile_runtime_user() ; CHECK-NOT: load i32, i32* @__llvm_profile_runtime Index: test/Instrumentation/InstrProfiling/platform.ll =================================================================== --- test/Instrumentation/InstrProfiling/platform.ll +++ test/Instrumentation/InstrProfiling/platform.ll @@ -2,6 +2,7 @@ ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s -check-prefix=MACHO ; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s -check-prefix=LINUX +; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s -check-prefix=LINUX ; RUN: opt < %s -mtriple=x86_64-unknown-freebsd -instrprof -S | FileCheck %s -check-prefix=FREEBSD ; RUN: opt < %s -mtriple=x86_64-scei-ps4 -instrprof -S | FileCheck %s -check-prefix=PS4 ; RUN: opt < %s -mtriple=x86_64-pc-solaris -instrprof -S | FileCheck %s -check-prefix=SOLARIS Index: test/Instrumentation/InstrProfiling/profiling.ll =================================================================== --- test/Instrumentation/InstrProfiling/profiling.ll +++ test/Instrumentation/InstrProfiling/profiling.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -instrprof -S | FileCheck %s +; RUN: opt < %s -passes=instrprof -S | FileCheck %s target triple = "x86_64-apple-macosx10.10.0"