BPFISelDAGToDAG.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. //===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector 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. // This file defines a DAG pattern matching instruction selector for BPF,
  10. // converting from a legalized dag to a BPF dag.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "BPF.h"
  14. #include "BPFRegisterInfo.h"
  15. #include "BPFSubtarget.h"
  16. #include "BPFTargetMachine.h"
  17. #include "llvm/CodeGen/FunctionLoweringInfo.h"
  18. #include "llvm/CodeGen/MachineConstantPool.h"
  19. #include "llvm/CodeGen/MachineFrameInfo.h"
  20. #include "llvm/CodeGen/MachineFunction.h"
  21. #include "llvm/CodeGen/MachineInstrBuilder.h"
  22. #include "llvm/CodeGen/MachineRegisterInfo.h"
  23. #include "llvm/CodeGen/SelectionDAGISel.h"
  24. #include "llvm/IR/Constants.h"
  25. #include "llvm/IR/IntrinsicInst.h"
  26. #include "llvm/IR/IntrinsicsBPF.h"
  27. #include "llvm/Support/Debug.h"
  28. #include "llvm/Support/Endian.h"
  29. #include "llvm/Support/ErrorHandling.h"
  30. #include "llvm/Support/raw_ostream.h"
  31. #include "llvm/Target/TargetMachine.h"
  32. using namespace llvm;
  33. #define DEBUG_TYPE "bpf-isel"
  34. // Instruction Selector Implementation
  35. namespace {
  36. class BPFDAGToDAGISel : public SelectionDAGISel {
  37. /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can
  38. /// make the right decision when generating code for different subtargets.
  39. const BPFSubtarget *Subtarget;
  40. public:
  41. explicit BPFDAGToDAGISel(BPFTargetMachine &TM)
  42. : SelectionDAGISel(TM), Subtarget(nullptr) {}
  43. StringRef getPassName() const override {
  44. return "BPF DAG->DAG Pattern Instruction Selection";
  45. }
  46. bool runOnMachineFunction(MachineFunction &MF) override {
  47. // Reset the subtarget each time through.
  48. Subtarget = &MF.getSubtarget<BPFSubtarget>();
  49. return SelectionDAGISel::runOnMachineFunction(MF);
  50. }
  51. void PreprocessISelDAG() override;
  52. bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
  53. std::vector<SDValue> &OutOps) override;
  54. private:
  55. // Include the pieces autogenerated from the target description.
  56. #include "BPFGenDAGISel.inc"
  57. void Select(SDNode *N) override;
  58. // Complex Pattern for address selection.
  59. bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
  60. bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
  61. // Node preprocessing cases
  62. void PreprocessLoad(SDNode *Node, SelectionDAG::allnodes_iterator &I);
  63. void PreprocessCopyToReg(SDNode *Node);
  64. void PreprocessTrunc(SDNode *Node, SelectionDAG::allnodes_iterator &I);
  65. // Find constants from a constant structure
  66. typedef std::vector<unsigned char> val_vec_type;
  67. bool fillGenericConstant(const DataLayout &DL, const Constant *CV,
  68. val_vec_type &Vals, uint64_t Offset);
  69. bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA,
  70. val_vec_type &Vals, int Offset);
  71. bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA,
  72. val_vec_type &Vals, int Offset);
  73. bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS,
  74. val_vec_type &Vals, int Offset);
  75. bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset,
  76. uint64_t Size, unsigned char *ByteSeq);
  77. // Mapping from ConstantStruct global value to corresponding byte-list values
  78. std::map<const void *, val_vec_type> cs_vals_;
  79. };
  80. } // namespace
  81. // ComplexPattern used on BPF Load/Store instructions
  82. bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
  83. // if Address is FI, get the TargetFrameIndex.
  84. SDLoc DL(Addr);
  85. if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
  86. Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
  87. Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
  88. return true;
  89. }
  90. if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
  91. Addr.getOpcode() == ISD::TargetGlobalAddress)
  92. return false;
  93. // Addresses of the form Addr+const or Addr|const
  94. if (CurDAG->isBaseWithConstantOffset(Addr)) {
  95. auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
  96. if (isInt<16>(CN->getSExtValue())) {
  97. // If the first operand is a FI, get the TargetFI Node
  98. if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
  99. Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
  100. else
  101. Base = Addr.getOperand(0);
  102. Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
  103. return true;
  104. }
  105. }
  106. Base = Addr;
  107. Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
  108. return true;
  109. }
  110. // ComplexPattern used on BPF FI instruction
  111. bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
  112. SDValue &Offset) {
  113. SDLoc DL(Addr);
  114. if (!CurDAG->isBaseWithConstantOffset(Addr))
  115. return false;
  116. // Addresses of the form Addr+const or Addr|const
  117. auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
  118. if (isInt<16>(CN->getSExtValue())) {
  119. // If the first operand is a FI, get the TargetFI Node
  120. if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
  121. Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
  122. else
  123. return false;
  124. Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
  125. return true;
  126. }
  127. return false;
  128. }
  129. bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
  130. const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
  131. SDValue Op0, Op1;
  132. switch (ConstraintCode) {
  133. default:
  134. return true;
  135. case InlineAsm::Constraint_m: // memory
  136. if (!SelectAddr(Op, Op0, Op1))
  137. return true;
  138. break;
  139. }
  140. SDLoc DL(Op);
  141. SDValue AluOp = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32);;
  142. OutOps.push_back(Op0);
  143. OutOps.push_back(Op1);
  144. OutOps.push_back(AluOp);
  145. return false;
  146. }
  147. void BPFDAGToDAGISel::Select(SDNode *Node) {
  148. unsigned Opcode = Node->getOpcode();
  149. // If we have a custom node, we already have selected!
  150. if (Node->isMachineOpcode()) {
  151. LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
  152. return;
  153. }
  154. // tablegen selection should be handled here.
  155. switch (Opcode) {
  156. default:
  157. break;
  158. case ISD::SDIV: {
  159. DebugLoc Empty;
  160. const DebugLoc &DL = Node->getDebugLoc();
  161. if (DL != Empty)
  162. errs() << "Error at line " << DL.getLine() << ": ";
  163. else
  164. errs() << "Error: ";
  165. errs() << "Unsupport signed division for DAG: ";
  166. Node->print(errs(), CurDAG);
  167. errs() << "Please convert to unsigned div/mod.\n";
  168. break;
  169. }
  170. case ISD::INTRINSIC_W_CHAIN: {
  171. unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
  172. switch (IntNo) {
  173. case Intrinsic::bpf_load_byte:
  174. case Intrinsic::bpf_load_half:
  175. case Intrinsic::bpf_load_word: {
  176. SDLoc DL(Node);
  177. SDValue Chain = Node->getOperand(0);
  178. SDValue N1 = Node->getOperand(1);
  179. SDValue Skb = Node->getOperand(2);
  180. SDValue N3 = Node->getOperand(3);
  181. SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
  182. Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb, SDValue());
  183. Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
  184. break;
  185. }
  186. }
  187. break;
  188. }
  189. case ISD::FrameIndex: {
  190. int FI = cast<FrameIndexSDNode>(Node)->getIndex();
  191. EVT VT = Node->getValueType(0);
  192. SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
  193. unsigned Opc = BPF::MOV_rr;
  194. if (Node->hasOneUse()) {
  195. CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
  196. return;
  197. }
  198. ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI));
  199. return;
  200. }
  201. }
  202. // Select the default instruction
  203. SelectCode(Node);
  204. }
  205. void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
  206. SelectionDAG::allnodes_iterator &I) {
  207. union {
  208. uint8_t c[8];
  209. uint16_t s;
  210. uint32_t i;
  211. uint64_t d;
  212. } new_val; // hold up the constant values replacing loads.
  213. bool to_replace = false;
  214. SDLoc DL(Node);
  215. const LoadSDNode *LD = cast<LoadSDNode>(Node);
  216. uint64_t size = LD->getMemOperand()->getSize();
  217. if (!size || size > 8 || (size & (size - 1)) || !LD->isSimple())
  218. return;
  219. SDNode *LDAddrNode = LD->getOperand(1).getNode();
  220. // Match LDAddr against either global_addr or (global_addr + offset)
  221. unsigned opcode = LDAddrNode->getOpcode();
  222. if (opcode == ISD::ADD) {
  223. SDValue OP1 = LDAddrNode->getOperand(0);
  224. SDValue OP2 = LDAddrNode->getOperand(1);
  225. // We want to find the pattern global_addr + offset
  226. SDNode *OP1N = OP1.getNode();
  227. if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END || OP1N->getNumOperands() == 0)
  228. return;
  229. LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
  230. const GlobalAddressSDNode *GADN =
  231. dyn_cast<GlobalAddressSDNode>(OP1N->getOperand(0).getNode());
  232. const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
  233. if (GADN && CDN)
  234. to_replace =
  235. getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val.c);
  236. } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
  237. LDAddrNode->getNumOperands() > 0) {
  238. LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
  239. SDValue OP1 = LDAddrNode->getOperand(0);
  240. if (const GlobalAddressSDNode *GADN =
  241. dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
  242. to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
  243. }
  244. if (!to_replace)
  245. return;
  246. // replacing the old with a new value
  247. uint64_t val;
  248. if (size == 1)
  249. val = new_val.c[0];
  250. else if (size == 2)
  251. val = new_val.s;
  252. else if (size == 4)
  253. val = new_val.i;
  254. else {
  255. val = new_val.d;
  256. }
  257. LLVM_DEBUG(dbgs() << "Replacing load of size " << size << " with constant "
  258. << val << '\n');
  259. SDValue NVal = CurDAG->getConstant(val, DL, LD->getValueType(0));
  260. // After replacement, the current node is dead, we need to
  261. // go backward one step to make iterator still work
  262. I--;
  263. SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
  264. SDValue To[] = {NVal, NVal};
  265. CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
  266. I++;
  267. // It is safe to delete node now
  268. CurDAG->DeleteNode(Node);
  269. }
  270. void BPFDAGToDAGISel::PreprocessISelDAG() {
  271. // Iterate through all nodes, interested in the following case:
  272. //
  273. // . loads from ConstantStruct or ConstantArray of constructs
  274. // which can be turns into constant itself, with this we can
  275. // avoid reading from read-only section at runtime.
  276. //
  277. // . Removing redundant AND for intrinsic narrow loads.
  278. for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
  279. E = CurDAG->allnodes_end();
  280. I != E;) {
  281. SDNode *Node = &*I++;
  282. unsigned Opcode = Node->getOpcode();
  283. if (Opcode == ISD::LOAD)
  284. PreprocessLoad(Node, I);
  285. else if (Opcode == ISD::AND)
  286. PreprocessTrunc(Node, I);
  287. }
  288. }
  289. bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
  290. uint64_t Offset, uint64_t Size,
  291. unsigned char *ByteSeq) {
  292. const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
  293. if (!V || !V->hasInitializer() || !V->isConstant())
  294. return false;
  295. const Constant *Init = V->getInitializer();
  296. const DataLayout &DL = CurDAG->getDataLayout();
  297. val_vec_type TmpVal;
  298. auto it = cs_vals_.find(static_cast<const void *>(Init));
  299. if (it != cs_vals_.end()) {
  300. TmpVal = it->second;
  301. } else {
  302. uint64_t total_size = 0;
  303. if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
  304. total_size =
  305. DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
  306. else if (const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
  307. total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) *
  308. CA->getNumOperands();
  309. else
  310. return false;
  311. val_vec_type Vals(total_size, 0);
  312. if (fillGenericConstant(DL, Init, Vals, 0) == false)
  313. return false;
  314. cs_vals_[static_cast<const void *>(Init)] = Vals;
  315. TmpVal = std::move(Vals);
  316. }
  317. // test whether host endianness matches target
  318. union {
  319. uint8_t c[2];
  320. uint16_t s;
  321. } test_buf;
  322. uint16_t test_val = 0x2345;
  323. if (DL.isLittleEndian())
  324. support::endian::write16le(test_buf.c, test_val);
  325. else
  326. support::endian::write16be(test_buf.c, test_val);
  327. bool endian_match = test_buf.s == test_val;
  328. for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++)
  329. ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
  330. return true;
  331. }
  332. bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL,
  333. const Constant *CV,
  334. val_vec_type &Vals, uint64_t Offset) {
  335. uint64_t Size = DL.getTypeAllocSize(CV->getType());
  336. if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
  337. return true; // already done
  338. if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
  339. uint64_t val = CI->getZExtValue();
  340. LLVM_DEBUG(dbgs() << "Byte array at offset " << Offset << " with value "
  341. << val << '\n');
  342. if (Size > 8 || (Size & (Size - 1)))
  343. return false;
  344. // Store based on target endian
  345. for (uint64_t i = 0; i < Size; ++i) {
  346. Vals[Offset + i] = DL.isLittleEndian()
  347. ? ((val >> (i * 8)) & 0xFF)
  348. : ((val >> ((Size - i - 1) * 8)) & 0xFF);
  349. }
  350. return true;
  351. }
  352. if (const ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(CV))
  353. return fillConstantDataArray(DL, CDA, Vals, Offset);
  354. if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV))
  355. return fillConstantArray(DL, CA, Vals, Offset);
  356. if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
  357. return fillConstantStruct(DL, CVS, Vals, Offset);
  358. return false;
  359. }
  360. bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL,
  361. const ConstantDataArray *CDA,
  362. val_vec_type &Vals, int Offset) {
  363. for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) {
  364. if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) ==
  365. false)
  366. return false;
  367. Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType());
  368. }
  369. return true;
  370. }
  371. bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL,
  372. const ConstantArray *CA,
  373. val_vec_type &Vals, int Offset) {
  374. for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
  375. if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false)
  376. return false;
  377. Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
  378. }
  379. return true;
  380. }
  381. bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout &DL,
  382. const ConstantStruct *CS,
  383. val_vec_type &Vals, int Offset) {
  384. const StructLayout *Layout = DL.getStructLayout(CS->getType());
  385. for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
  386. const Constant *Field = CS->getOperand(i);
  387. uint64_t SizeSoFar = Layout->getElementOffset(i);
  388. if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false)
  389. return false;
  390. }
  391. return true;
  392. }
  393. void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
  394. SelectionDAG::allnodes_iterator &I) {
  395. ConstantSDNode *MaskN = dyn_cast<ConstantSDNode>(Node->getOperand(1));
  396. if (!MaskN)
  397. return;
  398. // The Reg operand should be a virtual register, which is defined
  399. // outside the current basic block. DAG combiner has done a pretty
  400. // good job in removing truncating inside a single basic block except
  401. // when the Reg operand comes from bpf_load_[byte | half | word] for
  402. // which the generic optimizer doesn't understand their results are
  403. // zero extended.
  404. SDValue BaseV = Node->getOperand(0);
  405. if (BaseV.getOpcode() != ISD::INTRINSIC_W_CHAIN)
  406. return;
  407. unsigned IntNo = cast<ConstantSDNode>(BaseV->getOperand(1))->getZExtValue();
  408. uint64_t MaskV = MaskN->getZExtValue();
  409. if (!((IntNo == Intrinsic::bpf_load_byte && MaskV == 0xFF) ||
  410. (IntNo == Intrinsic::bpf_load_half && MaskV == 0xFFFF) ||
  411. (IntNo == Intrinsic::bpf_load_word && MaskV == 0xFFFFFFFF)))
  412. return;
  413. LLVM_DEBUG(dbgs() << "Remove the redundant AND operation in: ";
  414. Node->dump(); dbgs() << '\n');
  415. I--;
  416. CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
  417. I++;
  418. CurDAG->DeleteNode(Node);
  419. }
  420. FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) {
  421. return new BPFDAGToDAGISel(TM);
  422. }