Move swift-llvm-opt over to use the new pass manager

rdar://112424659
This commit is contained in:
Arnold Schwaighofer
2023-08-04 06:42:24 -07:00
parent 7558ef1aeb
commit 597f8d9e99
11 changed files with 777 additions and 829 deletions

View File

@@ -42,10 +42,12 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRPrinter/IRPrintingPasses.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
@@ -64,10 +66,7 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
// TODO: Replace pass manager:
// Removed in: d623b2f95fd559901f008a0588dddd0949a8db01
/* #include "llvm/Transforms/IPO/PassManagerBuilder.h" */
#include "llvm/Transforms/Scalar/LoopPassManager.h"
using namespace swift;
@@ -78,23 +77,9 @@ static llvm::codegen::RegisterCodeGenFlags CGF;
//===----------------------------------------------------------------------===//
struct SwiftLLVMOptOptions {
// The OptimizationList is automatically populated with registered passes by the
// PassNameParser.
//
llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser>
PassList = llvm::cl::list<const llvm::PassInfo *, bool, llvm::PassNameParser>(llvm::cl::desc("Optimizations available:"));
llvm::cl::opt<bool>
Optimized = llvm::cl::opt<bool>("O", llvm::cl::desc("Optimization level O. Similar to swift -O"));
// TODO: I wanted to call this 'verify', but some other pass is using this
// option.
llvm::cl::opt<bool>
VerifyEach = llvm::cl::opt<bool>(
"verify-each",
llvm::cl::desc("Should we spend time verifying that the IR is well "
"formed"));
llvm::cl::opt<std::string>
TargetTriple = llvm::cl::opt<std::string>("mtriple",
llvm::cl::desc("Override target triple for module"));
@@ -120,6 +105,11 @@ struct SwiftLLVMOptOptions {
llvm::cl::value_desc("layout-string"), llvm::cl::init(""));
};
static llvm::cl::opt<std::string> PassPipeline(
"passes",
llvm::cl::desc(
"A textual description of the pass pipeline. To have analysis passes "
"available before a certain pass, add 'require<foo-analysis>'."));
//===----------------------------------------------------------------------===//
// Helper Methods
//===----------------------------------------------------------------------===//
@@ -151,71 +141,6 @@ getTargetMachine(llvm::Triple TheTriple, StringRef CPUStr,
llvm::codegen::getExplicitCodeModel(), GetCodeGenOptLevel(options));
}
static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) {
// For now just always dump assembly.
llvm::legacy::PassManager EmitPasses;
EmitPasses.add(createPrintModulePass(os));
EmitPasses.run(M);
}
static inline void addPass(llvm::legacy::PassManagerBase &PM, llvm::Pass *P,
const SwiftLLVMOptOptions &options) {
// Add the pass to the pass manager...
PM.add(P);
if (P->getPassID() == &SwiftAAWrapperPass::ID) {
PM.add(llvm::createExternalAAWrapperPass([](llvm::Pass &P, llvm::Function &,
llvm::AAResults &AAR) {
if (auto *WrapperPass = P.getAnalysisIfAvailable<SwiftAAWrapperPass>())
AAR.addAAResult(WrapperPass->getResult());
}));
}
// If we are verifying all of the intermediate steps, add the verifier...
if (options.VerifyEach)
PM.add(llvm::createVerifierPass());
}
static void runSpecificPasses(StringRef Binary, llvm::Module *M,
llvm::TargetMachine *TM,
llvm::Triple &ModuleTriple,
const SwiftLLVMOptOptions &options) {
llvm::legacy::PassManager Passes;
llvm::TargetLibraryInfoImpl TLII(ModuleTriple);
Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII));
const llvm::DataLayout &DL = M->getDataLayout();
if (DL.isDefault() && !options.DefaultDataLayout.empty()) {
M->setDataLayout(options.DefaultDataLayout);
}
// Add internal analysis passes from the target machine.
Passes.add(createTargetTransformInfoWrapperPass(
TM ? TM->getTargetIRAnalysis() : llvm::TargetIRAnalysis()));
if (TM) {
// FIXME: We should dyn_cast this when supported.
auto &LTM = static_cast<llvm::LLVMTargetMachine &>(*TM);
llvm::Pass *TPC = LTM.createPassConfig(Passes);
Passes.add(TPC);
}
for (const llvm::PassInfo *PassInfo : options.PassList) {
llvm::Pass *P = nullptr;
if (PassInfo->getNormalCtor())
P = PassInfo->getNormalCtor()();
else
llvm::errs() << Binary
<< ": cannot create pass: " << PassInfo->getPassName()
<< "\n";
if (P) {
addPass(Passes, P, options);
}
}
// Do it.
Passes.run(*M);
}
//===----------------------------------------------------------------------===//
// Main Implementation
//===----------------------------------------------------------------------===//
@@ -223,31 +148,6 @@ static void runSpecificPasses(StringRef Binary, llvm::Module *M,
int swift_llvm_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
INITIALIZE_LLVM();
// Initialize passes
llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
initializeCore(Registry);
initializeScalarOpts(Registry);
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
initializeTarget(Registry);
// For codegen passes, only passes that do IR to IR transformation are
// supported.
initializeCodeGenPreparePass(Registry);
initializeAtomicExpandPass(Registry);
initializeWinEHPreparePass(Registry);
initializeDwarfEHPrepareLegacyPassPass(Registry);
initializeSjLjEHPreparePass(Registry);
// Register Swift Only Passes.
initializeSwiftAAWrapperPassPass(Registry);
initializeSwiftARCOptPass(Registry);
initializeSwiftARCContractPass(Registry);
initializeInlineTreePrinterPass(Registry);
initializeLegacySwiftMergeFunctionsPass(Registry);
SwiftLLVMOptOptions options;
llvm::cl::ParseCommandLineOptions(argv.size(), argv.data(), "Swift LLVM optimizer\n");
@@ -317,9 +217,87 @@ int swift_llvm_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
// Then perform the optimizations.
performLLVMOptimizations(Opts, M.get(), TM.get(), &Out->os());
} else {
runSpecificPasses(argv[0], M.get(), TM.get(), ModuleTriple, options);
// Finally dump the output.
dumpOutput(*M, Out->os());
std::string Pipeline = PassPipeline;
llvm::TargetLibraryInfoImpl TLII(ModuleTriple);
if (TM)
TM->setPGOOption(std::nullopt);
llvm::LoopAnalysisManager LAM;
llvm::FunctionAnalysisManager FAM;
llvm::CGSCCAnalysisManager CGAM;
llvm::ModuleAnalysisManager MAM;
std::optional<llvm::PGOOptions> P = std::nullopt;
llvm::PassInstrumentationCallbacks PIC;
llvm::PrintPassOptions PrintPassOpts;
PrintPassOpts.Verbose = false;
PrintPassOpts.SkipAnalyses = false;
auto &Mod = *M;
llvm::StandardInstrumentations SI(M->getContext(), false, false, PrintPassOpts);
SI.registerCallbacks(PIC, &MAM);
llvm::PipelineTuningOptions PTO;
// LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized
// to false above so we shouldn't necessarily need to check whether or not the
// option has been enabled.
PTO.LoopUnrolling = true;
llvm::PassBuilder PB(TM.get(), PTO, P, &PIC);
PB.registerPipelineParsingCallback(
[ModuleTriple](StringRef Name, llvm::ModulePassManager &PM,
ArrayRef<llvm::PassBuilder::PipelineElement>) {
if (Name == "swift-merge-functions") {
if (ModuleTriple.isArm64e())
PM.addPass(SwiftMergeFunctionsPass(true, 0));
else
PM.addPass(SwiftMergeFunctionsPass(false, 0));
return true;
}
return false;
});
PB.registerPipelineParsingCallback(
[ModuleTriple](StringRef Name, llvm::FunctionPassManager &PM,
ArrayRef<llvm::PassBuilder::PipelineElement>) {
if (Name == "swift-llvm-arc-optimize") {
PM.addPass(SwiftARCOptPass());
return true;
}
return false;
});
PB.registerPipelineParsingCallback(
[ModuleTriple](StringRef Name, llvm::FunctionPassManager &PM,
ArrayRef<llvm::PassBuilder::PipelineElement>) {
if (Name == "swift-llvm-arc-contract") {
PM.addPass(SwiftARCContractPass());
return true;
}
return false;
});
auto AA = PB.buildDefaultAAPipeline();
AA.registerFunctionAnalysis<SwiftAA>();
// Register the AA manager first so that our version is the one used.
FAM.registerPass([&] { return std::move(AA); });
FAM.registerPass([&] { return SwiftAA(); });
// Register our TargetLibraryInfoImpl.
FAM.registerPass([&] { return llvm::TargetLibraryAnalysis(TLII); });
// 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);
llvm::ModulePassManager MPM;
if (!Pipeline.empty()) {
if (auto Err = PB.parsePassPipeline(MPM, Pipeline)) {
llvm::errs() << argv[0] << ": " << toString(std::move(Err)) << "\n";
return 1;
}
}
MPM.addPass(llvm::PrintModulePass(Out.get()->os(), "", false, false));
MPM.run(*M, MAM);
}
return 0;