diff --git a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h --- a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -226,6 +226,12 @@ OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel; } + /// Enable or disable the new pass manager. + void setUseNewPM(unsigned Enabled) { UseNewPM = Enabled; } + + /// Enable or disable debug output for the new pass manager. + void setDebugPassManager(unsigned Enabled) { DebugPassManager = Enabled; } + /// Disable CodeGen, only run the stages till codegen and stop. The output /// will be bitcode. void disableCodeGen(bool Disable) { DisableCodeGen = Disable; } @@ -341,6 +347,14 @@ /// IR Optimization Level [0-3]. unsigned OptLevel = 3; + + /// Flag to indicate whether the new pass manager should be used for IR + /// optimizations. + bool UseNewPM = LLVM_ENABLE_NEW_PASS_MANAGER; + + /// Flag to indicate whether debug output should be enabled for the new pass + /// manager. + bool DebugPassManager = false; }; } #endif diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -37,6 +38,8 @@ #include "llvm/LTO/SummaryBasedOptimizations.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/Debug.h" @@ -262,6 +265,68 @@ PM.run(TheModule); } +static void optimizeModuleNewPM(Module &TheModule, TargetMachine &TM, + unsigned OptLevel, bool Freestanding, + bool DebugPassManager, + ModuleSummaryIndex *Index) { + Optional PGOOpt; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI(DebugPassManager); + SI.registerCallbacks(PIC, &FAM); + PipelineTuningOptions PTO; + PTO.LoopVectorization = true; + PTO.SLPVectorization = true; + PassBuilder PB(&TM, PTO, PGOOpt, &PIC); + + std::unique_ptr TLII( + new TargetLibraryInfoImpl(Triple(TM.getTargetTriple()))); + if (Freestanding) + TLII->disableAllFunctions(); + FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); + + AAManager AA = PB.buildDefaultAAPipeline(); + + // Register the AA manager first so that our version is the one used. + FAM.registerPass([&] { return std::move(AA); }); + + // Register all the basic analyses with the managers. + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + ModulePassManager MPM; + + PassBuilder::OptimizationLevel OL; + + switch (OptLevel) { + default: + llvm_unreachable("Invalid optimization level"); + case 0: + OL = PassBuilder::OptimizationLevel::O0; + break; + case 1: + OL = PassBuilder::OptimizationLevel::O1; + break; + case 2: + OL = PassBuilder::OptimizationLevel::O2; + break; + case 3: + OL = PassBuilder::OptimizationLevel::O3; + break; + } + + MPM.addPass(PB.buildThinLTODefaultPipeline(OL, Index)); + + MPM.run(TheModule, MAM); +} + static void addUsedSymbolToPreservedGUID(const lto::InputFile &File, DenseSet &PreservedGUID) { @@ -421,7 +486,8 @@ const GVSummaryMapTy &DefinedGlobals, const ThinLTOCodeGenerator::CachingOptions &CacheOptions, bool DisableCodeGen, StringRef SaveTempsDir, - bool Freestanding, unsigned OptLevel, unsigned count) { + bool Freestanding, unsigned OptLevel, unsigned count, + bool UseNewPM, bool DebugPassManager) { // "Benchmark"-like optimization: single-source case bool SingleModule = (ModuleMap.size() == 1); @@ -461,7 +527,11 @@ saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc"); } - optimizeModule(TheModule, TM, OptLevel, Freestanding, &Index); + if (UseNewPM) + optimizeModuleNewPM(TheModule, TM, OptLevel, Freestanding, DebugPassManager, + &Index); + else + optimizeModule(TheModule, TM, OptLevel, Freestanding, &Index); saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc"); @@ -1132,7 +1202,8 @@ *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList, ExportList, GUIDPreservedSymbols, ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions, - DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count); + DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count, + UseNewPM, DebugPassManager); // Commit to the cache (if enabled) CacheEntry.write(*OutputBuffer); diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll @@ -5,6 +5,7 @@ ; with -lto-pass-remarks-with-hotness. ; RUN: llvm-lto -thinlto-action=run \ +; RUN: -use-new-pm=false \ ; RUN: -lto-pass-remarks-output=%t.yaml \ ; RUN: -lto-pass-remarks-with-hotness \ ; RUN: -exported-symbol _func2 \ diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll --- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll @@ -4,6 +4,7 @@ ; Optimization records are collected regardless of the diagnostic handler ; RUN: rm -f %t.yaml.thin.0.yaml %t.yaml.thin.1.yaml ; RUN: llvm-lto -thinlto-action=run \ +; RUN: -use-new-pm=false \ ; RUN: -lto-pass-remarks-output=%t.yaml \ ; RUN: -lto-pass-remarks-filter=inline \ ; RUN: -lto-pass-remarks-format=yaml \ diff --git a/llvm/test/ThinLTO/X86/newpm-basic.ll b/llvm/test/ThinLTO/X86/newpm-basic.ll --- a/llvm/test/ThinLTO/X86/newpm-basic.ll +++ b/llvm/test/ThinLTO/X86/newpm-basic.ll @@ -1,7 +1,30 @@ ; RUN: opt -module-summary %s -o %t1.bc ; RUN: llvm-lto2 run %t1.bc -o %t.o \ ; RUN: -r=%t1.bc,_tinkywinky,pxl \ -; RUN: -use-new-pm +; RUN: -debug-pass-manager \ +; RUN: -use-new-pm 2>&1 | FileCheck --check-prefix=NEWPM %s + +; RUN: llvm-lto -thinlto-action=run -exported-symbol tinkywinky \ +; RUN: -use-new-pm \ +; RUN: -debug-pass-manager \ +; RUN: %t1.bc 2>&1 | FileCheck --check-prefix=NEWPM %s + +; RUN: llvm-lto -thinlto-action=run -exported-symbol tinkywinky \ +; RUN: -use-new-pm=false \ +; RUN: -debug-pass-manager \ +; RUN: -debug-pass=Structure \ +; RUN: %t1.bc 2>&1 | FileCheck --check-prefix=LEGACYPM %s + +; Check that the selected pass manager is used for middle-end optimizations by +; checking the debug output for IPSCCP. + +; NEWPM-NOT: Interprocedural Sparse Conditional Constant Propagation +; NEWPM: Running pass: IPSCCPPass on [module] +; NEWPM-NOT: Interprocedural Sparse Conditional Constant Propagation + +; LEGACYPM-NOT: IPSCCPPass +; LEGACYPM: Interprocedural Sparse Conditional Constant Propagation +; LEGACYPM-NOT: IPSCCPPass target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -227,6 +227,10 @@ cl::desc("Run LTO passes using the new pass manager"), cl::init(LLVM_ENABLE_NEW_PASS_MANAGER), cl::Hidden); +static cl::opt + DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden, + cl::desc("Print pass management debugging information")); + namespace { struct ModuleInfo { @@ -557,6 +561,8 @@ ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles); ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes); ThinGenerator.setFreestanding(EnableFreestanding); + ThinGenerator.setUseNewPM(UseNewPM); + ThinGenerator.setDebugPassManager(DebugPassManager); // Add all the exported symbols to the table of symbols to preserve. for (unsigned i = 0; i < ExportedSymbols.size(); ++i)