xur updated this revision to Diff 46303.
xur added a comment.
Integrated most recently comments/suggestions from David and Sean.
Thanks,
-Rong
http://reviews.llvm.org/D15829
Files:
include/clang/Basic/DiagnosticDriverKinds.td
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
include/clang/Frontend/CodeGenOptions.def
include/clang/Frontend/CodeGenOptions.h
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/Driver/Tools.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-instrument=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-instrument=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-instrument=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-instrument=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-instrument=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-instrument=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,29 @@
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_instrument_EQ)) {
+ StringRef Value = A->getValue();
+ PGOInstrumentor Method = llvm::StringSwitch<PGOInstrumentor>(Value)
+ .Case("Clang", Clang)
+ .Case("LLVM", LLVM)
+ .Default(Unknown);
+ switch (Method) {
+ case LLVM:
+ Opts.setProfileInstr(CodeGenOptions::ProfileIRInstr);
+ break;
+ case Clang:
+ Opts.setProfileInstr(CodeGenOptions::ProfileClangInstr);
+ break;
+ case Unknown:
+ default:
+ Diags.Report(diag::err_drv_invalid_pgo_instrumentor)
+ << A->getAsString(Args) << Value;
+ break;
+ }
+ }
+
Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ);
Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
Opts.CoverageMapping =
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -3230,8 +3230,9 @@
llvm::sys::path::append(Path, "default.profraw");
CmdArgs.push_back(
Args.MakeArgString(Twine("-fprofile-instr-generate=") + Path));
- } else
- Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
+ }
+ // The default is to use Clang Instrumentation.
+ CmdArgs.push_back("-fprofile-instrument=Clang");
}
if (ProfileUseArg) {
Index: lib/CodeGen/CodeGenPGO.cpp
===================================================================
--- lib/CodeGen/CodeGenPGO.cpp
+++ lib/CodeGen/CodeGenPGO.cpp
@@ -37,7 +37,8 @@
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().getProfileInstr() ==
+ CodeGenOptions::ProfileClangInstr)
FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
}
@@ -610,7 +611,8 @@
void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
const Decl *D = GD.getDecl();
- bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
+ bool InstrumentRegions = (CGM.getCodeGenOpts().getProfileInstr() ==
+ CodeGenOptions::ProfileClangInstr);
llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
if (!InstrumentRegions && !PGOReader)
return;
@@ -729,7 +731,9 @@
}
void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S) {
- if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
+ if (CGM.getCodeGenOpts().getProfileInstr() !=
+ CodeGenOptions::ProfileClangInstr ||
+ !RegionCounterMap)
return;
if (!Builder.GetInsertBlock())
return;
@@ -754,7 +758,8 @@
if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
return;
- bool InstrumentValueSites = CGM.getCodeGenOpts().ProfileInstrGenerate;
+ bool InstrumentValueSites = (CGM.getCodeGenOpts().getProfileInstr() ==
+ CodeGenOptions::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,8 @@
if (C.getLangOpts().ObjC1)
ObjCData = new ObjCEntrypoints();
- if (!CodeGenOpts.InstrProfileInput.empty()) {
+ if (CodeGenOpts.getProfileInstr() != CodeGenOptions::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,8 @@
public:
/// Increment the profiler's counter for the given statement.
void incrementProfileCounter(const Stmt *S) {
- if (CGM.getCodeGenOpts().ProfileInstrGenerate)
+ if (CGM.getCodeGenOpts().getProfileInstr() ==
+ CodeGenOptions::ProfileClangInstr)
PGO.emitCounterIncrement(Builder, S);
PGO.setCurrentStmt(S);
}
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -883,7 +883,9 @@
void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
const Stmt *S) {
llvm::BasicBlock *SkipCountBB = nullptr;
- if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileInstrGenerate) {
+ if (HaveInsertPoint() &&
+ CGM.getCodeGenOpts().getProfileInstr() ==
+ CodeGenOptions::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,8 @@
// 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().getProfileInstr() !=
+ CodeGenOptions::ProfileClangInstr &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isa<BreakStmt>(S.getSubStmt())) {
JumpDest Block = BreakContinueStack.back().BreakBlock;
@@ -1200,7 +1201,8 @@
if (SwitchWeights)
SwitchWeights->push_back(getProfileCount(NextCase));
- if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
+ if (CGM.getCodeGenOpts().getProfileInstr() ==
+ CodeGenOptions::ProfileClangInstr) {
CaseDest = createBasicBlock("sw.bb");
EmitBlockWithFallThrough(CaseDest, &S);
}
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -429,11 +429,24 @@
MPM->add(createStripSymbolsPass(true));
}
- if (CodeGenOpts.ProfileInstrGenerate) {
+ switch (CodeGenOpts.getProfileInstr()) {
+ case CodeGenOptions::ProfileClangInstr: {
InstrProfOptions Options;
Options.NoRedZone = CodeGenOpts.DisableRedZone;
Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
MPM->add(createInstrProfilingPass(Options));
+ break;
+ }
+ case CodeGenOptions::ProfileIRInstr:
+ if (!CodeGenOpts.InstrProfileInput.empty())
+ PMBuilder.PGOInstrUse = CodeGenOpts.InstrProfileInput;
+ else if (!CodeGenOpts.InstrProfileOutput.empty())
+ PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput;
+ else
+ PMBuilder.PGOInstrGen = "default.profraw";
+ break;
+ default:
+ break;
}
if (!CodeGenOpts.SampleProfileFile.empty())
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -108,6 +108,13 @@
SRCK_InRegs // Small structs in registers (-freg-struct-return).
};
+ enum ProfileInstrKind {
+ ProfileNoInstr, // No instrumentation.
+ ProfileClangInstr, // Clang instrumentation to generate execution counts
+ // to use with PGO.
+ ProfileIRInstr // IR level PGO instrumentation in LLVM.
+ };
+
/// The code model to use (-mcmodel).
std::string CodeModel;
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -103,8 +103,8 @@
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.
+/// \brief Choose PGO instrumenation kind.
+ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNoInstr)
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/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -446,7 +446,7 @@
def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
Alias<fprofile_sample_use_EQ>;
def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
- Group<f_Group>, Flags<[CC1Option]>,
+ Group<f_Group>, Flags<[DriverOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overriden by '=' form of option or LLVM_PROFILE_FILE env var)">;
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<file>">,
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -268,6 +268,10 @@
def fsanitize_coverage_8bit_counters
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
HelpText<"Enable frequency counters in sanitizer coverage">;
+def fprofile_instrument_EQ: Joined<["-"], "fprofile-instrument=">,
+ HelpText<"Specify the kind of instrumentation that instruments the code "
+ "to generate execution counts to use with PGO. Accepted values "
+ "are Clang and LLVM">;
//===----------------------------------------------------------------------===//
// 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits