]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
MFV r326007: less v529.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / BPF / BPFISelDAGToDAG.cpp
1 //===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a DAG pattern matching instruction selector for BPF,
11 // converting from a legalized dag to a BPF dag.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "BPF.h"
16 #include "BPFRegisterInfo.h"
17 #include "BPFSubtarget.h"
18 #include "BPFTargetMachine.h"
19 #include "llvm/CodeGen/FunctionLoweringInfo.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/SelectionDAGISel.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/Endian.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
33
34 using namespace llvm;
35
36 #define DEBUG_TYPE "bpf-isel"
37
38 // Instruction Selector Implementation
39 namespace {
40
41 class BPFDAGToDAGISel : public SelectionDAGISel {
42 public:
43   explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {}
44
45   StringRef getPassName() const override {
46     return "BPF DAG->DAG Pattern Instruction Selection";
47   }
48
49   void PreprocessISelDAG() override;
50
51 private:
52 // Include the pieces autogenerated from the target description.
53 #include "BPFGenDAGISel.inc"
54
55   void Select(SDNode *N) override;
56
57   // Complex Pattern for address selection.
58   bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
59   bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
60
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
66   // Find constants from a constant structure
67   typedef std::vector<unsigned char> val_vec_type;
68   bool fillGenericConstant(const DataLayout &DL, const Constant *CV,
69                            val_vec_type &Vals, uint64_t Offset);
70   bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA,
71                              val_vec_type &Vals, int Offset);
72   bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA,
73                          val_vec_type &Vals, int Offset);
74   bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS,
75                           val_vec_type &Vals, int Offset);
76   bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset,
77                              uint64_t Size, unsigned char *ByteSeq);
78   bool checkLoadDef(unsigned DefReg, unsigned match_load_op);
79
80   // Mapping from ConstantStruct global value to corresponding byte-list values
81   std::map<const void *, val_vec_type> cs_vals_;
82   // Mapping from vreg to load memory opcode
83   std::map<unsigned, unsigned> load_to_vreg_;
84 };
85 } // namespace
86
87 // ComplexPattern used on BPF Load/Store instructions
88 bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
89   // if Address is FI, get the TargetFrameIndex.
90   SDLoc DL(Addr);
91   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
92     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
93     Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
94     return true;
95   }
96
97   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
98       Addr.getOpcode() == ISD::TargetGlobalAddress)
99     return false;
100
101   // Addresses of the form Addr+const or Addr|const
102   if (CurDAG->isBaseWithConstantOffset(Addr)) {
103     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
104     if (isInt<16>(CN->getSExtValue())) {
105
106       // If the first operand is a FI, get the TargetFI Node
107       if (FrameIndexSDNode *FIN =
108               dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
109         Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
110       else
111         Base = Addr.getOperand(0);
112
113       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
114       return true;
115     }
116   }
117
118   Base = Addr;
119   Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
120   return true;
121 }
122
123 // ComplexPattern used on BPF FI instruction
124 bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
125                                    SDValue &Offset) {
126   SDLoc DL(Addr);
127
128   if (!CurDAG->isBaseWithConstantOffset(Addr))
129     return false;
130
131   // Addresses of the form Addr+const or Addr|const
132   ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
133   if (isInt<16>(CN->getSExtValue())) {
134
135     // If the first operand is a FI, get the TargetFI Node
136     if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
137       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
138     else
139       return false;
140
141     Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
142     return true;
143   }
144
145   return false;
146 }
147
148 void BPFDAGToDAGISel::Select(SDNode *Node) {
149   unsigned Opcode = Node->getOpcode();
150
151   // Dump information about the Node being selected
152   DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n');
153
154   // If we have a custom node, we already have selected!
155   if (Node->isMachineOpcode()) {
156     DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
157     return;
158   }
159
160   // tablegen selection should be handled here.
161   switch (Opcode) {
162   default:
163     break;
164   case ISD::SDIV: {
165     DebugLoc Empty;
166     const DebugLoc &DL = Node->getDebugLoc();
167     if (DL != Empty)
168       errs() << "Error at line " << DL.getLine() << ": ";
169     else
170       errs() << "Error: ";
171     errs() << "Unsupport signed division for DAG: ";
172     Node->print(errs(), CurDAG);
173     errs() << "Please convert to unsigned div/mod.\n";
174     break;
175   }
176   case ISD::INTRINSIC_W_CHAIN: {
177     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
178     switch (IntNo) {
179     case Intrinsic::bpf_load_byte:
180     case Intrinsic::bpf_load_half:
181     case Intrinsic::bpf_load_word: {
182       SDLoc DL(Node);
183       SDValue Chain = Node->getOperand(0);
184       SDValue N1 = Node->getOperand(1);
185       SDValue Skb = Node->getOperand(2);
186       SDValue N3 = Node->getOperand(3);
187
188       SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
189       Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb, SDValue());
190       Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
191       break;
192     }
193     }
194     break;
195   }
196
197   case ISD::FrameIndex: {
198     int FI = cast<FrameIndexSDNode>(Node)->getIndex();
199     EVT VT = Node->getValueType(0);
200     SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
201     unsigned Opc = BPF::MOV_rr;
202     if (Node->hasOneUse()) {
203       CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
204       return;
205     }
206     ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI));
207     return;
208   }
209   }
210
211   // Select the default instruction
212   SelectCode(Node);
213 }
214
215 void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
216                                      SelectionDAG::allnodes_iterator I) {
217   union {
218     uint8_t c[8];
219     uint16_t s;
220     uint32_t i;
221     uint64_t d;
222   } new_val; // hold up the constant values replacing loads.
223   bool to_replace = false;
224   SDLoc DL(Node);
225   const LoadSDNode *LD = cast<LoadSDNode>(Node);
226   uint64_t size = LD->getMemOperand()->getSize();
227
228   if (!size || size > 8 || (size & (size - 1)))
229     return;
230
231   SDNode *LDAddrNode = LD->getOperand(1).getNode();
232   // Match LDAddr against either global_addr or (global_addr + offset)
233   unsigned opcode = LDAddrNode->getOpcode();
234   if (opcode == ISD::ADD) {
235     SDValue OP1 = LDAddrNode->getOperand(0);
236     SDValue OP2 = LDAddrNode->getOperand(1);
237
238     // We want to find the pattern global_addr + offset
239     SDNode *OP1N = OP1.getNode();
240     if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END || OP1N->getNumOperands() == 0)
241       return;
242
243     DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
244
245     const GlobalAddressSDNode *GADN =
246         dyn_cast<GlobalAddressSDNode>(OP1N->getOperand(0).getNode());
247     const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
248     if (GADN && CDN)
249       to_replace =
250           getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val.c);
251   } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
252              LDAddrNode->getNumOperands() > 0) {
253     DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
254
255     SDValue OP1 = LDAddrNode->getOperand(0);
256     if (const GlobalAddressSDNode *GADN =
257             dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
258       to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
259   }
260
261   if (!to_replace)
262     return;
263
264   // replacing the old with a new value
265   uint64_t val;
266   if (size == 1)
267     val = new_val.c[0];
268   else if (size == 2)
269     val = new_val.s;
270   else if (size == 4)
271     val = new_val.i;
272   else {
273     val = new_val.d;
274   }
275
276   DEBUG(dbgs() << "Replacing load of size " << size << " with constant " << val
277                << '\n');
278   SDValue NVal = CurDAG->getConstant(val, DL, MVT::i64);
279
280   // After replacement, the current node is dead, we need to
281   // go backward one step to make iterator still work
282   I--;
283   SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
284   SDValue To[] = {NVal, NVal};
285   CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
286   I++;
287   // It is safe to delete node now
288   CurDAG->DeleteNode(Node);
289 }
290
291 void BPFDAGToDAGISel::PreprocessISelDAG() {
292   // Iterate through all nodes, interested in the following cases:
293   //
294   //  . loads from ConstantStruct or ConstantArray of constructs
295   //    which can be turns into constant itself, with this we can
296   //    avoid reading from read-only section at runtime.
297   //
298   //  . reg truncating is often the result of 8/16/32bit->64bit or
299   //    8/16bit->32bit conversion. If the reg value is loaded with
300   //    masked byte width, the AND operation can be removed since
301   //    BPF LOAD already has zero extension.
302   //
303   //    This also solved a correctness issue.
304   //    In BPF socket-related program, e.g., __sk_buff->{data, data_end}
305   //    are 32-bit registers, but later on, kernel verifier will rewrite
306   //    it with 64-bit value. Therefore, truncating the value after the
307   //    load will result in incorrect code.
308   for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
309                                        E = CurDAG->allnodes_end();
310        I != E;) {
311     SDNode *Node = &*I++;
312     unsigned Opcode = Node->getOpcode();
313     if (Opcode == ISD::LOAD)
314       PreprocessLoad(Node, I);
315     else if (Opcode == ISD::CopyToReg)
316       PreprocessCopyToReg(Node);
317     else if (Opcode == ISD::AND)
318       PreprocessTrunc(Node, I);
319   }
320 }
321
322 bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
323                                             uint64_t Offset, uint64_t Size,
324                                             unsigned char *ByteSeq) {
325   const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
326
327   if (!V || !V->hasInitializer())
328     return false;
329
330   const Constant *Init = V->getInitializer();
331   const DataLayout &DL = CurDAG->getDataLayout();
332   val_vec_type TmpVal;
333
334   auto it = cs_vals_.find(static_cast<const void *>(Init));
335   if (it != cs_vals_.end()) {
336     TmpVal = it->second;
337   } else {
338     uint64_t total_size = 0;
339     if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
340       total_size =
341           DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
342     else if (const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
343       total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) *
344                    CA->getNumOperands();
345     else
346       return false;
347
348     val_vec_type Vals(total_size, 0);
349     if (fillGenericConstant(DL, Init, Vals, 0) == false)
350       return false;
351     cs_vals_[static_cast<const void *>(Init)] = Vals;
352     TmpVal = std::move(Vals);
353   }
354
355   // test whether host endianness matches target
356   union {
357     uint8_t c[2];
358     uint16_t s;
359   } test_buf;
360   uint16_t test_val = 0x2345;
361   if (DL.isLittleEndian())
362     support::endian::write16le(test_buf.c, test_val);
363   else
364     support::endian::write16be(test_buf.c, test_val);
365
366   bool endian_match = test_buf.s == test_val;
367   for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++)
368     ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
369
370   return true;
371 }
372
373 bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL,
374                                           const Constant *CV,
375                                           val_vec_type &Vals, uint64_t Offset) {
376   uint64_t Size = DL.getTypeAllocSize(CV->getType());
377
378   if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
379     return true; // already done
380
381   if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
382     uint64_t val = CI->getZExtValue();
383     DEBUG(dbgs() << "Byte array at offset " << Offset << " with value " << val
384                  << '\n');
385
386     if (Size > 8 || (Size & (Size - 1)))
387       return false;
388
389     // Store based on target endian
390     for (uint64_t i = 0; i < Size; ++i) {
391       Vals[Offset + i] = DL.isLittleEndian()
392                              ? ((val >> (i * 8)) & 0xFF)
393                              : ((val >> ((Size - i - 1) * 8)) & 0xFF);
394     }
395     return true;
396   }
397
398   if (const ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(CV))
399     return fillConstantDataArray(DL, CDA, Vals, Offset);
400
401   if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV))
402     return fillConstantArray(DL, CA, Vals, Offset);
403
404   if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
405     return fillConstantStruct(DL, CVS, Vals, Offset);
406
407   return false;
408 }
409
410 bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL,
411                                             const ConstantDataArray *CDA,
412                                             val_vec_type &Vals, int Offset) {
413   for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) {
414     if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) ==
415         false)
416       return false;
417     Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType());
418   }
419
420   return true;
421 }
422
423 bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL,
424                                         const ConstantArray *CA,
425                                         val_vec_type &Vals, int Offset) {
426   for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
427     if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false)
428       return false;
429     Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
430   }
431
432   return true;
433 }
434
435 bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout &DL,
436                                          const ConstantStruct *CS,
437                                          val_vec_type &Vals, int Offset) {
438   const StructLayout *Layout = DL.getStructLayout(CS->getType());
439   for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
440     const Constant *Field = CS->getOperand(i);
441     uint64_t SizeSoFar = Layout->getElementOffset(i);
442     if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false)
443       return false;
444   }
445   return true;
446 }
447
448 void BPFDAGToDAGISel::PreprocessCopyToReg(SDNode *Node) {
449   const RegisterSDNode *RegN = dyn_cast<RegisterSDNode>(Node->getOperand(1));
450   if (!RegN || !TargetRegisterInfo::isVirtualRegister(RegN->getReg()))
451     return;
452
453   const LoadSDNode *LD = dyn_cast<LoadSDNode>(Node->getOperand(2));
454   if (!LD)
455     return;
456
457   // Assign a load value to a virtual register. record its load width
458   unsigned mem_load_op = 0;
459   switch (LD->getMemOperand()->getSize()) {
460   default:
461     return;
462   case 4:
463     mem_load_op = BPF::LDW;
464     break;
465   case 2:
466     mem_load_op = BPF::LDH;
467     break;
468   case 1:
469     mem_load_op = BPF::LDB;
470     break;
471   }
472
473   DEBUG(dbgs() << "Find Load Value to VReg "
474                << TargetRegisterInfo::virtReg2Index(RegN->getReg()) << '\n');
475   load_to_vreg_[RegN->getReg()] = mem_load_op;
476 }
477
478 void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
479                                       SelectionDAG::allnodes_iterator I) {
480   ConstantSDNode *MaskN = dyn_cast<ConstantSDNode>(Node->getOperand(1));
481   if (!MaskN)
482     return;
483
484   unsigned match_load_op = 0;
485   switch (MaskN->getZExtValue()) {
486   default:
487     return;
488   case 0xFFFFFFFF:
489     match_load_op = BPF::LDW;
490     break;
491   case 0xFFFF:
492     match_load_op = BPF::LDH;
493     break;
494   case 0xFF:
495     match_load_op = BPF::LDB;
496     break;
497   }
498
499   // The Reg operand should be a virtual register, which is defined
500   // outside the current basic block. DAG combiner has done a pretty
501   // good job in removing truncating inside a single basic block.
502   SDValue BaseV = Node->getOperand(0);
503   if (BaseV.getOpcode() != ISD::CopyFromReg)
504     return;
505
506   const RegisterSDNode *RegN =
507       dyn_cast<RegisterSDNode>(BaseV.getNode()->getOperand(1));
508   if (!RegN || !TargetRegisterInfo::isVirtualRegister(RegN->getReg()))
509     return;
510   unsigned AndOpReg = RegN->getReg();
511   DEBUG(dbgs() << "Examine %vreg" << TargetRegisterInfo::virtReg2Index(AndOpReg)
512                << '\n');
513
514   // Examine the PHI insns in the MachineBasicBlock to found out the
515   // definitions of this virtual register. At this stage (DAG2DAG
516   // transformation), only PHI machine insns are available in the machine basic
517   // block.
518   MachineBasicBlock *MBB = FuncInfo->MBB;
519   MachineInstr *MII = nullptr;
520   for (auto &MI : *MBB) {
521     for (unsigned i = 0; i < MI.getNumOperands(); ++i) {
522       const MachineOperand &MOP = MI.getOperand(i);
523       if (!MOP.isReg() || !MOP.isDef())
524         continue;
525       unsigned Reg = MOP.getReg();
526       if (TargetRegisterInfo::isVirtualRegister(Reg) && Reg == AndOpReg) {
527         MII = &MI;
528         break;
529       }
530     }
531   }
532
533   if (MII == nullptr) {
534     // No phi definition in this block.
535     if (!checkLoadDef(AndOpReg, match_load_op))
536       return;
537   } else {
538     // The PHI node looks like:
539     //   %vreg2<def> = PHI %vreg0, <BB#1>, %vreg1, <BB#3>
540     // Trace each incoming definition, e.g., (%vreg0, BB#1) and (%vreg1, BB#3)
541     // The AND operation can be removed if both %vreg0 in BB#1 and %vreg1 in
542     // BB#3 are defined with with a load matching the MaskN.
543     DEBUG(dbgs() << "Check PHI Insn: "; MII->dump(); dbgs() << '\n');
544     unsigned PrevReg = -1;
545     for (unsigned i = 0; i < MII->getNumOperands(); ++i) {
546       const MachineOperand &MOP = MII->getOperand(i);
547       if (MOP.isReg()) {
548         if (MOP.isDef())
549           continue;
550         PrevReg = MOP.getReg();
551         if (!TargetRegisterInfo::isVirtualRegister(PrevReg))
552           return;
553         if (!checkLoadDef(PrevReg, match_load_op))
554           return;
555       }
556     }
557   }
558
559   DEBUG(dbgs() << "Remove the redundant AND operation in: "; Node->dump();
560         dbgs() << '\n');
561
562   I--;
563   CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
564   I++;
565   CurDAG->DeleteNode(Node);
566 }
567
568 bool BPFDAGToDAGISel::checkLoadDef(unsigned DefReg, unsigned match_load_op) {
569   auto it = load_to_vreg_.find(DefReg);
570   if (it == load_to_vreg_.end())
571     return false; // The definition of register is not exported yet.
572
573   return it->second == match_load_op;
574 }
575
576 FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) {
577   return new BPFDAGToDAGISel(TM);
578 }