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