Index: include/clang/Basic/CodeGenOptions.h =================================================================== --- include/clang/Basic/CodeGenOptions.h +++ include/clang/Basic/CodeGenOptions.h @@ -101,6 +101,7 @@ ProfileClangInstr, // Clang instrumentation to generate execution counts // to use with PGO. ProfileIRInstr, // IR level PGO instrumentation in LLVM. + ProfileCSIRInstr, // IR level PGO context sensitive instrumentation in LLVM. }; enum EmbedBitcodeKind { @@ -200,8 +201,8 @@ /// A list of linker options to embed in the object file. std::vector LinkerOptions; - /// Name of the profile file to use as output for -fprofile-instr-generate - /// and -fprofile-generate. + /// Name of the profile file to use as output for -fprofile-instr-generate, + /// -fprofile-generate, and -fcs-profile-generate. std::string InstrProfileOutput; /// Name of the profile file to use with -fprofile-sample-use. @@ -310,6 +311,11 @@ return getProfileInstr() == ProfileIRInstr; } + /// Check if CS IR level profile instrumentation is on. + bool hasProfileCSIRInstr() const { + return getProfileInstr() == ProfileCSIRInstr; + } + /// Check if Clang profile use is on. bool hasProfileClangUse() const { return getProfileUse() == ProfileClangInstr; @@ -317,9 +323,12 @@ /// Check if IR level profile use is on. bool hasProfileIRUse() const { - return getProfileUse() == ProfileIRInstr; + return getProfileUse() == ProfileIRInstr || + getProfileUse() == ProfileCSIRInstr; } + /// Check if CSIR profile use is on. + bool hasProfileCSIRUse() const { return getProfileUse() == ProfileCSIRInstr; } }; } // end namespace clang Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -748,6 +748,12 @@ def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">, Group, Flags<[DriverOption]>, MetaVarName<"">, HelpText<"Generate instrumented code to collect execution counts into /default.profraw (overridden by LLVM_PROFILE_FILE env var)">; +def fcs_profile_generate : Flag<["-"], "fcs-profile-generate">, + Group, Flags<[DriverOption]>, + HelpText<"Generate instrumented code to collect context sensitive execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">; +def fcs_profile_generate_EQ : Joined<["-"], "fcs-profile-generate=">, + Group, Flags<[DriverOption]>, MetaVarName<"">, + HelpText<"Generate instrumented code to collect context sensitive execution counts into /default.profraw (overridden by LLVM_PROFILE_FILE env var)">; def fprofile_use : Flag<["-"], "fprofile-use">, Group, Alias; def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -684,15 +684,35 @@ MPM.add(createInstrProfilingLegacyPass(Options)); } + bool hasIRInstr = false; if (CodeGenOpts.hasProfileIRInstr()) { PMBuilder.EnablePGOInstrGen = true; + hasIRInstr = true; + } + if (CodeGenOpts.hasProfileCSIRInstr()) { + if (CodeGenOpts.hasProfileCSIRUse()) { + errs() << "Cannot have both CSProfileUse pass and CSProfileGen pass at " + "the same time"; + return; + } + if (hasIRInstr) { + errs() << "Cannot have both ProfileGen pass and CSProfileGen pass at the " + "same time"; + return; + } + PMBuilder.EnablePGOCSInstrGen = true; + hasIRInstr = true; + } + if (hasIRInstr) { if (!CodeGenOpts.InstrProfileOutput.empty()) PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput; else PMBuilder.PGOInstrGen = DefaultProfileGenName; } - if (CodeGenOpts.hasProfileIRUse()) + if (CodeGenOpts.hasProfileIRUse()) { PMBuilder.PGOInstrUse = CodeGenOpts.ProfileInstrumentUsePath; + PMBuilder.EnablePGOCSInstrUse = CodeGenOpts.hasProfileCSIRUse(); + } if (!CodeGenOpts.SampleProfileFile.empty()) PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile; @@ -936,21 +956,52 @@ PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty() ? DefaultProfileGenName : CodeGenOpts.InstrProfileOutput, - "", "", "", true, + "", "", PGOOptions::IRInstr, PGOOptions::NoCSAction, CodeGenOpts.DebugInfoForProfiling); - else if (CodeGenOpts.hasProfileIRUse()) + else if (CodeGenOpts.hasProfileIRUse()) { // -fprofile-use. - PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", - CodeGenOpts.ProfileRemappingFile, false, - CodeGenOpts.DebugInfoForProfiling); - else if (!CodeGenOpts.SampleProfileFile.empty()) + auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse + : PGOOptions::NoCSAction; + PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "", + CodeGenOpts.ProfileRemappingFile, PGOOptions::IRUse, + CSAction, CodeGenOpts.DebugInfoForProfiling); + } else if (!CodeGenOpts.SampleProfileFile.empty()) // -fprofile-sample-use - PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, - CodeGenOpts.ProfileRemappingFile, false, - CodeGenOpts.DebugInfoForProfiling); + PGOOpt = + PGOOptions(CodeGenOpts.SampleProfileFile, "", + CodeGenOpts.ProfileRemappingFile, PGOOptions::SampleUse, + PGOOptions::NoCSAction, CodeGenOpts.DebugInfoForProfiling); else if (CodeGenOpts.DebugInfoForProfiling) // -fdebug-info-for-profiling - PGOOpt = PGOOptions("", "", "", "", false, true); + PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction, + PGOOptions::NoCSAction, true); + + // Check to see if we want to generate a CS profile. + if (CodeGenOpts.hasProfileCSIRInstr()) { + if (CodeGenOpts.hasProfileCSIRUse()) { + errs() << "Cannot have both CSProfileUse pass and CSProfileGen pass at " + "the same time"; + return; + } + if (PGOOpt.hasValue()) { + if (PGOOpt->Action == PGOOptions::IRInstr || + PGOOpt->Action == PGOOptions::SampleUse) { + errs() << "Cannot run CSProfileGen pass with ProfileGen or SampleUse " + " pass"; + return; + } + PGOOpt->CSProfileGenFile = CodeGenOpts.InstrProfileOutput.empty() + ? DefaultProfileGenName + : CodeGenOpts.InstrProfileOutput; + PGOOpt->CSAction = PGOOptions::CSIRInstr; + } else + PGOOpt = PGOOptions("", + CodeGenOpts.InstrProfileOutput.empty() + ? DefaultProfileGenName + : CodeGenOpts.InstrProfileOutput, + "", PGOOptions::NoAction, PGOOptions::CSIRInstr, + CodeGenOpts.DebugInfoForProfiling); + } PassBuilder PB(TM.get(), PGOOpt); @@ -1211,6 +1262,16 @@ Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); + + // Context sensitive profile. + if (CGOpts.hasProfileCSIRInstr()) { + Conf.RunCSIRInstr = true; + Conf.CSIRProfile = std::move(CGOpts.InstrProfileOutput); + } else if (CGOpts.hasProfileCSIRUse()) { + Conf.RunCSIRInstr = false; + Conf.CSIRProfile = std::move(CGOpts.ProfileInstrumentUsePath); + } + Conf.ProfileRemapping = std::move(ProfileRemapping); Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; Conf.DebugPassManager = CGOpts.DebugPassManager; Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -53,6 +53,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ConvertUTF.h" @@ -418,7 +419,8 @@ OpenMPRuntime->clear(); } if (PGOReader) { - getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext)); + getModule().setProfileSummary(PGOReader->getSummary(false).getMD(VMContext), + llvm::ProfileSummary::PSK_Instr); if (PGOStats.hasDiagnostics()) PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName); } Index: lib/Driver/ToolChain.cpp =================================================================== --- lib/Driver/ToolChain.cpp +++ lib/Driver/ToolChain.cpp @@ -406,6 +406,8 @@ if (needsGCovInstrumentation(Args) || Args.hasArg(options::OPT_fprofile_generate) || Args.hasArg(options::OPT_fprofile_generate_EQ) || + Args.hasArg(options::OPT_fcs_profile_generate) || + Args.hasArg(options::OPT_fcs_profile_generate_EQ) || Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || Args.hasArg(options::OPT_fcreate_profile)) Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -725,6 +725,13 @@ PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) PGOGenerateArg = nullptr; + auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, + options::OPT_fcs_profile_generate_EQ, + options::OPT_fno_profile_generate); + if (CSPGOGenerateArg && + CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) + CSPGOGenerateArg = nullptr; + auto *ProfileGenerateArg = Args.getLastArg( options::OPT_fprofile_instr_generate, options::OPT_fprofile_instr_generate_EQ, @@ -748,6 +755,10 @@ D.Diag(diag::err_drv_argument_not_allowed_with) << ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling(); + if (CSPGOGenerateArg && PGOGenerateArg) + D.Diag(diag::err_drv_argument_not_allowed_with) + << CSPGOGenerateArg->getSpelling() << PGOGenerateArg->getSpelling(); + if (ProfileGenerateArg) { if (ProfileGenerateArg->getOption().matches( options::OPT_fprofile_instr_generate_EQ)) @@ -757,11 +768,22 @@ CmdArgs.push_back("-fprofile-instrument=clang"); } + Arg *PGOGenArg = nullptr; if (PGOGenerateArg) { + assert(!CSPGOGenerateArg); + PGOGenArg = PGOGenerateArg; CmdArgs.push_back("-fprofile-instrument=llvm"); - if (PGOGenerateArg->getOption().matches( - options::OPT_fprofile_generate_EQ)) { - SmallString<128> Path(PGOGenerateArg->getValue()); + } + if (CSPGOGenerateArg) { + assert(!PGOGenerateArg); + PGOGenArg = CSPGOGenerateArg; + CmdArgs.push_back("-fprofile-instrument=csllvm"); + } + if (PGOGenArg) { + if (PGOGenArg->getOption().matches( + PGOGenerateArg ? options::OPT_fprofile_generate_EQ + : options::OPT_fcs_profile_generate_EQ)) { + SmallString<128> Path(PGOGenArg->getValue()); llvm::sys::path::append(Path, "default_%m.profraw"); CmdArgs.push_back( Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path)); @@ -4515,6 +4537,14 @@ // Forward -f options with positive and negative forms; we translate // these by hand. if (Arg *A = getLastProfileSampleUseArg(Args)) { + auto *PGOArg = Args.getLastArg( + options::OPT_fprofile_generate, options::OPT_fprofile_generate_EQ, + options::OPT_fcs_profile_generate, options::OPT_fcs_profile_generate_EQ, + options::OPT_fprofile_use, options::OPT_fprofile_use_EQ); + if (PGOArg) + D.Diag(diag::err_drv_argument_not_allowed_with) + << "SampleUse with PGO options"; + StringRef fname = A->getValue(); if (!llvm::sys::fs::exists(fname)) D.Diag(diag::err_drv_no_such_file) << fname; Index: lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- lib/Driver/ToolChains/CommonArgs.cpp +++ lib/Driver/ToolChains/CommonArgs.cpp @@ -463,6 +463,31 @@ Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName)); } + auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, + options::OPT_fcs_profile_generate_EQ, + options::OPT_fno_profile_generate); + if (CSPGOGenerateArg && + CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) + CSPGOGenerateArg = nullptr; + + auto *ProfileUseArg = getLastProfileUseArg(Args); + + if (CSPGOGenerateArg) { + CmdArgs.push_back(Args.MakeArgString("-plugin-opt=cs-profile-generate")); + if (CSPGOGenerateArg->getOption().matches( + options::OPT_fcs_profile_generate_EQ)) { + SmallString<128> Path(CSPGOGenerateArg->getValue()); + llvm::sys::path::append(Path, "default_%m.profraw"); + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + Path)); + } else + CmdArgs.push_back( + Args.MakeArgString("-plugin-opt=cs-profile-path=default_%m.profraw")); + } else if (ProfileUseArg) { + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + + ProfileUseArg->getValue())); + } + // Need this flag to turn on new pass manager via Gold plugin. if (Args.hasFlag(options::OPT_fexperimental_new_pass_manager, options::OPT_fno_experimental_new_pass_manager, Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -587,6 +587,7 @@ .Case("none", CodeGenOptions::ProfileNone) .Case("clang", CodeGenOptions::ProfileClangInstr) .Case("llvm", CodeGenOptions::ProfileIRInstr) + .Case("csllvm", CodeGenOptions::ProfileCSIRInstr) .Default(~0U); if (I == ~0U) { Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args) @@ -609,9 +610,12 @@ } std::unique_ptr PGOReader = std::move(ReaderOrErr.get()); - if (PGOReader->isIRLevelProfile()) - Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); - else + if (PGOReader->isIRLevelProfile()) { + if (PGOReader->hasCSIRLevelProfile()) + Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr); + else + Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); + } else Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); } Index: test/CodeGen/Inputs/pgotestir.proftext =================================================================== --- test/CodeGen/Inputs/pgotestir.proftext +++ test/CodeGen/Inputs/pgotestir.proftext @@ -0,0 +1,2 @@ +# IR level Instrumentation Flag +:ir Index: test/CodeGen/Inputs/pgotestir_cs.proftext =================================================================== --- test/CodeGen/Inputs/pgotestir_cs.proftext +++ test/CodeGen/Inputs/pgotestir_cs.proftext @@ -0,0 +1,2 @@ +# IR level Instrumentation Flag with CS +:csir Index: test/CodeGen/cspgo-instrumentation.c =================================================================== --- test/CodeGen/cspgo-instrumentation.c +++ test/CodeGen/cspgo-instrumentation.c @@ -0,0 +1,40 @@ +// Test if CSPGO instrumentation and use pass are invoked. +// +// Ensure Pass PGOInstrumentationGenPass is invoked. +// RUN: %clang_cc1 -O2 -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw %s -mllvm -debug-pass=Structure -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN +// RUN: %clang_cc1 -O2 -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw %s -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-NEWPM +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN: PGOInstrumentationGenPass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-NEWPM: Running pass: PGOInstrumentationGen +// +// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotestir.proftext +// +// Ensure Pass PGOInstrumentationUsePass and PGOInstrumentationGenPass are invoked. +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw %s -mllvm -debug-pass=Structure -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2 +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw %s -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2-NEWPM +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2: PGOInstrumentationUsePass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2: PGOInstrumentationGenPass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN2-NEWPM: Running pass: PGOInstrumentationGen + +// Ensure Pass PGOInstrumentationUsePass is invoked only once. +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata %s -mllvm -debug-pass=Structure -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata %s -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE-NEWPM +// CHECK-PGOUSEPASS-INVOKED-USE: PGOInstrumentationUsePass +// CHECK-PGOUSEPASS-INVOKED-USE-NOT: PGOInstrumentationUsePass +// CHECK-PGOUSEPASS-INVOKED-USE-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-PGOUSEPASS-INVOKED-USE-NEWPM-NOT: Running pass: PGOInstrumentationUse +// +// Ensure Pass PGOInstrumentationUsePass is invoked twice. +// RUN: llvm-profdata merge -o %t_cs.profdata %S/Inputs/pgotestir_cs.proftext +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -mllvm -debug-pass=Structure -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE2 +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-USE2-NEWPM +// CHECK-PGOUSEPASS-INVOKED-USE2: PGOInstrumentationUsePass +// CHECK-PGOUSEPASS-INVOKED-USE2: PGOInstrumentationUsePass +// CHECK-PGOUSEPASS-INVOKED-USE2-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-PGOUSEPASS-INVOKED-USE2-NEWPM: Running pass: PGOInstrumentationUse + +// Ensure Pass CSPGOInstrumentationGenPass and CSPGOInstrumentationUsePass will +// not be on at the same time. +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENUSEPASS-ERROR +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw -fexperimental-new-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENUSEPASS-ERROR +// CHECK-CSPGOGENUSEPASS-ERROR: Cannot have both CSProfileUse pass and CSProfileGen pass at the same time Index: test/CodeGen/cspgo-instrumentation_thinlto.c =================================================================== --- test/CodeGen/cspgo-instrumentation_thinlto.c +++ test/CodeGen/cspgo-instrumentation_thinlto.c @@ -0,0 +1,47 @@ +// Test if CSPGO instrumentation and use pass are invoked in thinlto. +// +// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotestir.proftext +// +// Ensure Pass PGOInstrumentationGenPass is not invoked in PreLink. +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata -fprofile-instrument=csllvm %s -fprofile-instrument-path=default.profraw -flto=thin -mllvm -debug-pass=Structure -emit-llvm-bc -o %S/foo_fe.bc 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t.profdata -fprofile-instrument=csllvm %s -fprofile-instrument-path=default.profraw -flto=thin -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm-bc -o %S/foo_fe_pm.bc 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE-NEWPM +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE: PGOInstrumentationUsePass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE-NOT: PGOInstrumentationGenPass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-PRE-NEWPM-NOT: Running pass: PGOInstrumentationGen +// +// RUN: llvm-lto -thinlto -o %S/foo %S/foo_fe.bc +// RUN: llvm-lto -thinlto -o %S/foo_pm %S/foo_fe_pm.bc +// Ensure Pass PGOInstrumentationGenPass is invoked in PostLink. +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe.bc -fthinlto-index=%S/foo.thinlto.bc -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw -flto=thin -emit-llvm -mllvm -debug-pass=Structure -o - |& FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe_pm.bc -fthinlto-index=%S/foo_pm.thinlto.bc -fexperimental-new-pass-manager -fdebug-pass-manager -fprofile-instrument=csllvm -fprofile-instrument-path=default.profraw -flto=thin -emit-llvm -o - |& FileCheck %s -check-prefix=CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST-NEWPM +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST-NOT: PGOInstrumentationUsePass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST: PGOInstrumentationGenPass +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST-NEWPM-NOT: Running pass: PGOInstrumentationUse +// CHECK-CSPGOGENPASS-INVOKED-INSTR-GEN-POST-NEWPM: Running pass: PGOInstrumentationGen +// +// RUN: llvm-profdata merge -o %t_cs.profdata %S/Inputs/pgotestir_cs.proftext +// +// Ensure Pass PGOInstrumentationUsePass is invoked Once in PreLink. +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -flto=thin -mllvm -debug-pass=Structure -emit-llvm-bc -o %S/foo_fe.bc 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE +// RUN: %clang_cc1 -O2 -fprofile-instrument-use-path=%t_cs.profdata %s -flto=thin -fexperimental-new-pass-manager -fdebug-pass-manager -emit-llvm-bc -o %S/foo_fe_pm.bc 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE-NEWPM +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE: PGOInstrumentationUsePass +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE-NOT: PGOInstrumentationUsePass +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-PRE-NEWPM-NOT: Running pass: PGOInstrumentationUse +// +// RUN: llvm-lto -thinlto -o %S/foo %S/foo_fe.bc +// RUN: llvm-lto -thinlto -o %S/foo_pm %S/foo_fe_pm.bc +// Ensure Pass PGOInstrumentationUSEPass is invoked in PostLink. +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe.bc -fthinlto-index=%S/foo.thinlto.bc -fprofile-instrument-use-path=%t_cs.profdata -flto=thin -emit-llvm -mllvm -debug-pass=Structure -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe_pm.bc -fthinlto-index=%S/foo_pm.thinlto.bc -fexperimental-new-pass-manager -fdebug-pass-manager -fprofile-instrument-use-path=%t_cs.profdata -flto=thin -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST-NEWPM +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST: PGOInstrumentationUsePass +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST-NOT: PGOInstrumentationUsePass +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST-NEWPM: Running pass: PGOInstrumentationUse +// CHECK-CSPGOUSEPASS-INVOKED-INSTR-USE-POST-NEWPM-NOT: Running pass: PGOInstrumentationUse +// +// Finally, test if a non-cs profile is passed to postline, PGO UsePass is not invoked. +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe.bc -fthinlto-index=%S/foo.thinlto.bc -fprofile-instrument-use-path=%t.profdata -flto=thin -emit-llvm -mllvm -debug-pass=Structure -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-INSTR-USE-POST +// RUN: %clang_cc1 -O2 -x ir %S/foo_fe_pm.bc -fthinlto-index=%S/foo_pm.thinlto.bc -fexperimental-new-pass-manager -fdebug-pass-manager -fprofile-instrument-use-path=%t.profdata -flto=thin -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOUSEPASS-INVOKED-INSTR-USE-POST-NEWPM +// CHECK-PGOUSEPASS-INVOKED-INSTR-USE-POST-NOT: PGOInstrumentationUsePass +// CHECK-PGOUSEPASS-INVOKED-INSTR-USE-POST-NEWPM-NOT: Running pass: PGOInstrumentationUse