Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -1116,6 +1116,16 @@ // code generation. MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/false)); + // At -O0, we can still do PGO. Add all the requested passes for + // instrumentation PGO, if requested. + if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr || + PGOOpt->Action == PGOOptions::IRUse)) + PB.addPGOInstrPasses(MPM, CodeGenOpts.DebugPassManager, PassBuilder::O0, + /* RunProfileGen */ PGOOpt->Action == + PGOOptions::IRInstr, + /* IsCS */ false, PGOOpt->ProfileFile, + PGOOpt->ProfileRemappingFile); + // At -O0 we directly run necessary sanitizer passes. if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass())); Index: clang/test/Profile/Inputs/gcc-flag-compatibility_IR.proftext =================================================================== --- /dev/null +++ clang/test/Profile/Inputs/gcc-flag-compatibility_IR.proftext @@ -0,0 +1,11 @@ +# IR level Instrumentation Flag +:ir +main +# Func Hash: +34137660316 +# Num Counters: +2 +# Counter Values: +100 +1 + Index: clang/test/Profile/gcc-flag-compatibility.c =================================================================== --- clang/test/Profile/gcc-flag-compatibility.c +++ clang/test/Profile/gcc-flag-compatibility.c @@ -7,26 +7,50 @@ // -fprofile-use= Uses the profile file /default.profdata // -fprofile-use=/file Uses the profile file /file -// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate | FileCheck -check-prefix=PROFILE-GEN %s -// PROFILE-GEN: __llvm_profile_filename +// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-GEN %s +// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-GEN %s +// PROFILE-GEN: @__profc_main = private global [2 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 +// PROFILE-GEN: @__profd_main = private global // Check that -fprofile-generate=/path/to generates /path/to/default.profraw -// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to | FileCheck -check-prefix=PROFILE-GEN-EQ %s +// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to -fno-experimental-new-pass-manager | FileCheck -check-prefixes=PROFILE-GEN,PROFILE-GEN-EQ %s +// RxUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to -fexperimental-new-pass-manager | FileCheck -check-prefixes=PROFILE-GEN,PROFILE-GEN-EQ %s // PROFILE-GEN-EQ: constant [{{.*}} x i8] c"/path/to{{/|\\5C}}{{.*}}\00" // Check that -fprofile-use=some/path reads some/path/default.profdata +// This uses Clang FE format profile. // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir/some/path // RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/default.profdata -// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s -// PROFILE-USE-2: = !{!"branch_weights", i32 101, i32 2} +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s // Check that -fprofile-use=some/path/file.prof reads some/path/file.prof +// This uses Clang FE format profile. // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir/some/path // RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/file.prof -// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s -// PROFILE-USE-3: = !{!"branch_weights", i32 101, i32 2} +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s +// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s +// PROFILE-USE: = !{!"branch_weights", i32 101, i32 2} + +// Check that -fprofile-use=some/path reads some/path/default.profdata +// This uses LLVM IR format profile. +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/some/path +// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR.proftext -o %t.dir/some/path/default.profdata +// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s +// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s + +// Check that -fprofile-use=some/path/file.prof reads some/path/file.prof +// This uses LLVM IR format profile. +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/some/path +// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR.proftext -o %t.dir/some/path/file.prof +// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s +// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s + +// PROFILE-USE-IR: = !{!"branch_weights", i32 100, i32 1} int X = 0; Index: llvm/include/llvm/Passes/PassBuilder.h =================================================================== --- llvm/include/llvm/Passes/PassBuilder.h +++ llvm/include/llvm/Passes/PassBuilder.h @@ -629,6 +629,12 @@ TopLevelPipelineParsingCallbacks.push_back(C); } + /// Add PGOInstrumenation passes. + void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, + OptimizationLevel Level, bool RunProfileGen, bool IsCS, + std::string ProfileFile, + std::string ProfileRemappingFile); + private: static Optional> parsePipelineText(StringRef Text); @@ -656,11 +662,6 @@ ArrayRef Pipeline, bool VerifyEachPass, bool DebugLogging); - void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, - OptimizationLevel Level, bool RunProfileGen, bool IsCS, - std::string ProfileFile, - std::string ProfileRemappingFile); - void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); // Extension Point callbacks Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -544,7 +544,7 @@ // the size grows, so let's be conservative here and skip this simplification // at -Os/Oz. We will not do this inline for context sensistive PGO (when // IsCS is true). - if (!isOptimizingForSize(Level) && !IsCS) { + if (Level > 0 && !isOptimizingForSize(Level) && !IsCS) { InlineParams IP; // In the old pass manager, this is a cl::opt. Should still this be one? @@ -569,26 +569,29 @@ CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPipeline))); - } - // Delete anything that is now dead to make sure that we don't instrument - // dead code. Instrumentation can end up keeping dead code around and - // dramatically increase code size. - MPM.addPass(GlobalDCEPass()); + // Delete anything that is now dead to make sure that we don't instrument + // dead code. Instrumentation can end up keeping dead code around and + // dramatically increase code size. + MPM.addPass(GlobalDCEPass()); + } if (RunProfileGen) { MPM.addPass(PGOInstrumentationGen(IsCS)); - FunctionPassManager FPM; - FPM.addPass( - createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging)); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + if (Level > 0) { + FunctionPassManager FPM; + FPM.addPass( + createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } // Add the profile lowering pass. InstrProfOptions Options; if (!ProfileFile.empty()) Options.InstrProfileOutput = ProfileFile; - Options.DoCounterPromotion = true; + // Do counter promotion at Level greater than O0. + Options.DoCounterPromotion = (Level > 0); Options.UseBFIInPromotion = IsCS; MPM.addPass(InstrProfiling(Options, IsCS)); } else if (!ProfileFile.empty()) {