Index: include/llvm/LTO/Config.h =================================================================== --- include/llvm/LTO/Config.h +++ include/llvm/LTO/Config.h @@ -78,6 +78,11 @@ /// Disable entirely the optimizer, including importing for ThinLTO bool CodeGenOnly = false; + /// If this field is set, the set of passes run in the middle-end optimizer + /// will be the one specified by the string. Only works with the new pass + /// manager as the old one doesn't have this ability. + std::string OptPipeline; + /// Setting this field will replace target triples in input files with this /// triple. std::string OverrideTriple; @@ -164,6 +169,7 @@ RelocModel(std::move(X.RelocModel)), CodeModel(std::move(X.CodeModel)), CGOptLevel(std::move(X.CGOptLevel)), OptLevel(std::move(X.OptLevel)), DisableVerify(std::move(X.DisableVerify)), + OptPipeline(std::move(X.OptPipeline)), OverrideTriple(std::move(X.OverrideTriple)), DefaultTriple(std::move(X.DefaultTriple)), ShouldDiscardValueNames(std::move(X.ShouldDiscardValueNames)), @@ -187,6 +193,7 @@ CGOptLevel = std::move(X.CGOptLevel); OptLevel = std::move(X.OptLevel); DisableVerify = std::move(X.DisableVerify); + OptPipeline = std::move(X.OptPipeline); OverrideTriple = std::move(X.OverrideTriple); DefaultTriple = std::move(X.DefaultTriple); ShouldDiscardValueNames = std::move(X.ShouldDiscardValueNames); Index: lib/LTO/LLVMBuild.txt =================================================================== --- lib/LTO/LLVMBuild.txt +++ lib/LTO/LLVMBuild.txt @@ -31,6 +31,7 @@ MC ObjCARC Object + Passes Scalar Support Target Index: lib/LTO/LTOBackend.cpp =================================================================== --- lib/LTO/LTOBackend.cpp +++ lib/LTO/LTOBackend.cpp @@ -15,12 +15,18 @@ //===----------------------------------------------------------------------===// #include "llvm/LTO/LTOBackend.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/LoopPassManager.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" #include "llvm/LTO/LTO.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/TargetRegistry.h" @@ -114,6 +120,41 @@ C.CodeModel, C.CGOptLevel)); } +static void runNewPMCustomPasses(Module &M, TargetMachine *TM, + std::string PipelineDesc, + bool DisableVerify) { + PassBuilder PB(TM); + AAManager AA; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + + // 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; + + // Always verify the input. + MPM.addPass(VerifierPass()); + + // Now, add all the passes we've been requested to. + if (!PB.parsePassPipeline(MPM, PipelineDesc)) + report_fatal_error("unable to parse pass pipeline description: " + + PipelineDesc); + + if (!DisableVerify) + MPM.addPass(VerifierPass()); + MPM.run(M, MAM); +} + static void runOldPMPasses(Config &C, Module &M, TargetMachine *TM, bool IsThinLto) { legacy::PassManager passes; @@ -139,7 +180,10 @@ bool opt(Config &C, TargetMachine *TM, unsigned Task, Module &M, bool IsThinLto) { M.setDataLayout(TM->createDataLayout()); - runOldPMPasses(C, M, TM, IsThinLto); + if (C.OptPipeline.empty()) + runOldPMPasses(C, M, TM, IsThinLto); + else + runNewPMCustomPasses(M, TM, C.OptPipeline, C.DisableVerify); return !C.PostOptModuleHook || C.PostOptModuleHook(Task, M); } Index: test/tools/llvm-lto2/X86/pipeline.ll =================================================================== --- /dev/null +++ test/tools/llvm-lto2/X86/pipeline.ll @@ -0,0 +1,24 @@ +; RUN: llvm-as < %s > %t1.bc + +; Try a custom pipeline +; RUN: llvm-lto2 %t1.bc -o %t.o -save-temps \ +; RUN: -r %t1.bc,patatino,px -opt-pipeline loweratomic +; RUN: llvm-dis < %t.o.0.4.opt.bc | FileCheck %s --check-prefix=CUSTOM + +target triple = "x86_64-unknown-linux-gnu" + +define void @patatino() { + fence seq_cst + ret void +} + +; CUSTOM: define void @patatino() { +; CUSTOM-NEXT: ret void +; CUSTOM-NEXT: } + +; Check that invalid pipeline are caught as errors. +; RUN: not llvm-lto2 %t1.bc -o %t.o -save-temps \ +; RUN: -r %t1.bc,patatino,px -opt-pipeline foogoo 2>&1 | \ +; RUN: FileCheck %s --check-prefix=ERR + +; ERR: LLVM ERROR: unable to parse pass pipeline description: foogoo Index: tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- tools/llvm-lto2/llvm-lto2.cpp +++ tools/llvm-lto2/llvm-lto2.cpp @@ -35,6 +35,10 @@ static cl::opt CacheDir("cache-dir", cl::desc("Cache Directory"), cl::value_desc("directory")); +static cl::opt OptPipeline("opt-pipeline", + cl::desc("Optimizer Pipeline"), + cl::value_desc("pipeline")); + static cl::opt SaveTemps("save-temps", cl::desc("Save temporary files")); static cl::opt @@ -148,6 +152,9 @@ check(Conf.addSaveTemps(OutputFilename + "."), "Config::addSaveTemps failed"); + // Run a custom pipeline, if asked for. + Conf.OptPipeline = OptPipeline; + ThinBackend Backend; if (ThinLTODistributedIndexes) Backend = createWriteIndexesThinBackend("", "", true, "");