blob: 089c926189c83d9f41a276e7883c05f869416d7b [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "BPF.h"
#include "BPFAsmPrinter.h"
#include "BPFSubtarget.h"
#include "BPFTargetMachine.h"
#include "llvm/CodeGen/AtomicExpand.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Passes/CodeGenPassBuilder.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Error.h"
#include "llvm/Target/CGPassBuilderOption.h"
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
#include "llvm/Transforms/Utils/SimplifyCFGOptions.h"
using namespace llvm;
extern cl::opt<bool> DisableMIPeephole;
namespace {
class BPFCodeGenPassBuilder
: public CodeGenPassBuilder<BPFCodeGenPassBuilder, BPFTargetMachine> {
using Base = CodeGenPassBuilder<BPFCodeGenPassBuilder, BPFTargetMachine>;
public:
explicit BPFCodeGenPassBuilder(BPFTargetMachine &TM,
const CGPassBuilderOption &Opts,
PassInstrumentationCallbacks *PIC)
: CodeGenPassBuilder(TM, Opts, PIC) {}
void addIRPasses(PassManagerWrapper &PMW) const;
Error addInstSelector(PassManagerWrapper &PMW) const;
void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
void addPreEmitPass(PassManagerWrapper &PMW) const;
void addAsmPrinterBegin(PassManagerWrapper &PMW) const;
void addAsmPrinter(PassManagerWrapper &PMW) const;
void addAsmPrinterEnd(PassManagerWrapper &PMW) const;
};
void BPFCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
addFunctionPass(AtomicExpandPass(TM), PMW);
flushFPMsToMPM(PMW);
addModulePass(BPFCheckAndAdjustIRPass(), PMW);
Base::addIRPasses(PMW);
}
Error BPFCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
addMachineFunctionPass(BPFISelDAGToDAGPass(TM), PMW);
return Error::success();
}
void BPFCodeGenPassBuilder::addMachineSSAOptimization(
PassManagerWrapper &PMW) const {
addMachineFunctionPass(BPFMISimplifyPatchablePass(), PMW);
Base::addMachineSSAOptimization(PMW);
const BPFSubtarget *Subtarget = TM.getSubtargetImpl();
if (!DisableMIPeephole) {
if (Subtarget->getHasAlu32())
addMachineFunctionPass(BPFMIPeepholePass(), PMW);
}
}
void BPFCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) const {
addMachineFunctionPass(BPFMIPreEmitCheckingPass(), PMW);
if (!DisableMIPeephole) {
addMachineFunctionPass(BPFMIExpandStackArgPseudosPass(), PMW);
addMachineFunctionPass(BPFMIPreEmitPeepholePass(), PMW);
}
}
void BPFCodeGenPassBuilder::addAsmPrinterBegin(PassManagerWrapper &PMW) const {
addModulePass(BPFAsmPrinterBeginPass(), PMW, /*Force=*/true);
}
void BPFCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) const {
addMachineFunctionPass(BPFAsmPrinterPass(), PMW);
}
void BPFCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) const {
addModulePass(BPFAsmPrinterEndPass(), PMW);
}
} // namespace
static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) {
return PassBuilder::parseSinglePassOption(Params, "allow-partial",
"BPFPreserveStaticOffsetPass");
}
void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
#define GET_PASS_REGISTRY "BPFPassRegistry.def"
#include "llvm/Passes/TargetPassRegistry.inc"
// TODO(boomanaiden154): Move this into the base CodeGenPassBuilder once all
// targets that currently implement it have a ported asm-printer pass.
if (PIC) {
PIC->addClassToPassName(BPFAsmPrinterBeginPass::name(),
"bpf-asm-printer-begin");
PIC->addClassToPassName(BPFAsmPrinterPass::name(), "bpf-asmprinter");
PIC->addClassToPassName(BPFAsmPrinterEndPass::name(),
"bpf-asm-printer-end");
}
PB.registerPipelineStartEPCallback(
[=](ModulePassManager &MPM, OptimizationLevel) {
FunctionPassManager FPM;
FPM.addPass(BPFPreserveStaticOffsetPass(true));
FPM.addPass(BPFAbstractMemberAccessPass(this));
FPM.addPass(BPFPreserveDITypePass());
FPM.addPass(BPFIRPeepholePass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
});
PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM,
OptimizationLevel Level) {
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true)));
FPM.addPass(BPFASpaceCastSimplifyPass());
});
PB.registerScalarOptimizerLateEPCallback(
[=](FunctionPassManager &FPM, OptimizationLevel Level) {
// Run this after loop unrolling but before
// SimplifyCFGPass(... .sinkCommonInsts(true))
FPM.addPass(BPFPreserveStaticOffsetPass(false));
});
PB.registerPipelineEarlySimplificationEPCallback(
[=](ModulePassManager &MPM, OptimizationLevel, ThinOrFullLTOPhase) {
MPM.addPass(BPFAdjustOptPass());
});
}
Error BPFTargetMachine::buildCodeGenPipeline(
ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
const CGPassBuilderOption &Opt, MCContext &Ctx,
PassInstrumentationCallbacks *PIC) {
auto CGPB = BPFCodeGenPassBuilder(*this, Opt, PIC);
return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
}