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