1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "BPF.h"
10#include "BPFAsmPrinter.h"
11#include "BPFSubtarget.h"
12#include "BPFTargetMachine.h"
13#include "llvm/CodeGen/AtomicExpand.h"
14#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
15#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
16#include "llvm/CodeGen/GlobalISel/Legalizer.h"
17#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
18#include "llvm/IR/PassInstrumentation.h"
19#include "llvm/MC/MCStreamer.h"
20#include "llvm/Passes/CodeGenPassBuilder.h"
21#include "llvm/Passes/PassBuilder.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Target/CGPassBuilderOption.h"
24#include "llvm/Transforms/Scalar/SimplifyCFG.h"
25#include "llvm/Transforms/Utils/SimplifyCFGOptions.h"
26
27using namespace llvm;
28
29extern cl::opt<bool> DisableMIPeephole;
30
31namespace {
32
33class BPFCodeGenPassBuilder : public CodeGenPassBuilder {
34 using Base = CodeGenPassBuilder;
35
36 BPFTargetMachine &getTM() const {
37 return static_cast<BPFTargetMachine &>(TM);
38 }
39
40public:
41 explicit BPFCodeGenPassBuilder(BPFTargetMachine &TM,
42 const CGPassBuilderOption &Opts,
43 PassInstrumentationCallbacks *PIC)
44 : CodeGenPassBuilder(TM, Opts, PIC) {}
45
46 void addIRPasses(PassManagerWrapper &PMW) override;
47
48 Error addInstSelector(PassManagerWrapper &PMW) override;
49
50 Error addIRTranslator(PassManagerWrapper &PMW) override;
51 Error addLegalizeMachineIR(PassManagerWrapper &PMW) override;
52 Error addRegBankSelect(PassManagerWrapper &PMW) override;
53 Error addGlobalInstructionSelect(PassManagerWrapper &PMW) override;
54
55 void addMachineSSAOptimization(PassManagerWrapper &PMW) override;
56 void addPreEmitPass(PassManagerWrapper &PMW) override;
57 void addAsmPrinterBegin(PassManagerWrapper &PMW) override;
58 void addAsmPrinter(PassManagerWrapper &PMW) override;
59 void addAsmPrinterEnd(PassManagerWrapper &PMW) override;
60};
61
62void BPFCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
63 addFunctionPass(Pass: AtomicExpandPass(TM), PMW);
64 flushFPMsToMPM(PMW);
65 addModulePass(Pass: BPFCheckAndAdjustIRPass(), PMW);
66
67 Base::addIRPasses(PMW);
68}
69
70Error BPFCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) {
71 addMachineFunctionPass(Pass: BPFISelDAGToDAGPass(getTM()), PMW);
72 return Error::success();
73}
74
75Error BPFCodeGenPassBuilder::addIRTranslator(PassManagerWrapper &PMW) {
76 addMachineFunctionPass(Pass: IRTranslatorPass(getOptLevel()), PMW);
77 return Error::success();
78}
79
80Error BPFCodeGenPassBuilder::addLegalizeMachineIR(PassManagerWrapper &PMW) {
81 addMachineFunctionPass(Pass: LegalizerPass(), PMW);
82 return Error::success();
83}
84
85Error BPFCodeGenPassBuilder::addRegBankSelect(PassManagerWrapper &PMW) {
86 addMachineFunctionPass(Pass: RegBankSelectPass(), PMW);
87 return Error::success();
88}
89
90Error BPFCodeGenPassBuilder::addGlobalInstructionSelect(
91 PassManagerWrapper &PMW) {
92 addMachineFunctionPass(Pass: InstructionSelectPass(), PMW);
93 return Error::success();
94}
95
96void BPFCodeGenPassBuilder::addMachineSSAOptimization(PassManagerWrapper &PMW) {
97 addMachineFunctionPass(Pass: BPFMISimplifyPatchablePass(), PMW);
98
99 Base::addMachineSSAOptimization(PMW);
100
101 const BPFSubtarget *Subtarget = getTM().getSubtargetImpl();
102 if (!DisableMIPeephole) {
103 if (Subtarget->getHasAlu32())
104 addMachineFunctionPass(Pass: BPFMIPeepholePass(), PMW);
105 }
106}
107
108void BPFCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) {
109 addMachineFunctionPass(Pass: BPFMIPreEmitCheckingPass(), PMW);
110 if (!DisableMIPeephole) {
111 addMachineFunctionPass(Pass: BPFMIExpandStackArgPseudosPass(), PMW);
112 addMachineFunctionPass(Pass: BPFMIPreEmitPeepholePass(), PMW);
113 }
114}
115
116void BPFCodeGenPassBuilder::addAsmPrinterBegin(PassManagerWrapper &PMW) {
117 addModulePass(Pass: BPFAsmPrinterBeginPass(), PMW, /*Force=*/true);
118}
119
120void BPFCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) {
121 addMachineFunctionPass(Pass: BPFAsmPrinterPass(), PMW);
122}
123
124void BPFCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) {
125 addModulePass(Pass: BPFAsmPrinterEndPass(), PMW);
126}
127
128} // namespace
129
130static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) {
131 return PassBuilder::parseSinglePassOption(Params, OptionName: "allow-partial",
132 PassName: "BPFPreserveStaticOffsetPass");
133}
134
135void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
136#define GET_PASS_REGISTRY "BPFPassRegistry.def"
137#include "llvm/Passes/TargetPassRegistry.inc"
138
139 PB.registerPipelineStartEPCallback(
140 C: [=](ModulePassManager &MPM, OptimizationLevel) {
141 FunctionPassManager FPM;
142 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(true));
143 FPM.addPass(Pass: BPFAbstractMemberAccessPass(this));
144 FPM.addPass(Pass: BPFPreserveDITypePass());
145 FPM.addPass(Pass: BPFIRPeepholePass());
146 MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM)));
147 });
148 PB.registerPeepholeEPCallback(C: [=](FunctionPassManager &FPM,
149 OptimizationLevel Level) {
150 FPM.addPass(Pass: SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(B: true)));
151 FPM.addPass(Pass: BPFASpaceCastSimplifyPass());
152 });
153 PB.registerScalarOptimizerLateEPCallback(
154 C: [=](FunctionPassManager &FPM, OptimizationLevel Level) {
155 // Run this after loop unrolling but before
156 // SimplifyCFGPass(... .sinkCommonInsts(true))
157 FPM.addPass(Pass: BPFPreserveStaticOffsetPass(false));
158 });
159 PB.registerPipelineEarlySimplificationEPCallback(
160 C: [=](ModulePassManager &MPM, OptimizationLevel, ThinOrFullLTOPhase) {
161 MPM.addPass(Pass: BPFAdjustOptPass());
162 });
163}
164
165Error BPFTargetMachine::buildCodeGenPipeline(
166 ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
167 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
168 const CGPassBuilderOption &Opt, MCContext &Ctx,
169 PassInstrumentationCallbacks *PIC) {
170 auto CGPB = BPFCodeGenPassBuilder(*this, Opt, PIC);
171 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
172}
173