summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/LTO/Config.h7
-rw-r--r--llvm/lib/LTO/LLVMBuild.txt1
-rw-r--r--llvm/lib/LTO/LTOBackend.cpp46
-rw-r--r--llvm/test/tools/llvm-lto2/X86/pipeline.ll24
-rw-r--r--llvm/tools/llvm-lto2/llvm-lto2.cpp7
5 files changed, 84 insertions, 1 deletions
diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index bb6c145bc12..3d19ab60497 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -78,6 +78,11 @@ struct Config {
/// 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 @@ struct Config {
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 @@ struct Config {
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);
diff --git a/llvm/lib/LTO/LLVMBuild.txt b/llvm/lib/LTO/LLVMBuild.txt
index f6bcaf558bc..b940362e523 100644
--- a/llvm/lib/LTO/LLVMBuild.txt
+++ b/llvm/lib/LTO/LLVMBuild.txt
@@ -31,6 +31,7 @@ required_libraries =
MC
ObjCARC
Object
+ Passes
Scalar
Support
Target
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 3ed52ba575d..75f3182ee1d 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/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 @@ createTargetMachine(Config &Conf, StringRef TheTriple,
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 @@ static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
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);
}
diff --git a/llvm/test/tools/llvm-lto2/X86/pipeline.ll b/llvm/test/tools/llvm-lto2/X86/pipeline.ll
new file mode 100644
index 00000000000..3cdf64e8999
--- /dev/null
+++ b/llvm/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
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 06c3d0406cf..a2cc54ad7da 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -35,6 +35,10 @@ static cl::opt<std::string> OutputFilename("o", cl::Required,
static cl::opt<std::string> CacheDir("cache-dir", cl::desc("Cache Directory"),
cl::value_desc("directory"));
+static cl::opt<std::string> OptPipeline("opt-pipeline",
+ cl::desc("Optimizer Pipeline"),
+ cl::value_desc("pipeline"));
+
static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temporary files"));
static cl::opt<bool>
@@ -148,6 +152,9 @@ int main(int argc, char **argv) {
check(Conf.addSaveTemps(OutputFilename + "."),
"Config::addSaveTemps failed");
+ // Run a custom pipeline, if asked for.
+ Conf.OptPipeline = OptPipeline;
+
ThinBackend Backend;
if (ThinLTODistributedIndexes)
Backend = createWriteIndexesThinBackend("", "", true, "");
OpenPOWER on IntegriCloud