xur updated this revision to Diff 46199.
xur added a comment.

This new version implemented the usage model David proposed. We now have a cc1 
option -fprofile-instrumentor={llvm | clang} to choose which instrumentation to 
use. The slight difference from David's proposal is that we can use this option 
with -fprofile-instr-use.

Thanks,

-Rong


http://reviews.llvm.org/D15829

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Driver/CC1Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGStmt.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenPGO.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/Inputs/pgotest.profraw
  test/CodeGen/pgo-instrumentation.c

Index: test/CodeGen/pgo-instrumentation.c
===================================================================
--- /dev/null
+++ test/CodeGen/pgo-instrumentation.c
@@ -0,0 +1,28 @@
+// Test if PGO instrumentation and use pass are invoked.
+//
+// Ensure Pass PGOInstrumentationGenPass is invoked.
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=llvm -fprofile-instr-generate %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOGENPASS-INVOKED-INSTR-GEN
+// CHECK-PGOGENPASS-INVOKED-INSTR-GEN: PGOInstrumentationGenPass
+//
+// Ensure Pass PGOInstrumentationGenPass is invoked.
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=llvm -fprofile-generate %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOGENPASS-INVOKED-GEN
+// CHECK-PGOGENPASS-INVOKED-GEN: PGOInstrumentationGenPass
+//
+// Ensure Pass PGOInstrumentationGenPass is not invoked.
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=clang -fprofile-instr-generate %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOGENPASS-INVOKED-INSTR-GEN-CLANG
+// CHECK-PGOGENPASS-INVOKED-INSTR-GEN-CLANG-NOT: PGOInstrumentationGenPass
+//
+// Ensure Pass PGOInstrumentationUsePass is invoked.
+// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotest.profraw
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=llvm -fprofile-instr-use=%t.profdata %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-INSTR-USE
+// CHECK-PGOUSEPASS-INVOKED-INSTR-USE: PGOInstrumentationUsePass
+//
+// Ensure Pass PGOInstrumentationUsePass is invoked.
+// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotest.profraw
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=llvm -fprofile-use=%t.profdata %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE
+// CHECK-PGOUSEPASS-INVOKED-USE: PGOInstrumentationUsePass
+//
+// Ensure Pass PGOInstrumentationUsePass is not invoked.
+// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotest.profraw
+// RUN: %clang -O2 -c -Xclang -fprofile-instrumentor=clang -fprofile-use=%t.profdata %s -mllvm -debug-pass=Structure 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE-CLANG
+// CHECK-PGOUSEPASS-INVOKED-USE-CLANG-NOT: PGOInstrumentationUsePass
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -477,8 +477,28 @@
   Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as);
   Opts.Autolink = !Args.hasArg(OPT_fno_autolink);
   Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
-  Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate) ||
-      Args.hasArg(OPT_fprofile_instr_generate_EQ);
+
+  enum PGOInstrumentor { Unknown, Clang, LLVM };
+  if (Arg *A = Args.getLastArg(OPT_fprofile_instrumentor_EQ)) {
+    StringRef Value = A->getValue();
+    PGOInstrumentor Method = llvm::StringSwitch<PGOInstrumentor>(Value)
+      .Case("clang", Clang)
+      .Case("llvm", LLVM)
+      .Default(Unknown);
+    if (Method == Unknown)
+      Diags.Report(diag::err_drv_invalid_pgo_instrumentor) 
+                     << A->getAsString(Args) << Value;
+    else {
+      Opts.ProfileIRInstr = (Method == LLVM);
+      Opts.ProfileClangInstr = (Method == Clang);
+    }
+  } else {
+    // Default PGO instrumentor is Clang instrumentation.
+    Opts.ProfileClangInstr = Args.hasArg(OPT_fprofile_instr_generate) ||
+                             Args.hasArg(OPT_fprofile_instr_generate_EQ);
+    Opts.ProfileIRInstr = false;
+  }
+
   Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ);
   Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
   Opts.CoverageMapping =
Index: lib/CodeGen/CodeGenPGO.cpp
===================================================================
--- lib/CodeGen/CodeGenPGO.cpp
+++ lib/CodeGen/CodeGenPGO.cpp
@@ -37,7 +37,7 @@
       PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
 
   // If we're generating a profile, create a variable for the name.
-  if (CGM.getCodeGenOpts().ProfileInstrGenerate)
+  if (CGM.getCodeGenOpts().ProfileClangInstr)
     FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
 }
 
@@ -610,7 +610,7 @@
 
 void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
   const Decl *D = GD.getDecl();
-  bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
+  bool InstrumentRegions = CGM.getCodeGenOpts().ProfileClangInstr;
   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
   if (!InstrumentRegions && !PGOReader)
     return;
@@ -729,7 +729,7 @@
 }
 
 void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S) {
-  if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
+  if (!CGM.getCodeGenOpts().ProfileClangInstr || !RegionCounterMap)
     return;
   if (!Builder.GetInsertBlock())
     return;
@@ -754,7 +754,7 @@
   if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
     return;
 
-  bool InstrumentValueSites = CGM.getCodeGenOpts().ProfileInstrGenerate;
+  bool InstrumentValueSites = CGM.getCodeGenOpts().ProfileClangInstr;
   if (InstrumentValueSites && RegionCounterMap) {
     llvm::LLVMContext &Ctx = CGM.getLLVMContext();
     auto *I8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -147,7 +147,7 @@
   if (C.getLangOpts().ObjC1)
     ObjCData = new ObjCEntrypoints();
 
-  if (!CodeGenOpts.InstrProfileInput.empty()) {
+  if (!CodeGenOpts.ProfileIRInstr && !CodeGenOpts.InstrProfileInput.empty()) {
     auto ReaderOrErr =
         llvm::IndexedInstrProfReader::create(CodeGenOpts.InstrProfileInput);
     if (std::error_code EC = ReaderOrErr.getError()) {
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -952,7 +952,7 @@
 public:
   /// Increment the profiler's counter for the given statement.
   void incrementProfileCounter(const Stmt *S) {
-    if (CGM.getCodeGenOpts().ProfileInstrGenerate)
+    if (CGM.getCodeGenOpts().ProfileClangInstr)
       PGO.emitCounterIncrement(Builder, S);
     PGO.setCurrentStmt(S);
   }
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -883,7 +883,7 @@
 void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
                                                const Stmt *S) {
   llvm::BasicBlock *SkipCountBB = nullptr;
-  if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileInstrGenerate) {
+  if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileClangInstr) {
     // When instrumenting for profiling, the fallthrough to certain
     // statements needs to skip over the instrumentation code so that we
     // get an accurate count.
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -1153,7 +1153,7 @@
   // If the body of the case is just a 'break', try to not emit an empty block.
   // If we're profiling or we're not optimizing, leave the block in for better
   // debug and coverage analysis.
-  if (!CGM.getCodeGenOpts().ProfileInstrGenerate &&
+  if (!CGM.getCodeGenOpts().ProfileClangInstr &&
       CGM.getCodeGenOpts().OptimizationLevel > 0 &&
       isa<BreakStmt>(S.getSubStmt())) {
     JumpDest Block = BreakContinueStack.back().BreakBlock;
@@ -1200,7 +1200,7 @@
 
     if (SwitchWeights)
       SwitchWeights->push_back(getProfileCount(NextCase));
-    if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
+    if (CGM.getCodeGenOpts().ProfileClangInstr) {
       CaseDest = createBasicBlock("sw.bb");
       EmitBlockWithFallThrough(CaseDest, &S);
     }
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -429,13 +429,22 @@
       MPM->add(createStripSymbolsPass(true));
   }
 
-  if (CodeGenOpts.ProfileInstrGenerate) {
+  if (CodeGenOpts.ProfileClangInstr) {
     InstrProfOptions Options;
     Options.NoRedZone = CodeGenOpts.DisableRedZone;
     Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
     MPM->add(createInstrProfilingPass(Options));
   }
 
+  if (CodeGenOpts.ProfileIRInstr) {
+    if (!CodeGenOpts.InstrProfileInput.empty())
+      PMBuilder.PGOInstrUse = CodeGenOpts.InstrProfileInput;
+    else if (!CodeGenOpts.InstrProfileOutput.empty())
+      PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput;
+    else
+      PMBuilder.PGOInstrGen = "default.profraw";
+  }
+
   if (!CodeGenOpts.SampleProfileFile.empty())
     MPM->add(createSampleProfileLoaderPass(CodeGenOpts.SampleProfileFile));
 
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -103,8 +103,9 @@
 VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
 VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
 
-CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate
-                                        ///< execution counts to use with PGO.
+CODEGENOPT(ProfileClangInstr, 1, 0) ///< Clang Instrumentation to generate
+                                    ///< execution counts to use with PGO.
+CODEGENOPT(ProfileIRInstr, 1, 0) ///< IR level PGO instrumentation and use.
 CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
                                    ///< enable code coverage analysis.
 CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -268,6 +268,9 @@
 def fsanitize_coverage_8bit_counters
     : Flag<["-"], "fsanitize-coverage-8bit-counters">,
       HelpText<"Enable frequency counters in sanitizer coverage">;
+def fprofile_instrumentor_EQ: Joined<["-"], "fprofile-instrumentor=">,
+    HelpText<"Specify the instrumentor that instruments the code to generate "
+             "execution counts to use with PGO">;
 
 //===----------------------------------------------------------------------===//
 // Dependency Output Options
Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -27,6 +27,8 @@
   "invalid thread model '%0' in '%1' for this target">;
 def err_drv_invalid_linker_name : Error<
   "invalid linker name in argument '%0'">;
+def err_drv_invalid_pgo_instrumentor: Error<
+  "invalid PGO instrumentor in argument '%0'">;
 def err_drv_invalid_rtlib_name : Error<
   "invalid runtime library name in argument '%0'">;
 def err_drv_unsupported_rtlib_for_platform : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to