xref: /freebsd/contrib/llvm-project/llvm/lib/Target/BPF/BPFTargetMachine.cpp (revision e3f4a63af63bea70bc86b6c790b14aa5ee99fcd0)
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(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, 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, "allow-partial",
126                                             "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       [=](ModulePassManager &MPM, OptimizationLevel) {
135         FunctionPassManager FPM;
136         FPM.addPass(BPFPreserveStaticOffsetPass(true));
137         FPM.addPass(BPFAbstractMemberAccessPass(this));
138         FPM.addPass(BPFPreserveDITypePass());
139         FPM.addPass(BPFIRPeepholePass());
140         MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
141       });
142   PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM,
143                                     OptimizationLevel Level) {
144     FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true)));
145     FPM.addPass(BPFASpaceCastSimplifyPass());
146   });
147   PB.registerScalarOptimizerLateEPCallback(
148       [=](FunctionPassManager &FPM, OptimizationLevel Level) {
149         // Run this after loop unrolling but before
150         // SimplifyCFGPass(... .sinkCommonInsts(true))
151         FPM.addPass(BPFPreserveStaticOffsetPass(false));
152       });
153   PB.registerPipelineEarlySimplificationEPCallback(
154       [=](ModulePassManager &MPM, OptimizationLevel, ThinOrFullLTOPhase) {
155         MPM.addPass(BPFAdjustOptPass());
156       });
157 }
158 
159 void BPFPassConfig::addIRPasses() {
160   addPass(createAtomicExpandLegacyPass());
161   addPass(createBPFCheckAndAdjustIR());
162 
163   TargetPassConfig::addIRPasses();
164 }
165 
166 TargetTransformInfo
167 BPFTargetMachine::getTargetTransformInfo(const Function &F) const {
168   return TargetTransformInfo(std::make_unique<BPFTTIImpl>(this, F));
169 }
170 
171 // Install an instruction selector pass using
172 // the ISelDag to gen BPF code.
173 bool BPFPassConfig::addInstSelector() {
174   addPass(createBPFISelDag(getBPFTargetMachine()));
175 
176   return false;
177 }
178 
179 void BPFPassConfig::addMachineSSAOptimization() {
180   addPass(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(createBPFMIPeepholePass());
190   }
191 }
192 
193 void BPFPassConfig::addPreEmitPass() {
194   addPass(createBPFMIPreEmitCheckingPass());
195   if (getOptLevel() != CodeGenOptLevel::None)
196     if (!DisableMIPeephole)
197       addPass(createBPFMIPreEmitPeepholePass());
198 }
199 
200 bool BPFPassConfig::addIRTranslator() {
201   addPass(new IRTranslator());
202   return false;
203 }
204 
205 bool BPFPassConfig::addLegalizeMachineIR() {
206   addPass(new Legalizer());
207   return false;
208 }
209 
210 bool BPFPassConfig::addRegBankSelect() {
211   addPass(new RegBankSelect());
212   return false;
213 }
214 
215 bool BPFPassConfig::addGlobalInstructionSelect() {
216   addPass(new InstructionSelect(getOptLevel()));
217   return false;
218 }
219