[compiler-rt] 8f20ac9 - [PGO] Don't reference functions unless value profiling is enabled

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu May 20 11:09:29 PDT 2021


Author: Reid Kleckner
Date: 2021-05-20T11:09:24-07:00
New Revision: 8f20ac9595c8b279641dace6f212b8a9673b24e4

URL: https://github.com/llvm/llvm-project/commit/8f20ac9595c8b279641dace6f212b8a9673b24e4
DIFF: https://github.com/llvm/llvm-project/commit/8f20ac9595c8b279641dace6f212b8a9673b24e4.diff

LOG: [PGO] Don't reference functions unless value profiling is enabled

This reduces the size of chrome.dll.pdb built with optimizations,
coverage, and line table info from 4,690,210,816 to 2,181,128,192, which
makes it possible to fit under the 4GB limit.

This change can greatly reduce binary size in coverage builds, which do
not need value profiling. IR PGO builds are unaffected. There is a minor
behavior change for frontend PGO.

PGO and coverage both use InstrProfiling to create profile data with
counters. PGO records the address of each function in the __profd_
global. It is used later to map runtime function pointer values back to
source-level function names. Coverage does not appear to use this
information.

Recording the address of every function with code coverage drastically
increases code size. Consider this program:

  void foo();
  void bar();
  inline void inlineMe(int x) {
    if (x > 0)
      foo();
    else
      bar();
  }
  int getVal();
  int main() { inlineMe(getVal()); }

With code coverage, the InstrProfiling pass runs before inlining, and it
captures the address of inlineMe in the __profd_ global. This greatly
increases code size, because now the compiler can no longer delete
trivial code.

One downside to this approach is that users of frontend PGO must apply
the -mllvm -enable-value-profiling flag globally in TUs that enable PGO.
Otherwise, some inline virtual method addresses may not be recorded and
will not be able to be promoted. My assumption is that this mllvm flag
is not popular, and most frontend PGO users don't enable it.

Differential Revision: https://reviews.llvm.org/D102818

Added: 
    

Modified: 
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/CodeGen/CodeGenPGO.cpp
    clang/lib/CodeGen/CodeGenPGO.h
    compiler-rt/test/profile/instrprof-value-prof-2.c
    compiler-rt/test/profile/instrprof-value-prof.c
    llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e38dee92db293..03920982ee086 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -511,6 +511,7 @@ void CodeGenModule::Release() {
   EmitGlobalAnnotations();
   EmitStaticExternCAliases();
   EmitDeferredUnusedCoverageMappings();
+  CodeGenPGO(*this).setValueProfilingFlag(getModule());
   if (CoverageMapping)
     CoverageMapping->emit();
   if (CodeGenOpts.SanitizeCfiCrossDso) {

diff  --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 49b38a404f5dc..d828ac0eb5e98 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -962,6 +962,12 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
         makeArrayRef(Args));
 }
 
+void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
+  if (CGM.getCodeGenOpts().hasProfileClangInstr())
+    M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling",
+                    uint32_t(EnableValueProfiling));
+}
+
 // This method either inserts a call to the profile run-time during
 // instrumentation or puts profile data into metadata for PGO use.
 void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,

diff  --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 906c5e406d77c..f740692ac205b 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -87,6 +87,10 @@ class CodeGenPGO {
   // Insert instrumentation or attach profile metadata at value sites
   void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
                     llvm::Instruction *ValueSite, llvm::Value *ValuePtr);
+
+  // Set a module flag indicating if value profiling is enabled.
+  void setValueProfilingFlag(llvm::Module &M);
+
 private:
   void setFuncName(llvm::Function *Fn);
   void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);

diff  --git a/compiler-rt/test/profile/instrprof-value-prof-2.c b/compiler-rt/test/profile/instrprof-value-prof-2.c
index 88a2de039979e..abc990ac8b052 100644
--- a/compiler-rt/test/profile/instrprof-value-prof-2.c
+++ b/compiler-rt/test/profile/instrprof-value-prof-2.c
@@ -1,4 +1,4 @@
-// RUN: %clang_profgen -O2 -o %t %s
+// RUN: %clang_profgen -mllvm -enable-value-profiling -O2 -o %t %s
 // RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
 // RUN: llvm-profdata merge -o %t.profdata %t.profraw
 // RUN: llvm-profdata show --all-functions -ic-targets  %t.profdata > %t.out

diff  --git a/compiler-rt/test/profile/instrprof-value-prof.c b/compiler-rt/test/profile/instrprof-value-prof.c
index 53e5fdafc5207..3e8203f8182d1 100644
--- a/compiler-rt/test/profile/instrprof-value-prof.c
+++ b/compiler-rt/test/profile/instrprof-value-prof.c
@@ -1,4 +1,4 @@
-// RUN: %clang_profgen -mllvm -vp-static-alloc=false  -O2 -o %t %s
+// RUN: %clang_profgen -mllvm -enable-value-profiling -mllvm -vp-static-alloc=false  -O2 -o %t %s
 // RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
 // RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t DO_NOT_INSTRUMENT
 // RUN: llvm-profdata merge -o %t.profdata %t.profraw

diff  --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index bdb182403041e..1b092f2518041 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -748,7 +748,26 @@ static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) {
   return (Prefix + Name + "." + Twine(FuncHash)).str();
 }
 
+static uint64_t getIntModuleFlagOrZero(Module *M, StringRef Flag) {
+  auto *MD = dyn_cast_or_null<ConstantAsMetadata>(M->getModuleFlag(Flag));
+  if (!MD)
+    return 0;
+
+  // If the flag is a ConstantAsMetadata, it should be an integer representable
+  // in 64-bits.
+  return cast<ConstantInt>(MD->getValue())->getZExtValue();
+}
+
 static inline bool shouldRecordFunctionAddr(Function *F) {
+  // Only record function addresses if IR PGO is enabled or if clang value
+  // profiling is enabled. Recording function addresses greatly increases object
+  // file size, because it prevents the inliner from deleting functions that
+  // have been inlined everywhere.
+  if (!isIRPGOFlagSet(F->getParent()) &&
+      getIntModuleFlagOrZero(F->getParent(), "EnableValueProfiling") == 0) {
+    return false;
+  }
+
   // Check the linkage
   bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage();
   if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&


        


More information about the llvm-commits mailing list