BPFMIPeephole.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. //===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
  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 performs peephole optimizations to cleanup ugly code sequences at
  10. // MachineInstruction layer.
  11. //
  12. // Currently, there are two optimizations implemented:
  13. // - One pre-RA MachineSSA pass to eliminate type promotion sequences, those
  14. // zero extend 32-bit subregisters to 64-bit registers, if the compiler
  15. // could prove the subregisters is defined by 32-bit operations in which
  16. // case the upper half of the underlying 64-bit registers were zeroed
  17. // implicitly.
  18. //
  19. // - One post-RA PreEmit pass to do final cleanup on some redundant
  20. // instructions generated due to bad RA on subregister.
  21. //===----------------------------------------------------------------------===//
  22. #include "BPF.h"
  23. #include "BPFInstrInfo.h"
  24. #include "BPFTargetMachine.h"
  25. #include "llvm/ADT/Statistic.h"
  26. #include "llvm/CodeGen/MachineFunctionPass.h"
  27. #include "llvm/CodeGen/MachineInstrBuilder.h"
  28. #include "llvm/CodeGen/MachineRegisterInfo.h"
  29. #include "llvm/Support/Debug.h"
  30. #include <set>
  31. using namespace llvm;
  32. #define DEBUG_TYPE "bpf-mi-zext-elim"
  33. STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
  34. namespace {
  35. struct BPFMIPeephole : public MachineFunctionPass {
  36. static char ID;
  37. const BPFInstrInfo *TII;
  38. MachineFunction *MF;
  39. MachineRegisterInfo *MRI;
  40. BPFMIPeephole() : MachineFunctionPass(ID) {
  41. initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
  42. }
  43. private:
  44. // Initialize class variables.
  45. void initialize(MachineFunction &MFParm);
  46. bool isCopyFrom32Def(MachineInstr *CopyMI);
  47. bool isInsnFrom32Def(MachineInstr *DefInsn);
  48. bool isPhiFrom32Def(MachineInstr *MovMI);
  49. bool isMovFrom32Def(MachineInstr *MovMI);
  50. bool eliminateZExtSeq();
  51. bool eliminateZExt();
  52. std::set<MachineInstr *> PhiInsns;
  53. public:
  54. // Main entry point for this pass.
  55. bool runOnMachineFunction(MachineFunction &MF) override {
  56. if (skipFunction(MF.getFunction()))
  57. return false;
  58. initialize(MF);
  59. // First try to eliminate (zext, lshift, rshift) and then
  60. // try to eliminate zext.
  61. bool ZExtSeqExist, ZExtExist;
  62. ZExtSeqExist = eliminateZExtSeq();
  63. ZExtExist = eliminateZExt();
  64. return ZExtSeqExist || ZExtExist;
  65. }
  66. };
  67. // Initialize class variables.
  68. void BPFMIPeephole::initialize(MachineFunction &MFParm) {
  69. MF = &MFParm;
  70. MRI = &MF->getRegInfo();
  71. TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
  72. LLVM_DEBUG(dbgs() << "*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
  73. }
  74. bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
  75. {
  76. MachineOperand &opnd = CopyMI->getOperand(1);
  77. if (!opnd.isReg())
  78. return false;
  79. // Return false if getting value from a 32bit physical register.
  80. // Most likely, this physical register is aliased to
  81. // function call return value or current function parameters.
  82. Register Reg = opnd.getReg();
  83. if (!Reg.isVirtual())
  84. return false;
  85. if (MRI->getRegClass(Reg) == &BPF::GPRRegClass)
  86. return false;
  87. MachineInstr *DefInsn = MRI->getVRegDef(Reg);
  88. if (!isInsnFrom32Def(DefInsn))
  89. return false;
  90. return true;
  91. }
  92. bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
  93. {
  94. for (unsigned i = 1, e = PhiMI->getNumOperands(); i < e; i += 2) {
  95. MachineOperand &opnd = PhiMI->getOperand(i);
  96. if (!opnd.isReg())
  97. return false;
  98. MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
  99. if (!PhiDef)
  100. return false;
  101. if (PhiDef->isPHI()) {
  102. if (!PhiInsns.insert(PhiDef).second)
  103. return false;
  104. if (!isPhiFrom32Def(PhiDef))
  105. return false;
  106. }
  107. if (PhiDef->getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
  108. return false;
  109. }
  110. return true;
  111. }
  112. // The \p DefInsn instruction defines a virtual register.
  113. bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
  114. {
  115. if (!DefInsn)
  116. return false;
  117. if (DefInsn->isPHI()) {
  118. if (!PhiInsns.insert(DefInsn).second)
  119. return false;
  120. if (!isPhiFrom32Def(DefInsn))
  121. return false;
  122. } else if (DefInsn->getOpcode() == BPF::COPY) {
  123. if (!isCopyFrom32Def(DefInsn))
  124. return false;
  125. }
  126. return true;
  127. }
  128. bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
  129. {
  130. MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
  131. LLVM_DEBUG(dbgs() << " Def of Mov Src:");
  132. LLVM_DEBUG(DefInsn->dump());
  133. PhiInsns.clear();
  134. if (!isInsnFrom32Def(DefInsn))
  135. return false;
  136. LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
  137. return true;
  138. }
  139. bool BPFMIPeephole::eliminateZExtSeq() {
  140. MachineInstr* ToErase = nullptr;
  141. bool Eliminated = false;
  142. for (MachineBasicBlock &MBB : *MF) {
  143. for (MachineInstr &MI : MBB) {
  144. // If the previous instruction was marked for elimination, remove it now.
  145. if (ToErase) {
  146. ToErase->eraseFromParent();
  147. ToErase = nullptr;
  148. }
  149. // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
  150. //
  151. // MOV_32_64 rB, wA
  152. // SLL_ri rB, rB, 32
  153. // SRL_ri rB, rB, 32
  154. if (MI.getOpcode() == BPF::SRL_ri &&
  155. MI.getOperand(2).getImm() == 32) {
  156. Register DstReg = MI.getOperand(0).getReg();
  157. Register ShfReg = MI.getOperand(1).getReg();
  158. MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
  159. LLVM_DEBUG(dbgs() << "Starting SRL found:");
  160. LLVM_DEBUG(MI.dump());
  161. if (!SllMI ||
  162. SllMI->isPHI() ||
  163. SllMI->getOpcode() != BPF::SLL_ri ||
  164. SllMI->getOperand(2).getImm() != 32)
  165. continue;
  166. LLVM_DEBUG(dbgs() << " SLL found:");
  167. LLVM_DEBUG(SllMI->dump());
  168. MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
  169. if (!MovMI ||
  170. MovMI->isPHI() ||
  171. MovMI->getOpcode() != BPF::MOV_32_64)
  172. continue;
  173. LLVM_DEBUG(dbgs() << " Type cast Mov found:");
  174. LLVM_DEBUG(MovMI->dump());
  175. Register SubReg = MovMI->getOperand(1).getReg();
  176. if (!isMovFrom32Def(MovMI)) {
  177. LLVM_DEBUG(dbgs()
  178. << " One ZExt elim sequence failed qualifying elim.\n");
  179. continue;
  180. }
  181. BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
  182. .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
  183. SllMI->eraseFromParent();
  184. MovMI->eraseFromParent();
  185. // MI is the right shift, we can't erase it in it's own iteration.
  186. // Mark it to ToErase, and erase in the next iteration.
  187. ToErase = &MI;
  188. ZExtElemNum++;
  189. Eliminated = true;
  190. }
  191. }
  192. }
  193. return Eliminated;
  194. }
  195. bool BPFMIPeephole::eliminateZExt() {
  196. MachineInstr* ToErase = nullptr;
  197. bool Eliminated = false;
  198. for (MachineBasicBlock &MBB : *MF) {
  199. for (MachineInstr &MI : MBB) {
  200. // If the previous instruction was marked for elimination, remove it now.
  201. if (ToErase) {
  202. ToErase->eraseFromParent();
  203. ToErase = nullptr;
  204. }
  205. if (MI.getOpcode() != BPF::MOV_32_64)
  206. continue;
  207. // Eliminate MOV_32_64 if possible.
  208. // MOV_32_64 rA, wB
  209. //
  210. // If wB has been zero extended, replace it with a SUBREG_TO_REG.
  211. // This is to workaround BPF programs where pkt->{data, data_end}
  212. // is encoded as u32, but actually the verifier populates them
  213. // as 64bit pointer. The MOV_32_64 will zero out the top 32 bits.
  214. LLVM_DEBUG(dbgs() << "Candidate MOV_32_64 instruction:");
  215. LLVM_DEBUG(MI.dump());
  216. if (!isMovFrom32Def(&MI))
  217. continue;
  218. LLVM_DEBUG(dbgs() << "Removing the MOV_32_64 instruction\n");
  219. Register dst = MI.getOperand(0).getReg();
  220. Register src = MI.getOperand(1).getReg();
  221. // Build a SUBREG_TO_REG instruction.
  222. BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), dst)
  223. .addImm(0).addReg(src).addImm(BPF::sub_32);
  224. ToErase = &MI;
  225. Eliminated = true;
  226. }
  227. }
  228. return Eliminated;
  229. }
  230. } // end default namespace
  231. INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
  232. "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
  233. false, false)
  234. char BPFMIPeephole::ID = 0;
  235. FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
  236. STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
  237. namespace {
  238. struct BPFMIPreEmitPeephole : public MachineFunctionPass {
  239. static char ID;
  240. MachineFunction *MF;
  241. const TargetRegisterInfo *TRI;
  242. BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
  243. initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
  244. }
  245. private:
  246. // Initialize class variables.
  247. void initialize(MachineFunction &MFParm);
  248. bool eliminateRedundantMov();
  249. public:
  250. // Main entry point for this pass.
  251. bool runOnMachineFunction(MachineFunction &MF) override {
  252. if (skipFunction(MF.getFunction()))
  253. return false;
  254. initialize(MF);
  255. return eliminateRedundantMov();
  256. }
  257. };
  258. // Initialize class variables.
  259. void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
  260. MF = &MFParm;
  261. TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
  262. LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
  263. }
  264. bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
  265. MachineInstr* ToErase = nullptr;
  266. bool Eliminated = false;
  267. for (MachineBasicBlock &MBB : *MF) {
  268. for (MachineInstr &MI : MBB) {
  269. // If the previous instruction was marked for elimination, remove it now.
  270. if (ToErase) {
  271. LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
  272. LLVM_DEBUG(ToErase->dump());
  273. ToErase->eraseFromParent();
  274. ToErase = nullptr;
  275. }
  276. // Eliminate identical move:
  277. //
  278. // MOV rA, rA
  279. //
  280. // Note that we cannot remove
  281. // MOV_32_64 rA, wA
  282. // MOV_rr_32 wA, wA
  283. // as these two instructions having side effects, zeroing out
  284. // top 32 bits of rA.
  285. unsigned Opcode = MI.getOpcode();
  286. if (Opcode == BPF::MOV_rr) {
  287. Register dst = MI.getOperand(0).getReg();
  288. Register src = MI.getOperand(1).getReg();
  289. if (dst != src)
  290. continue;
  291. ToErase = &MI;
  292. RedundantMovElemNum++;
  293. Eliminated = true;
  294. }
  295. }
  296. }
  297. return Eliminated;
  298. }
  299. } // end default namespace
  300. INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
  301. "BPF PreEmit Peephole Optimization", false, false)
  302. char BPFMIPreEmitPeephole::ID = 0;
  303. FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
  304. {
  305. return new BPFMIPreEmitPeephole();
  306. }
  307. STATISTIC(TruncElemNum, "Number of truncation eliminated");
  308. namespace {
  309. struct BPFMIPeepholeTruncElim : public MachineFunctionPass {
  310. static char ID;
  311. const BPFInstrInfo *TII;
  312. MachineFunction *MF;
  313. MachineRegisterInfo *MRI;
  314. BPFMIPeepholeTruncElim() : MachineFunctionPass(ID) {
  315. initializeBPFMIPeepholeTruncElimPass(*PassRegistry::getPassRegistry());
  316. }
  317. private:
  318. // Initialize class variables.
  319. void initialize(MachineFunction &MFParm);
  320. bool eliminateTruncSeq();
  321. public:
  322. // Main entry point for this pass.
  323. bool runOnMachineFunction(MachineFunction &MF) override {
  324. if (skipFunction(MF.getFunction()))
  325. return false;
  326. initialize(MF);
  327. return eliminateTruncSeq();
  328. }
  329. };
  330. static bool TruncSizeCompatible(int TruncSize, unsigned opcode)
  331. {
  332. if (TruncSize == 1)
  333. return opcode == BPF::LDB || opcode == BPF::LDB32;
  334. if (TruncSize == 2)
  335. return opcode == BPF::LDH || opcode == BPF::LDH32;
  336. if (TruncSize == 4)
  337. return opcode == BPF::LDW || opcode == BPF::LDW32;
  338. return false;
  339. }
  340. // Initialize class variables.
  341. void BPFMIPeepholeTruncElim::initialize(MachineFunction &MFParm) {
  342. MF = &MFParm;
  343. MRI = &MF->getRegInfo();
  344. TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
  345. LLVM_DEBUG(dbgs() << "*** BPF MachineSSA TRUNC Elim peephole pass ***\n\n");
  346. }
  347. // Reg truncating is often the result of 8/16/32bit->64bit or
  348. // 8/16bit->32bit conversion. If the reg value is loaded with
  349. // masked byte width, the AND operation can be removed since
  350. // BPF LOAD already has zero extension.
  351. //
  352. // This also solved a correctness issue.
  353. // In BPF socket-related program, e.g., __sk_buff->{data, data_end}
  354. // are 32-bit registers, but later on, kernel verifier will rewrite
  355. // it with 64-bit value. Therefore, truncating the value after the
  356. // load will result in incorrect code.
  357. bool BPFMIPeepholeTruncElim::eliminateTruncSeq() {
  358. MachineInstr* ToErase = nullptr;
  359. bool Eliminated = false;
  360. for (MachineBasicBlock &MBB : *MF) {
  361. for (MachineInstr &MI : MBB) {
  362. // The second insn to remove if the eliminate candidate is a pair.
  363. MachineInstr *MI2 = nullptr;
  364. Register DstReg, SrcReg;
  365. MachineInstr *DefMI;
  366. int TruncSize = -1;
  367. // If the previous instruction was marked for elimination, remove it now.
  368. if (ToErase) {
  369. ToErase->eraseFromParent();
  370. ToErase = nullptr;
  371. }
  372. // AND A, 0xFFFFFFFF will be turned into SLL/SRL pair due to immediate
  373. // for BPF ANDI is i32, and this case only happens on ALU64.
  374. if (MI.getOpcode() == BPF::SRL_ri &&
  375. MI.getOperand(2).getImm() == 32) {
  376. SrcReg = MI.getOperand(1).getReg();
  377. if (!MRI->hasOneNonDBGUse(SrcReg))
  378. continue;
  379. MI2 = MRI->getVRegDef(SrcReg);
  380. DstReg = MI.getOperand(0).getReg();
  381. if (!MI2 ||
  382. MI2->getOpcode() != BPF::SLL_ri ||
  383. MI2->getOperand(2).getImm() != 32)
  384. continue;
  385. // Update SrcReg.
  386. SrcReg = MI2->getOperand(1).getReg();
  387. DefMI = MRI->getVRegDef(SrcReg);
  388. if (DefMI)
  389. TruncSize = 4;
  390. } else if (MI.getOpcode() == BPF::AND_ri ||
  391. MI.getOpcode() == BPF::AND_ri_32) {
  392. SrcReg = MI.getOperand(1).getReg();
  393. DstReg = MI.getOperand(0).getReg();
  394. DefMI = MRI->getVRegDef(SrcReg);
  395. if (!DefMI)
  396. continue;
  397. int64_t imm = MI.getOperand(2).getImm();
  398. if (imm == 0xff)
  399. TruncSize = 1;
  400. else if (imm == 0xffff)
  401. TruncSize = 2;
  402. }
  403. if (TruncSize == -1)
  404. continue;
  405. // The definition is PHI node, check all inputs.
  406. if (DefMI->isPHI()) {
  407. bool CheckFail = false;
  408. for (unsigned i = 1, e = DefMI->getNumOperands(); i < e; i += 2) {
  409. MachineOperand &opnd = DefMI->getOperand(i);
  410. if (!opnd.isReg()) {
  411. CheckFail = true;
  412. break;
  413. }
  414. MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
  415. if (!PhiDef || PhiDef->isPHI() ||
  416. !TruncSizeCompatible(TruncSize, PhiDef->getOpcode())) {
  417. CheckFail = true;
  418. break;
  419. }
  420. }
  421. if (CheckFail)
  422. continue;
  423. } else if (!TruncSizeCompatible(TruncSize, DefMI->getOpcode())) {
  424. continue;
  425. }
  426. BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::MOV_rr), DstReg)
  427. .addReg(SrcReg);
  428. if (MI2)
  429. MI2->eraseFromParent();
  430. // Mark it to ToErase, and erase in the next iteration.
  431. ToErase = &MI;
  432. TruncElemNum++;
  433. Eliminated = true;
  434. }
  435. }
  436. return Eliminated;
  437. }
  438. } // end default namespace
  439. INITIALIZE_PASS(BPFMIPeepholeTruncElim, "bpf-mi-trunc-elim",
  440. "BPF MachineSSA Peephole Optimization For TRUNC Eliminate",
  441. false, false)
  442. char BPFMIPeepholeTruncElim::ID = 0;
  443. FunctionPass* llvm::createBPFMIPeepholeTruncElimPass()
  444. {
  445. return new BPFMIPeepholeTruncElim();
  446. }