Index: llvm/trunk/include/llvm/LTO/Config.h =================================================================== --- llvm/trunk/include/llvm/LTO/Config.h +++ llvm/trunk/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: llvm/trunk/lib/LTO/LLVMBuild.txt =================================================================== --- llvm/trunk/lib/LTO/LLVMBuild.txt +++ llvm/trunk/lib/LTO/LLVMBuild.txt @@ -31,6 +31,7 @@ MC ObjCARC Object + Passes Scalar Support Target Index: llvm/trunk/lib/LTO/LTOBackend.cpp =================================================================== --- llvm/trunk/lib/LTO/LTOBackend.cpp +++ llvm/trunk/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" @@ -115,6 +121,41 @@ Conf.CodeModel, Conf.CGOptLevel)); } +static void runNewPMCustomPasses(Module &Mod, 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(Mod, MAM); +} + static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM, bool IsThinLto) { legacy::PassManager passes; @@ -140,7 +181,10 @@ bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod, bool IsThinLto) { Mod.setDataLayout(TM->createDataLayout()); - runOldPMPasses(Conf, Mod, TM, IsThinLto); + if (Conf.OptPipeline.empty()) + runOldPMPasses(Conf, Mod, TM, IsThinLto); + else + runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.DisableVerify); return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod); } Index: llvm/trunk/test/tools/llvm-lto2/X86/pipeline.ll =================================================================== --- llvm/trunk/test/tools/llvm-lto2/X86/pipeline.ll +++ llvm/trunk/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: llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp +++ llvm/trunk/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, "");