LLVM  3.7.0
BPFISelDAGToDAG.cpp
Go to the documentation of this file.
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"
25 #include "llvm/IR/IntrinsicInst.h"
26 #include "llvm/Support/Debug.h"
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "bpf-isel"
33 
34 // Instruction Selector Implementation
35 namespace {
36 
37 class BPFDAGToDAGISel : public SelectionDAGISel {
38 public:
39  explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {}
40 
41  const char *getPassName() const override {
42  return "BPF DAG->DAG Pattern Instruction Selection";
43  }
44 
45 private:
46 // Include the pieces autogenerated from the target description.
47 #include "BPFGenDAGISel.inc"
48 
49  SDNode *Select(SDNode *N) override;
50 
51  // Complex Pattern for address selection.
52  bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
53 };
54 }
55 
56 // ComplexPattern used on BPF Load/Store instructions
57 bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
58  // if Address is FI, get the TargetFrameIndex.
59  SDLoc DL(Addr);
60  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
61  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
62  Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
63  return true;
64  }
65 
66  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
68  return false;
69 
70  // Addresses of the form FI+const or FI|const
71  if (CurDAG->isBaseWithConstantOffset(Addr)) {
73  if (isInt<32>(CN->getSExtValue())) {
74 
75  // If the first operand is a FI, get the TargetFI Node
76  if (FrameIndexSDNode *FIN =
77  dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
78  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
79  else
80  Base = Addr.getOperand(0);
81 
82  Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
83  return true;
84  }
85  }
86 
87  Base = Addr;
88  Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
89  return true;
90 }
91 
93  unsigned Opcode = Node->getOpcode();
94 
95  // Dump information about the Node being selected
96  DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n');
97 
98  // If we have a custom node, we already have selected!
99  if (Node->isMachineOpcode()) {
100  DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
101  return NULL;
102  }
103 
104  // tablegen selection should be handled here.
105  switch (Opcode) {
106  default: break;
107 
108  case ISD::UNDEF: {
109  errs() << "BUG: "; Node->dump(CurDAG); errs() << '\n';
110  report_fatal_error("shouldn't see UNDEF during Select");
111  break;
112  }
113 
114  case ISD::INTRINSIC_W_CHAIN: {
115  unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
116  switch (IntNo) {
117  case Intrinsic::bpf_load_byte:
118  case Intrinsic::bpf_load_half:
119  case Intrinsic::bpf_load_word: {
120  SDLoc DL(Node);
121  SDValue Chain = Node->getOperand(0);
122  SDValue N1 = Node->getOperand(1);
123  SDValue Skb = Node->getOperand(2);
124  SDValue N3 = Node->getOperand(3);
125 
126  SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
127  Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb, SDValue());
128  Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
129  break;
130  }
131  }
132  break;
133  }
134 
135  case ISD::FrameIndex: {
136  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
137  EVT VT = Node->getValueType(0);
138  SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
139  unsigned Opc = BPF::MOV_rr;
140  if (Node->hasOneUse())
141  return CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
142  return CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI);
143  }
144  }
145 
146  // Select the default instruction
147  SDNode *ResNode = SelectCode(Node);
148 
149  DEBUG(dbgs() << "=> ";
150  if (ResNode == nullptr || ResNode == Node)
151  Node->dump(CurDAG);
152  else
153  ResNode->dump(CurDAG);
154  dbgs() << '\n');
155  return ResNode;
156 }
157 
159  return new BPFDAGToDAGISel(TM);
160 }
bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:276
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void dump() const
Dump this node, for debugging.
bool hasOneUse() const
Return true if there is exactly one use of this node.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:122
const SDValue & getOperand(unsigned Num) const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:150
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
UNDEF - An undefined node.
Definition: ISDOpcodes.h:169
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
EVT - Extended Value Type.
Definition: ValueTypes.h:31
#define R6(n)
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:123
int64_t getSExtValue() const
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
#define N
#define DEBUG(X)
Definition: Debug.h:92
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...