1 | //===-- BPFTargetMachine.cpp - Define TargetMachine for BPF ---------------===// |
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 | // Implements the info about BPF target spec. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "BPFTargetMachine.h" |
14 | #include "BPF.h" |
15 | #include "BPFTargetTransformInfo.h" |
16 | #include "MCTargetDesc/BPFMCAsmInfo.h" |
17 | #include "TargetInfo/BPFTargetInfo.h" |
18 | #include "llvm/CodeGen/GlobalISel/IRTranslator.h" |
19 | #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" |
20 | #include "llvm/CodeGen/GlobalISel/Legalizer.h" |
21 | #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" |
22 | #include "llvm/CodeGen/Passes.h" |
23 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
24 | #include "llvm/CodeGen/TargetPassConfig.h" |
25 | #include "llvm/IR/PassManager.h" |
26 | #include "llvm/InitializePasses.h" |
27 | #include "llvm/MC/TargetRegistry.h" |
28 | #include "llvm/Passes/PassBuilder.h" |
29 | #include "llvm/Support/FormattedStream.h" |
30 | #include "llvm/Target/TargetOptions.h" |
31 | #include "llvm/Transforms/Scalar.h" |
32 | #include "llvm/Transforms/Scalar/SimplifyCFG.h" |
33 | #include "llvm/Transforms/Utils/SimplifyCFGOptions.h" |
34 | #include <optional> |
35 | using namespace llvm; |
36 | |
37 | static cl:: |
38 | opt<bool> DisableMIPeephole("disable-bpf-peephole" , cl::Hidden, |
39 | cl::desc("Disable machine peepholes for BPF" )); |
40 | |
41 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() { |
42 | // Register the target. |
43 | RegisterTargetMachine<BPFTargetMachine> X(getTheBPFleTarget()); |
44 | RegisterTargetMachine<BPFTargetMachine> Y(getTheBPFbeTarget()); |
45 | RegisterTargetMachine<BPFTargetMachine> Z(getTheBPFTarget()); |
46 | |
47 | PassRegistry &PR = *PassRegistry::getPassRegistry(); |
48 | initializeGlobalISel(PR); |
49 | initializeBPFCheckAndAdjustIRPass(PR); |
50 | initializeBPFMIPeepholePass(PR); |
51 | initializeBPFDAGToDAGISelLegacyPass(PR); |
52 | } |
53 | |
54 | // DataLayout: little or big endian |
55 | static std::string computeDataLayout(const Triple &TT) { |
56 | if (TT.getArch() == Triple::bpfeb) |
57 | return "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128" ; |
58 | else |
59 | return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" ; |
60 | } |
61 | |
62 | static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) { |
63 | return RM.value_or(u: Reloc::PIC_); |
64 | } |
65 | |
66 | BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT, |
67 | StringRef CPU, StringRef FS, |
68 | const TargetOptions &Options, |
69 | std::optional<Reloc::Model> RM, |
70 | std::optional<CodeModel::Model> CM, |
71 | CodeGenOptLevel OL, bool JIT) |
72 | : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, |
73 | getEffectiveRelocModel(RM), |
74 | getEffectiveCodeModel(CM, Default: CodeModel::Small), OL), |
75 | TLOF(std::make_unique<TargetLoweringObjectFileELF>()), |
76 | Subtarget(TT, std::string(CPU), std::string(FS), *this) { |
77 | initAsmInfo(); |
78 | |
79 | BPFMCAsmInfo *MAI = |
80 | static_cast<BPFMCAsmInfo *>(const_cast<MCAsmInfo *>(AsmInfo.get())); |
81 | MAI->setDwarfUsesRelocationsAcrossSections(!Subtarget.getUseDwarfRIS()); |
82 | } |
83 | |
84 | namespace { |
85 | // BPF Code Generator Pass Configuration Options. |
86 | class BPFPassConfig : public TargetPassConfig { |
87 | public: |
88 | BPFPassConfig(BPFTargetMachine &TM, PassManagerBase &PM) |
89 | : TargetPassConfig(TM, PM) {} |
90 | |
91 | BPFTargetMachine &getBPFTargetMachine() const { |
92 | return getTM<BPFTargetMachine>(); |
93 | } |
94 | |
95 | void addIRPasses() override; |
96 | bool addInstSelector() override; |
97 | void addMachineSSAOptimization() override; |
98 | void addPreEmitPass() override; |
99 | |
100 | bool addIRTranslator() override; |
101 | bool addLegalizeMachineIR() override; |
102 | bool addRegBankSelect() override; |
103 | bool addGlobalInstructionSelect() override; |
104 | }; |
105 | } |
106 | |
107 | TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) { |
108 | return new BPFPassConfig(*this, PM); |
109 | } |
110 | |
111 | static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) { |
112 | return PassBuilder::parseSinglePassOption(Params, OptionName: "allow-partial" , |
113 | PassName: "BPFPreserveStaticOffsetPass" ); |
114 | } |
115 | |
116 | void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { |
117 | #define GET_PASS_REGISTRY "BPFPassRegistry.def" |
118 | #include "llvm/Passes/TargetPassRegistry.inc" |
119 | |
120 | PB.registerPipelineStartEPCallback( |
121 | C: [=](ModulePassManager &MPM, OptimizationLevel) { |
122 | FunctionPassManager FPM; |
123 | FPM.addPass(Pass: BPFPreserveStaticOffsetPass(true)); |
124 | FPM.addPass(Pass: BPFAbstractMemberAccessPass(this)); |
125 | FPM.addPass(Pass: BPFPreserveDITypePass()); |
126 | FPM.addPass(Pass: BPFIRPeepholePass()); |
127 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM))); |
128 | }); |
129 | PB.registerPeepholeEPCallback(C: [=](FunctionPassManager &FPM, |
130 | OptimizationLevel Level) { |
131 | FPM.addPass(Pass: SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(B: true))); |
132 | FPM.addPass(Pass: BPFASpaceCastSimplifyPass()); |
133 | }); |
134 | PB.registerScalarOptimizerLateEPCallback( |
135 | C: [=](FunctionPassManager &FPM, OptimizationLevel Level) { |
136 | // Run this after loop unrolling but before |
137 | // SimplifyCFGPass(... .sinkCommonInsts(true)) |
138 | FPM.addPass(Pass: BPFPreserveStaticOffsetPass(false)); |
139 | }); |
140 | PB.registerPipelineEarlySimplificationEPCallback( |
141 | C: [=](ModulePassManager &MPM, OptimizationLevel) { |
142 | MPM.addPass(Pass: BPFAdjustOptPass()); |
143 | }); |
144 | } |
145 | |
146 | void BPFPassConfig::addIRPasses() { |
147 | addPass(P: createAtomicExpandLegacyPass()); |
148 | addPass(P: createBPFCheckAndAdjustIR()); |
149 | |
150 | TargetPassConfig::addIRPasses(); |
151 | } |
152 | |
153 | TargetTransformInfo |
154 | BPFTargetMachine::getTargetTransformInfo(const Function &F) const { |
155 | return TargetTransformInfo(BPFTTIImpl(this, F)); |
156 | } |
157 | |
158 | // Install an instruction selector pass using |
159 | // the ISelDag to gen BPF code. |
160 | bool BPFPassConfig::addInstSelector() { |
161 | addPass(P: createBPFISelDag(TM&: getBPFTargetMachine())); |
162 | |
163 | return false; |
164 | } |
165 | |
166 | void BPFPassConfig::addMachineSSAOptimization() { |
167 | addPass(P: createBPFMISimplifyPatchablePass()); |
168 | |
169 | // The default implementation must be called first as we want eBPF |
170 | // Peephole ran at last. |
171 | TargetPassConfig::addMachineSSAOptimization(); |
172 | |
173 | const BPFSubtarget *Subtarget = getBPFTargetMachine().getSubtargetImpl(); |
174 | if (!DisableMIPeephole) { |
175 | if (Subtarget->getHasAlu32()) |
176 | addPass(P: createBPFMIPeepholePass()); |
177 | } |
178 | } |
179 | |
180 | void BPFPassConfig::addPreEmitPass() { |
181 | addPass(P: createBPFMIPreEmitCheckingPass()); |
182 | if (getOptLevel() != CodeGenOptLevel::None) |
183 | if (!DisableMIPeephole) |
184 | addPass(P: createBPFMIPreEmitPeepholePass()); |
185 | } |
186 | |
187 | bool BPFPassConfig::addIRTranslator() { |
188 | addPass(P: new IRTranslator()); |
189 | return false; |
190 | } |
191 | |
192 | bool BPFPassConfig::addLegalizeMachineIR() { |
193 | addPass(P: new Legalizer()); |
194 | return false; |
195 | } |
196 | |
197 | bool BPFPassConfig::addRegBankSelect() { |
198 | addPass(P: new RegBankSelect()); |
199 | return false; |
200 | } |
201 | |
202 | bool BPFPassConfig::addGlobalInstructionSelect() { |
203 | addPass(P: new InstructionSelect(getOptLevel())); |
204 | return false; |
205 | } |
206 | |