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