2024-01-24 09:27:25 +08:00
|
|
|
//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
///
|
|
|
|
/// This file is just a split of the code that logically belongs in llc.cpp but
|
|
|
|
/// that includes the new pass manager headers.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "NewPMDriver.h"
|
|
|
|
#include "llvm/Analysis/CGSCCPassManager.h"
|
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
|
|
#include "llvm/CodeGen/CommandFlags.h"
|
2024-01-25 17:24:05 +08:00
|
|
|
#include "llvm/CodeGen/FreeMachineFunction.h"
|
2024-01-24 09:27:25 +08:00
|
|
|
#include "llvm/CodeGen/MIRParser/MIRParser.h"
|
|
|
|
#include "llvm/CodeGen/MIRPrinter.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachinePassManager.h"
|
|
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/PassManager.h"
|
|
|
|
#include "llvm/IR/Verifier.h"
|
|
|
|
#include "llvm/IRReader/IRReader.h"
|
2024-01-24 11:29:18 +08:00
|
|
|
#include "llvm/Passes/CodeGenPassBuilder.h" // TODO: Include pass headers properly.
|
2024-01-24 09:27:25 +08:00
|
|
|
#include "llvm/Passes/PassBuilder.h"
|
|
|
|
#include "llvm/Passes/StandardInstrumentations.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/FormattedStream.h"
|
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
|
|
|
#include "llvm/Support/WithColor.h"
|
|
|
|
#include "llvm/Target/CGPassBuilderOption.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
|
|
|
#include "llvm/Transforms/Utils/Cloning.h"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
extern cl::opt<bool> PrintPipelinePasses;
|
|
|
|
} // namespace llvm
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
RegAlloc("regalloc-npm",
|
|
|
|
cl::desc("Register allocator to use for new pass manager"),
|
|
|
|
cl::Hidden, cl::init("default"));
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
DebugPM("debug-pass-manager", cl::Hidden,
|
|
|
|
cl::desc("Print pass management debugging information"));
|
|
|
|
|
|
|
|
bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
|
|
|
|
DiagnosticHandler::handleDiagnostics(DI);
|
|
|
|
if (DI.getKind() == llvm::DK_SrcMgr) {
|
|
|
|
const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
|
|
|
|
const SMDiagnostic &SMD = DISM.getSMDiag();
|
|
|
|
|
|
|
|
SMD.print(nullptr, errs());
|
|
|
|
|
|
|
|
// For testing purposes, we print the LocCookie here.
|
|
|
|
if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
|
|
|
|
WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
|
|
|
|
if (!Remark->isEnabled())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
DiagnosticPrinterRawOStream DP(errs());
|
|
|
|
errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
|
|
|
|
DI.print(DP);
|
|
|
|
errs() << "\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static llvm::ExitOnError ExitOnErr;
|
|
|
|
|
|
|
|
static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M,
|
|
|
|
LLVMContext &Context, SmallString<0> &Buffer,
|
|
|
|
ModulePassManager *MPM, ModuleAnalysisManager *MAM,
|
|
|
|
MachineFunctionPassManager &MFPM,
|
|
|
|
MachineFunctionAnalysisManager &MFAM) {
|
|
|
|
assert(M && "invalid input module!");
|
|
|
|
|
|
|
|
// Before executing passes, print the final values of the LLVM options.
|
|
|
|
cl::PrintOptionValues();
|
|
|
|
|
|
|
|
if (MPM) {
|
|
|
|
assert(MAM && "expect a ModuleAnalysisManager!");
|
|
|
|
MPM->run(*M, *MAM);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExitOnErr(MFPM.run(*M, MFAM));
|
|
|
|
|
|
|
|
if (Context.getDiagHandlerPtr()->HasErrors)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
if (BOS)
|
|
|
|
Out->os() << Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
int llvm::compileModuleWithNewPM(
|
|
|
|
StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
|
|
|
|
std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
|
|
|
|
std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
|
|
|
|
const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline,
|
|
|
|
CodeGenFileType FileType) {
|
|
|
|
|
|
|
|
if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
|
|
|
|
WithColor::warning(errs(), Arg0)
|
|
|
|
<< "--passes cannot be used with "
|
|
|
|
<< TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
|
|
|
|
|
|
|
|
raw_pwrite_stream *OS = &Out->os();
|
|
|
|
|
|
|
|
// Manually do the buffering rather than using buffer_ostream,
|
|
|
|
// so we can memcmp the contents in CompileTwice mode in future.
|
|
|
|
SmallString<0> Buffer;
|
|
|
|
std::unique_ptr<raw_svector_ostream> BOS;
|
|
|
|
if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
|
|
|
|
!Out->os().supportsSeeking())) {
|
|
|
|
BOS = std::make_unique<raw_svector_ostream>(Buffer);
|
|
|
|
OS = BOS.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch options from TargetPassConfig
|
|
|
|
CGPassBuilderOption Opt = getCGPassBuilderOption();
|
|
|
|
Opt.DisableVerify = NoVerify;
|
|
|
|
Opt.DebugPM = DebugPM;
|
|
|
|
Opt.RegAlloc = RegAlloc;
|
|
|
|
|
2024-02-07 10:15:43 -07:00
|
|
|
MachineModuleInfo MMI(&LLVMTM);
|
|
|
|
|
2024-01-24 09:27:25 +08:00
|
|
|
PassInstrumentationCallbacks PIC;
|
|
|
|
StandardInstrumentations SI(Context, Opt.DebugPM);
|
|
|
|
SI.registerCallbacks(PIC);
|
|
|
|
registerCodeGenCallback(PIC, LLVMTM);
|
|
|
|
|
|
|
|
LoopAnalysisManager LAM;
|
|
|
|
FunctionAnalysisManager FAM;
|
|
|
|
CGSCCAnalysisManager CGAM;
|
|
|
|
ModuleAnalysisManager MAM;
|
|
|
|
PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
|
|
|
|
PB.registerModuleAnalyses(MAM);
|
|
|
|
PB.registerCGSCCAnalyses(CGAM);
|
|
|
|
PB.registerFunctionAnalyses(FAM);
|
|
|
|
PB.registerLoopAnalyses(LAM);
|
|
|
|
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
|
|
|
|
|
|
|
|
FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
|
2024-02-07 10:15:43 -07:00
|
|
|
MAM.registerPass([&] { return MachineModuleAnalysis(MMI); });
|
2024-01-24 09:27:25 +08:00
|
|
|
|
|
|
|
MachineFunctionAnalysisManager MFAM(FAM, MAM);
|
|
|
|
|
2024-02-03 16:52:54 +08:00
|
|
|
ModulePassManager MPM;
|
|
|
|
MachineFunctionPassManager MFPM;
|
|
|
|
|
2024-01-24 09:27:25 +08:00
|
|
|
if (!PassPipeline.empty()) {
|
|
|
|
// Construct a custom pass pipeline that starts after instruction
|
|
|
|
// selection.
|
|
|
|
|
|
|
|
if (!MIR) {
|
|
|
|
WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline));
|
2024-02-03 16:52:54 +08:00
|
|
|
MPM.addPass(PrintMIRPreparePass(*OS));
|
2024-01-24 09:27:25 +08:00
|
|
|
MFPM.addPass(PrintMIRPass(*OS));
|
|
|
|
MFPM.addPass(FreeMachineFunctionPass());
|
|
|
|
|
2024-02-07 10:15:43 -07:00
|
|
|
auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M).getMMI();
|
2024-01-24 09:27:25 +08:00
|
|
|
if (MIR->parseMachineFunctions(*M, MMI))
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
|
|
|
|
DwoOut ? &DwoOut->os() : nullptr,
|
|
|
|
FileType, Opt, &PIC));
|
|
|
|
|
|
|
|
auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC);
|
|
|
|
assert(StartStopInfo && "Expect StartStopInfo!");
|
|
|
|
|
|
|
|
if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) {
|
|
|
|
MFPM.addPass(PrintMIRPass(*OS));
|
|
|
|
MFPM.addPass(FreeMachineFunctionPass());
|
|
|
|
}
|
2024-02-07 10:16:47 -07:00
|
|
|
}
|
2024-01-24 09:27:25 +08:00
|
|
|
|
2024-02-07 10:16:47 -07:00
|
|
|
if (PrintPipelinePasses) {
|
|
|
|
std::string IRPipeline;
|
|
|
|
raw_string_ostream IRSOS(IRPipeline);
|
|
|
|
MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) {
|
|
|
|
auto PassName = PIC.getPassNameForClassName(ClassName);
|
|
|
|
return PassName.empty() ? ClassName : PassName;
|
|
|
|
});
|
|
|
|
outs() << "IR pipeline: " << IRPipeline << '\n';
|
|
|
|
|
|
|
|
std::string MIRPipeline;
|
|
|
|
raw_string_ostream MIRSOS(MIRPipeline);
|
|
|
|
MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) {
|
|
|
|
auto PassName = PIC.getPassNameForClassName(ClassName);
|
|
|
|
return PassName.empty() ? ClassName : PassName;
|
|
|
|
});
|
|
|
|
outs() << "MIR pipeline: " << MIRPipeline << '\n';
|
|
|
|
return 0;
|
2024-01-24 09:27:25 +08:00
|
|
|
}
|
|
|
|
|
2024-02-07 10:16:47 -07:00
|
|
|
RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM, MFPM,
|
|
|
|
MFAM);
|
|
|
|
|
2024-01-24 09:27:25 +08:00
|
|
|
// Declare success.
|
|
|
|
Out->keep();
|
|
|
|
if (DwoOut)
|
|
|
|
DwoOut->keep();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|