BPFMISimplifyPatchable.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===//
  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. // This pass targets a subset of instructions like below
  10. // ld_imm64 r1, @global
  11. // ldd r2, r1, 0
  12. // add r3, struct_base_reg, r2
  13. //
  14. // Here @global should represent an AMA (abstruct member access).
  15. // Such an access is subject to bpf load time patching. After this pass, the
  16. // code becomes
  17. // ld_imm64 r1, @global
  18. // add r3, struct_base_reg, r1
  19. //
  20. // Eventually, at BTF output stage, a relocation record will be generated
  21. // for ld_imm64 which should be replaced later by bpf loader:
  22. // r1 = <calculated field_info>
  23. // add r3, struct_base_reg, r1
  24. //
  25. // This pass also removes the intermediate load generated in IR pass for
  26. // __builtin_btf_type_id() intrinsic.
  27. //
  28. //===----------------------------------------------------------------------===//
  29. #include "BPF.h"
  30. #include "BPFCORE.h"
  31. #include "BPFInstrInfo.h"
  32. #include "BPFTargetMachine.h"
  33. #include "llvm/CodeGen/MachineInstrBuilder.h"
  34. #include "llvm/CodeGen/MachineRegisterInfo.h"
  35. #include "llvm/Support/Debug.h"
  36. using namespace llvm;
  37. #define DEBUG_TYPE "bpf-mi-simplify-patchable"
  38. namespace {
  39. struct BPFMISimplifyPatchable : public MachineFunctionPass {
  40. static char ID;
  41. const BPFInstrInfo *TII;
  42. MachineFunction *MF;
  43. BPFMISimplifyPatchable() : MachineFunctionPass(ID) {
  44. initializeBPFMISimplifyPatchablePass(*PassRegistry::getPassRegistry());
  45. }
  46. private:
  47. // Initialize class variables.
  48. void initialize(MachineFunction &MFParm);
  49. bool removeLD();
  50. void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB,
  51. MachineInstr &MI, Register &SrcReg, Register &DstReg,
  52. const GlobalValue *GVal, bool IsAma);
  53. void processDstReg(MachineRegisterInfo *MRI, Register &DstReg,
  54. Register &SrcReg, const GlobalValue *GVal,
  55. bool doSrcRegProp, bool IsAma);
  56. void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst,
  57. MachineOperand *RelocOp, const GlobalValue *GVal);
  58. void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp,
  59. const GlobalValue *GVal);
  60. void checkShift(MachineRegisterInfo *MRI, MachineBasicBlock &MBB,
  61. MachineOperand *RelocOp, const GlobalValue *GVal,
  62. unsigned Opcode);
  63. public:
  64. // Main entry point for this pass.
  65. bool runOnMachineFunction(MachineFunction &MF) override {
  66. if (skipFunction(MF.getFunction()))
  67. return false;
  68. initialize(MF);
  69. return removeLD();
  70. }
  71. };
  72. // Initialize class variables.
  73. void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
  74. MF = &MFParm;
  75. TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
  76. LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
  77. }
  78. void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
  79. MachineOperand *RelocOp, const GlobalValue *GVal) {
  80. const MachineInstr *Inst = RelocOp->getParent();
  81. const MachineOperand *Op1 = &Inst->getOperand(1);
  82. const MachineOperand *Op2 = &Inst->getOperand(2);
  83. const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1;
  84. // Go through all uses of %1 as in %1 = ADD_rr %2, %3
  85. const MachineOperand Op0 = Inst->getOperand(0);
  86. for (MachineOperand &MO :
  87. llvm::make_early_inc_range(MRI->use_operands(Op0.getReg()))) {
  88. // The candidate needs to have a unique definition.
  89. if (!MRI->getUniqueVRegDef(MO.getReg()))
  90. continue;
  91. MachineInstr *DefInst = MO.getParent();
  92. unsigned Opcode = DefInst->getOpcode();
  93. unsigned COREOp;
  94. if (Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW ||
  95. Opcode == BPF::LDD || Opcode == BPF::STB || Opcode == BPF::STH ||
  96. Opcode == BPF::STW || Opcode == BPF::STD)
  97. COREOp = BPF::CORE_MEM;
  98. else if (Opcode == BPF::LDB32 || Opcode == BPF::LDH32 ||
  99. Opcode == BPF::LDW32 || Opcode == BPF::STB32 ||
  100. Opcode == BPF::STH32 || Opcode == BPF::STW32)
  101. COREOp = BPF::CORE_ALU32_MEM;
  102. else
  103. continue;
  104. // It must be a form of %2 = *(type *)(%1 + 0) or *(type *)(%1 + 0) = %2.
  105. const MachineOperand &ImmOp = DefInst->getOperand(2);
  106. if (!ImmOp.isImm() || ImmOp.getImm() != 0)
  107. continue;
  108. // Reject the form:
  109. // %1 = ADD_rr %2, %3
  110. // *(type *)(%2 + 0) = %1
  111. if (Opcode == BPF::STB || Opcode == BPF::STH || Opcode == BPF::STW ||
  112. Opcode == BPF::STD || Opcode == BPF::STB32 || Opcode == BPF::STH32 ||
  113. Opcode == BPF::STW32) {
  114. const MachineOperand &Opnd = DefInst->getOperand(0);
  115. if (Opnd.isReg() && Opnd.getReg() == MO.getReg())
  116. continue;
  117. }
  118. BuildMI(*DefInst->getParent(), *DefInst, DefInst->getDebugLoc(), TII->get(COREOp))
  119. .add(DefInst->getOperand(0)).addImm(Opcode).add(*BaseOp)
  120. .addGlobalAddress(GVal);
  121. DefInst->eraseFromParent();
  122. }
  123. }
  124. void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI,
  125. MachineBasicBlock &MBB, MachineOperand *RelocOp, const GlobalValue *GVal,
  126. unsigned Opcode) {
  127. // Relocation operand should be the operand #2.
  128. MachineInstr *Inst = RelocOp->getParent();
  129. if (RelocOp != &Inst->getOperand(2))
  130. return;
  131. BuildMI(MBB, *Inst, Inst->getDebugLoc(), TII->get(BPF::CORE_SHIFT))
  132. .add(Inst->getOperand(0)).addImm(Opcode)
  133. .add(Inst->getOperand(1)).addGlobalAddress(GVal);
  134. Inst->eraseFromParent();
  135. }
  136. void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI,
  137. MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg,
  138. Register &DstReg, const GlobalValue *GVal, bool IsAma) {
  139. if (MRI->getRegClass(DstReg) == &BPF::GPR32RegClass) {
  140. if (IsAma) {
  141. // We can optimize such a pattern:
  142. // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2"
  143. // %2:gpr32 = LDW32 %1:gpr, 0
  144. // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32
  145. // %4:gpr = ADD_rr %0:gpr, %3:gpr
  146. // or similar patterns below for non-alu32 case.
  147. auto Begin = MRI->use_begin(DstReg), End = MRI->use_end();
  148. decltype(End) NextI;
  149. for (auto I = Begin; I != End; I = NextI) {
  150. NextI = std::next(I);
  151. if (!MRI->getUniqueVRegDef(I->getReg()))
  152. continue;
  153. unsigned Opcode = I->getParent()->getOpcode();
  154. if (Opcode == BPF::SUBREG_TO_REG) {
  155. Register TmpReg = I->getParent()->getOperand(0).getReg();
  156. processDstReg(MRI, TmpReg, DstReg, GVal, false, IsAma);
  157. }
  158. }
  159. }
  160. BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::COPY), DstReg)
  161. .addReg(SrcReg, 0, BPF::sub_32);
  162. return;
  163. }
  164. // All uses of DstReg replaced by SrcReg
  165. processDstReg(MRI, DstReg, SrcReg, GVal, true, IsAma);
  166. }
  167. void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI,
  168. Register &DstReg, Register &SrcReg, const GlobalValue *GVal,
  169. bool doSrcRegProp, bool IsAma) {
  170. auto Begin = MRI->use_begin(DstReg), End = MRI->use_end();
  171. decltype(End) NextI;
  172. for (auto I = Begin; I != End; I = NextI) {
  173. NextI = std::next(I);
  174. if (doSrcRegProp)
  175. I->setReg(SrcReg);
  176. // The candidate needs to have a unique definition.
  177. if (IsAma && MRI->getUniqueVRegDef(I->getReg()))
  178. processInst(MRI, I->getParent(), &*I, GVal);
  179. }
  180. }
  181. // Check to see whether we could do some optimization
  182. // to attach relocation to downstream dependent instructions.
  183. // Two kinds of patterns are recognized below:
  184. // Pattern 1:
  185. // %1 = LD_imm64 @"llvm.b:0:4$0:1" <== patch_imm = 4
  186. // %2 = LDD %1, 0 <== this insn will be removed
  187. // %3 = ADD_rr %0, %2
  188. // %4 = LDW[32] %3, 0 OR STW[32] %4, %3, 0
  189. // The `%4 = ...` will be transformed to
  190. // CORE_[ALU32_]MEM(%4, mem_opcode, %0, @"llvm.b:0:4$0:1")
  191. // and later on, BTF emit phase will translate to
  192. // %4 = LDW[32] %0, 4 STW[32] %4, %0, 4
  193. // and attach a relocation to it.
  194. // Pattern 2:
  195. // %15 = LD_imm64 @"llvm.t:5:63$0:2" <== relocation type 5
  196. // %16 = LDD %15, 0 <== this insn will be removed
  197. // %17 = SRA_rr %14, %16
  198. // The `%17 = ...` will be transformed to
  199. // %17 = CORE_SHIFT(SRA_ri, %14, @"llvm.t:5:63$0:2")
  200. // and later on, BTF emit phase will translate to
  201. // %r4 = SRA_ri %r4, 63
  202. void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI,
  203. MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal) {
  204. unsigned Opcode = Inst->getOpcode();
  205. if (Opcode == BPF::ADD_rr)
  206. checkADDrr(MRI, RelocOp, GVal);
  207. else if (Opcode == BPF::SLL_rr)
  208. checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SLL_ri);
  209. else if (Opcode == BPF::SRA_rr)
  210. checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRA_ri);
  211. else if (Opcode == BPF::SRL_rr)
  212. checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRL_ri);
  213. }
  214. /// Remove unneeded Load instructions.
  215. bool BPFMISimplifyPatchable::removeLD() {
  216. MachineRegisterInfo *MRI = &MF->getRegInfo();
  217. MachineInstr *ToErase = nullptr;
  218. bool Changed = false;
  219. for (MachineBasicBlock &MBB : *MF) {
  220. for (MachineInstr &MI : MBB) {
  221. if (ToErase) {
  222. ToErase->eraseFromParent();
  223. ToErase = nullptr;
  224. }
  225. // Ensure the register format is LOAD <reg>, <reg>, 0
  226. if (MI.getOpcode() != BPF::LDD && MI.getOpcode() != BPF::LDW &&
  227. MI.getOpcode() != BPF::LDH && MI.getOpcode() != BPF::LDB &&
  228. MI.getOpcode() != BPF::LDW32 && MI.getOpcode() != BPF::LDH32 &&
  229. MI.getOpcode() != BPF::LDB32)
  230. continue;
  231. if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg())
  232. continue;
  233. if (!MI.getOperand(2).isImm() || MI.getOperand(2).getImm())
  234. continue;
  235. Register DstReg = MI.getOperand(0).getReg();
  236. Register SrcReg = MI.getOperand(1).getReg();
  237. MachineInstr *DefInst = MRI->getUniqueVRegDef(SrcReg);
  238. if (!DefInst)
  239. continue;
  240. if (DefInst->getOpcode() != BPF::LD_imm64)
  241. continue;
  242. const MachineOperand &MO = DefInst->getOperand(1);
  243. if (!MO.isGlobal())
  244. continue;
  245. const GlobalValue *GVal = MO.getGlobal();
  246. auto *GVar = dyn_cast<GlobalVariable>(GVal);
  247. if (!GVar)
  248. continue;
  249. // Global variables representing structure offset or type id.
  250. bool IsAma = false;
  251. if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr))
  252. IsAma = true;
  253. else if (!GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
  254. continue;
  255. processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal, IsAma);
  256. ToErase = &MI;
  257. Changed = true;
  258. }
  259. }
  260. return Changed;
  261. }
  262. } // namespace
  263. INITIALIZE_PASS(BPFMISimplifyPatchable, DEBUG_TYPE,
  264. "BPF PreEmit SimplifyPatchable", false, false)
  265. char BPFMISimplifyPatchable::ID = 0;
  266. FunctionPass *llvm::createBPFMISimplifyPatchablePass() {
  267. return new BPFMISimplifyPatchable();
  268. }