1e4c8c807SAlexei Starovoitov //===-- BPFTargetMachine.cpp - Define TargetMachine for BPF ---------------===//
2e4c8c807SAlexei Starovoitov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e4c8c807SAlexei Starovoitov //
7e4c8c807SAlexei Starovoitov //===----------------------------------------------------------------------===//
8e4c8c807SAlexei Starovoitov //
9e4c8c807SAlexei Starovoitov // Implements the info about BPF target spec.
10e4c8c807SAlexei Starovoitov //
11e4c8c807SAlexei Starovoitov //===----------------------------------------------------------------------===//
12e4c8c807SAlexei Starovoitov 
13e4c8c807SAlexei Starovoitov #include "BPFTargetMachine.h"
146bda14b3SChandler Carruth #include "BPF.h"
15a260ae71SYonghong Song #include "BPFTargetTransformInfo.h"
1603e1c8b8SYonghong Song #include "MCTargetDesc/BPFMCAsmInfo.h"
17a68ee931SRichard Trieu #include "TargetInfo/BPFTargetInfo.h"
18e4c8c807SAlexei Starovoitov #include "llvm/CodeGen/Passes.h"
196bda14b3SChandler Carruth #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2031d19d43SMatthias Braun #include "llvm/CodeGen/TargetPassConfig.h"
216bda14b3SChandler Carruth #include "llvm/IR/LegacyPassManager.h"
2240251feeSArthur Eubanks #include "llvm/IR/PassManager.h"
2389b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
2440251feeSArthur Eubanks #include "llvm/Passes/PassBuilder.h"
25e4c8c807SAlexei Starovoitov #include "llvm/Support/FormattedStream.h"
26e4c8c807SAlexei Starovoitov #include "llvm/Target/TargetOptions.h"
2787cba434SYonghong Song #include "llvm/Transforms/IPO/PassManagerBuilder.h"
2887cba434SYonghong Song #include "llvm/Transforms/Scalar.h"
2940251feeSArthur Eubanks #include "llvm/Transforms/Scalar/SimplifyCFG.h"
3087cba434SYonghong Song #include "llvm/Transforms/Utils/SimplifyCFGOptions.h"
31e4c8c807SAlexei Starovoitov using namespace llvm;
32e4c8c807SAlexei Starovoitov 
3360fed1feSYonghong Song static cl::
3460fed1feSYonghong Song opt<bool> DisableMIPeephole("disable-bpf-peephole", cl::Hidden,
3560fed1feSYonghong Song                             cl::desc("Disable machine peepholes for BPF"));
3660fed1feSYonghong Song 
LLVMInitializeBPFTarget()370dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() {
38e4c8c807SAlexei Starovoitov   // Register the target.
39f42454b9SMehdi Amini   RegisterTargetMachine<BPFTargetMachine> X(getTheBPFleTarget());
40f42454b9SMehdi Amini   RegisterTargetMachine<BPFTargetMachine> Y(getTheBPFbeTarget());
41f42454b9SMehdi Amini   RegisterTargetMachine<BPFTargetMachine> Z(getTheBPFTarget());
4260fed1feSYonghong Song 
4360fed1feSYonghong Song   PassRegistry &PR = *PassRegistry::getPassRegistry();
4440251feeSArthur Eubanks   initializeBPFAbstractMemberAccessLegacyPassPass(PR);
456b01b465SYonghong Song   initializeBPFPreserveDITypePass(PR);
46009f3a89SYonghong Song   initializeBPFIRPeepholePass(PR);
47ddf1864aSYonghong Song   initializeBPFAdjustOptPass(PR);
4854d9f743SYonghong Song   initializeBPFCheckAndAdjustIRPass(PR);
4960fed1feSYonghong Song   initializeBPFMIPeepholePass(PR);
50ec518510SJiong Wang   initializeBPFMIPeepholeTruncElimPass(PR);
51e4c8c807SAlexei Starovoitov }
52e4c8c807SAlexei Starovoitov 
53310deadaSAlexei Starovoitov // DataLayout: little or big endian
computeDataLayout(const Triple & TT)543e5de88dSDaniel Sanders static std::string computeDataLayout(const Triple &TT) {
553e5de88dSDaniel Sanders   if (TT.getArch() == Triple::bpfeb)
56ced0d1f4SYonghong Song     return "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
57310deadaSAlexei Starovoitov   else
58ced0d1f4SYonghong Song     return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
59310deadaSAlexei Starovoitov }
60310deadaSAlexei Starovoitov 
getEffectiveRelocModel(Optional<Reloc::Model> RM)618c34dd82SRafael Espindola static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
62*129b531cSKazu Hirata   return RM.value_or(Reloc::PIC_);
638c34dd82SRafael Espindola }
648c34dd82SRafael Espindola 
BPFTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)653e5de88dSDaniel Sanders BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT,
663e5de88dSDaniel Sanders                                    StringRef CPU, StringRef FS,
673e5de88dSDaniel Sanders                                    const TargetOptions &Options,
688c34dd82SRafael Espindola                                    Optional<Reloc::Model> RM,
6979e238afSRafael Espindola                                    Optional<CodeModel::Model> CM,
7079e238afSRafael Espindola                                    CodeGenOpt::Level OL, bool JIT)
71bb8507e6SMatthias Braun     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
72ca29c271SDavid Green                         getEffectiveRelocModel(RM),
73ca29c271SDavid Green                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
740eaee545SJonas Devlieghere       TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
75adcd0268SBenjamin Kramer       Subtarget(TT, std::string(CPU), std::string(FS), *this) {
76e4c8c807SAlexei Starovoitov   initAsmInfo();
7703e1c8b8SYonghong Song 
7810a21625SFangrui Song   BPFMCAsmInfo *MAI =
7910a21625SFangrui Song       static_cast<BPFMCAsmInfo *>(const_cast<MCAsmInfo *>(AsmInfo.get()));
8003e1c8b8SYonghong Song   MAI->setDwarfUsesRelocationsAcrossSections(!Subtarget.getUseDwarfRIS());
81e4c8c807SAlexei Starovoitov }
82d3d88d08SYonghong Song 
83e4c8c807SAlexei Starovoitov namespace {
84e4c8c807SAlexei Starovoitov // BPF Code Generator Pass Configuration Options.
85e4c8c807SAlexei Starovoitov class BPFPassConfig : public TargetPassConfig {
86e4c8c807SAlexei Starovoitov public:
BPFPassConfig(BPFTargetMachine & TM,PassManagerBase & PM)875e394c3dSMatthias Braun   BPFPassConfig(BPFTargetMachine &TM, PassManagerBase &PM)
88e4c8c807SAlexei Starovoitov       : TargetPassConfig(TM, PM) {}
89e4c8c807SAlexei Starovoitov 
getBPFTargetMachine() const90e4c8c807SAlexei Starovoitov   BPFTargetMachine &getBPFTargetMachine() const {
91e4c8c807SAlexei Starovoitov     return getTM<BPFTargetMachine>();
92e4c8c807SAlexei Starovoitov   }
93e4c8c807SAlexei Starovoitov 
94d3d88d08SYonghong Song   void addIRPasses() override;
95e4c8c807SAlexei Starovoitov   bool addInstSelector() override;
9660fed1feSYonghong Song   void addMachineSSAOptimization() override;
97e91802f3SYonghong Song   void addPreEmitPass() override;
98e4c8c807SAlexei Starovoitov };
99f00654e3SAlexander Kornienko }
100e4c8c807SAlexei Starovoitov 
createPassConfig(PassManagerBase & PM)101e4c8c807SAlexei Starovoitov TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) {
1025e394c3dSMatthias Braun   return new BPFPassConfig(*this, PM);
103e4c8c807SAlexei Starovoitov }
104e4c8c807SAlexei Starovoitov 
adjustPassManager(PassManagerBuilder & Builder)10587cba434SYonghong Song void BPFTargetMachine::adjustPassManager(PassManagerBuilder &Builder) {
10687cba434SYonghong Song  Builder.addExtension(
10754d9f743SYonghong Song       PassManagerBuilder::EP_EarlyAsPossible,
10854d9f743SYonghong Song       [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
10954d9f743SYonghong Song         PM.add(createBPFAbstractMemberAccess(this));
11054d9f743SYonghong Song         PM.add(createBPFPreserveDIType());
111009f3a89SYonghong Song         PM.add(createBPFIRPeephole());
11254d9f743SYonghong Song       });
11354d9f743SYonghong Song 
11454d9f743SYonghong Song   Builder.addExtension(
11587cba434SYonghong Song       PassManagerBuilder::EP_Peephole,
11687cba434SYonghong Song       [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
11787cba434SYonghong Song         PM.add(createCFGSimplificationPass(
11887cba434SYonghong Song             SimplifyCFGOptions().hoistCommonInsts(true)));
11987cba434SYonghong Song       });
120ddf1864aSYonghong Song   Builder.addExtension(
121ddf1864aSYonghong Song       PassManagerBuilder::EP_ModuleOptimizerEarly,
122ddf1864aSYonghong Song       [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
123ddf1864aSYonghong Song         PM.add(createBPFAdjustOpt());
124ddf1864aSYonghong Song       });
12587cba434SYonghong Song }
126d3d88d08SYonghong Song 
registerPassBuilderCallbacks(PassBuilder & PB)12734a8a437SArthur Eubanks void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
128ab0ddbc3SArthur Eubanks   PB.registerPipelineStartEPCallback(
1297a797b29STarindu Jayatilaka       [=](ModulePassManager &MPM, OptimizationLevel) {
13034a8a437SArthur Eubanks         FunctionPassManager FPM;
13140251feeSArthur Eubanks         FPM.addPass(BPFAbstractMemberAccessPass(this));
13240251feeSArthur Eubanks         FPM.addPass(BPFPreserveDITypePass());
133009f3a89SYonghong Song         FPM.addPass(BPFIRPeepholePass());
13440251feeSArthur Eubanks         MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
13540251feeSArthur Eubanks       });
13640251feeSArthur Eubanks   PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM,
1377a797b29STarindu Jayatilaka                                     OptimizationLevel Level) {
13840251feeSArthur Eubanks     FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true)));
13940251feeSArthur Eubanks   });
14092a67e13SArthur Eubanks   PB.registerPipelineEarlySimplificationEPCallback(
1417a797b29STarindu Jayatilaka       [=](ModulePassManager &MPM, OptimizationLevel) {
14292a67e13SArthur Eubanks         MPM.addPass(BPFAdjustOptPass());
14392a67e13SArthur Eubanks       });
14440251feeSArthur Eubanks }
14540251feeSArthur Eubanks 
addIRPasses()14687cba434SYonghong Song void BPFPassConfig::addIRPasses() {
14754d9f743SYonghong Song   addPass(createBPFCheckAndAdjustIR());
148d3d88d08SYonghong Song   TargetPassConfig::addIRPasses();
149d3d88d08SYonghong Song }
150d3d88d08SYonghong Song 
151a260ae71SYonghong Song TargetTransformInfo
getTargetTransformInfo(const Function & F) const152c4b1a63aSJameson Nash BPFTargetMachine::getTargetTransformInfo(const Function &F) const {
153a260ae71SYonghong Song   return TargetTransformInfo(BPFTTIImpl(this, F));
154a260ae71SYonghong Song }
155a260ae71SYonghong Song 
156e4c8c807SAlexei Starovoitov // Install an instruction selector pass using
157e4c8c807SAlexei Starovoitov // the ISelDag to gen BPF code.
addInstSelector()158e4c8c807SAlexei Starovoitov bool BPFPassConfig::addInstSelector() {
159e4c8c807SAlexei Starovoitov   addPass(createBPFISelDag(getBPFTargetMachine()));
160e4c8c807SAlexei Starovoitov 
161e4c8c807SAlexei Starovoitov   return false;
162e4c8c807SAlexei Starovoitov }
16360fed1feSYonghong Song 
addMachineSSAOptimization()16460fed1feSYonghong Song void BPFPassConfig::addMachineSSAOptimization() {
165d3d88d08SYonghong Song   addPass(createBPFMISimplifyPatchablePass());
166d3d88d08SYonghong Song 
16760fed1feSYonghong Song   // The default implementation must be called first as we want eBPF
16860fed1feSYonghong Song   // Peephole ran at last.
16960fed1feSYonghong Song   TargetPassConfig::addMachineSSAOptimization();
17060fed1feSYonghong Song 
17160fed1feSYonghong Song   const BPFSubtarget *Subtarget = getBPFTargetMachine().getSubtargetImpl();
172ec518510SJiong Wang   if (!DisableMIPeephole) {
173ec518510SJiong Wang     if (Subtarget->getHasAlu32())
17460fed1feSYonghong Song       addPass(createBPFMIPeepholePass());
175ec518510SJiong Wang     addPass(createBPFMIPeepholeTruncElimPass());
176ec518510SJiong Wang   }
17760fed1feSYonghong Song }
178e91802f3SYonghong Song 
addPreEmitPass()179e91802f3SYonghong Song void BPFPassConfig::addPreEmitPass() {
180150ca514SYonghong Song   addPass(createBPFMIPreEmitCheckingPass());
181e91802f3SYonghong Song   if (getOptLevel() != CodeGenOpt::None)
182ec518510SJiong Wang     if (!DisableMIPeephole)
183e91802f3SYonghong Song       addPass(createBPFMIPreEmitPeepholePass());
184e91802f3SYonghong Song }
185