mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Move swift-llvm-opt over to use the new pass manager
rdar://112424659
This commit is contained in:
@@ -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 <M = 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;
|
||||
|
||||
Reference in New Issue
Block a user