BPFInstrInfo.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
  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 file contains the BPF implementation of the TargetInstrInfo class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "BPFInstrInfo.h"
  13. #include "BPF.h"
  14. #include "llvm/ADT/SmallVector.h"
  15. #include "llvm/CodeGen/MachineBasicBlock.h"
  16. #include "llvm/CodeGen/MachineInstrBuilder.h"
  17. #include "llvm/IR/DebugLoc.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include <cassert>
  20. #include <iterator>
  21. #define GET_INSTRINFO_CTOR_DTOR
  22. #include "BPFGenInstrInfo.inc"
  23. using namespace llvm;
  24. BPFInstrInfo::BPFInstrInfo()
  25. : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
  26. void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
  27. MachineBasicBlock::iterator I,
  28. const DebugLoc &DL, MCRegister DestReg,
  29. MCRegister SrcReg, bool KillSrc) const {
  30. if (BPF::GPRRegClass.contains(DestReg, SrcReg))
  31. BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
  32. .addReg(SrcReg, getKillRegState(KillSrc));
  33. else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
  34. BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
  35. .addReg(SrcReg, getKillRegState(KillSrc));
  36. else
  37. llvm_unreachable("Impossible reg-to-reg copy");
  38. }
  39. void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
  40. Register DstReg = MI->getOperand(0).getReg();
  41. Register SrcReg = MI->getOperand(1).getReg();
  42. uint64_t CopyLen = MI->getOperand(2).getImm();
  43. uint64_t Alignment = MI->getOperand(3).getImm();
  44. Register ScratchReg = MI->getOperand(4).getReg();
  45. MachineBasicBlock *BB = MI->getParent();
  46. DebugLoc dl = MI->getDebugLoc();
  47. unsigned LdOpc, StOpc;
  48. switch (Alignment) {
  49. case 1:
  50. LdOpc = BPF::LDB;
  51. StOpc = BPF::STB;
  52. break;
  53. case 2:
  54. LdOpc = BPF::LDH;
  55. StOpc = BPF::STH;
  56. break;
  57. case 4:
  58. LdOpc = BPF::LDW;
  59. StOpc = BPF::STW;
  60. break;
  61. case 8:
  62. LdOpc = BPF::LDD;
  63. StOpc = BPF::STD;
  64. break;
  65. default:
  66. llvm_unreachable("unsupported memcpy alignment");
  67. }
  68. unsigned IterationNum = CopyLen >> Log2_64(Alignment);
  69. for(unsigned I = 0; I < IterationNum; ++I) {
  70. BuildMI(*BB, MI, dl, get(LdOpc))
  71. .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
  72. .addImm(I * Alignment);
  73. BuildMI(*BB, MI, dl, get(StOpc))
  74. .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
  75. .addImm(I * Alignment);
  76. }
  77. unsigned BytesLeft = CopyLen & (Alignment - 1);
  78. unsigned Offset = IterationNum * Alignment;
  79. bool Hanging4Byte = BytesLeft & 0x4;
  80. bool Hanging2Byte = BytesLeft & 0x2;
  81. bool Hanging1Byte = BytesLeft & 0x1;
  82. if (Hanging4Byte) {
  83. BuildMI(*BB, MI, dl, get(BPF::LDW))
  84. .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
  85. BuildMI(*BB, MI, dl, get(BPF::STW))
  86. .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
  87. Offset += 4;
  88. }
  89. if (Hanging2Byte) {
  90. BuildMI(*BB, MI, dl, get(BPF::LDH))
  91. .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
  92. BuildMI(*BB, MI, dl, get(BPF::STH))
  93. .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
  94. Offset += 2;
  95. }
  96. if (Hanging1Byte) {
  97. BuildMI(*BB, MI, dl, get(BPF::LDB))
  98. .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
  99. BuildMI(*BB, MI, dl, get(BPF::STB))
  100. .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
  101. }
  102. BB->erase(MI);
  103. }
  104. bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
  105. if (MI.getOpcode() == BPF::MEMCPY) {
  106. expandMEMCPY(MI);
  107. return true;
  108. }
  109. return false;
  110. }
  111. void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
  112. MachineBasicBlock::iterator I,
  113. Register SrcReg, bool IsKill, int FI,
  114. const TargetRegisterClass *RC,
  115. const TargetRegisterInfo *TRI,
  116. Register VReg) const {
  117. DebugLoc DL;
  118. if (I != MBB.end())
  119. DL = I->getDebugLoc();
  120. if (RC == &BPF::GPRRegClass)
  121. BuildMI(MBB, I, DL, get(BPF::STD))
  122. .addReg(SrcReg, getKillRegState(IsKill))
  123. .addFrameIndex(FI)
  124. .addImm(0);
  125. else if (RC == &BPF::GPR32RegClass)
  126. BuildMI(MBB, I, DL, get(BPF::STW32))
  127. .addReg(SrcReg, getKillRegState(IsKill))
  128. .addFrameIndex(FI)
  129. .addImm(0);
  130. else
  131. llvm_unreachable("Can't store this register to stack slot");
  132. }
  133. void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
  134. MachineBasicBlock::iterator I,
  135. Register DestReg, int FI,
  136. const TargetRegisterClass *RC,
  137. const TargetRegisterInfo *TRI,
  138. Register VReg) const {
  139. DebugLoc DL;
  140. if (I != MBB.end())
  141. DL = I->getDebugLoc();
  142. if (RC == &BPF::GPRRegClass)
  143. BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
  144. else if (RC == &BPF::GPR32RegClass)
  145. BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
  146. else
  147. llvm_unreachable("Can't load this register from stack slot");
  148. }
  149. bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
  150. MachineBasicBlock *&TBB,
  151. MachineBasicBlock *&FBB,
  152. SmallVectorImpl<MachineOperand> &Cond,
  153. bool AllowModify) const {
  154. // Start from the bottom of the block and work up, examining the
  155. // terminator instructions.
  156. MachineBasicBlock::iterator I = MBB.end();
  157. while (I != MBB.begin()) {
  158. --I;
  159. if (I->isDebugInstr())
  160. continue;
  161. // Working from the bottom, when we see a non-terminator
  162. // instruction, we're done.
  163. if (!isUnpredicatedTerminator(*I))
  164. break;
  165. // A terminator that isn't a branch can't easily be handled
  166. // by this analysis.
  167. if (!I->isBranch())
  168. return true;
  169. // Handle unconditional branches.
  170. if (I->getOpcode() == BPF::JMP) {
  171. if (!AllowModify) {
  172. TBB = I->getOperand(0).getMBB();
  173. continue;
  174. }
  175. // If the block has any instructions after a J, delete them.
  176. MBB.erase(std::next(I), MBB.end());
  177. Cond.clear();
  178. FBB = nullptr;
  179. // Delete the J if it's equivalent to a fall-through.
  180. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
  181. TBB = nullptr;
  182. I->eraseFromParent();
  183. I = MBB.end();
  184. continue;
  185. }
  186. // TBB is used to indicate the unconditinal destination.
  187. TBB = I->getOperand(0).getMBB();
  188. continue;
  189. }
  190. // Cannot handle conditional branches
  191. return true;
  192. }
  193. return false;
  194. }
  195. unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,
  196. MachineBasicBlock *TBB,
  197. MachineBasicBlock *FBB,
  198. ArrayRef<MachineOperand> Cond,
  199. const DebugLoc &DL,
  200. int *BytesAdded) const {
  201. assert(!BytesAdded && "code size not handled");
  202. // Shouldn't be a fall through.
  203. assert(TBB && "insertBranch must not be told to insert a fallthrough");
  204. if (Cond.empty()) {
  205. // Unconditional branch
  206. assert(!FBB && "Unconditional branch with multiple successors!");
  207. BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
  208. return 1;
  209. }
  210. llvm_unreachable("Unexpected conditional branch");
  211. }
  212. unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
  213. int *BytesRemoved) const {
  214. assert(!BytesRemoved && "code size not handled");
  215. MachineBasicBlock::iterator I = MBB.end();
  216. unsigned Count = 0;
  217. while (I != MBB.begin()) {
  218. --I;
  219. if (I->isDebugInstr())
  220. continue;
  221. if (I->getOpcode() != BPF::JMP)
  222. break;
  223. // Remove the branch.
  224. I->eraseFromParent();
  225. I = MBB.end();
  226. ++Count;
  227. }
  228. return Count;
  229. }