1*9880d681SAndroid Build Coastguard Worker //===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF ----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines a DAG pattern matching instruction selector for BPF,
11*9880d681SAndroid Build Coastguard Worker // converting from a legalized dag to a BPF dag.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "BPF.h"
16*9880d681SAndroid Build Coastguard Worker #include "BPFRegisterInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "BPFSubtarget.h"
18*9880d681SAndroid Build Coastguard Worker #include "BPFTargetMachine.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "bpf-isel"
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker // Instruction Selector Implementation
35*9880d681SAndroid Build Coastguard Worker namespace {
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker class BPFDAGToDAGISel : public SelectionDAGISel {
38*9880d681SAndroid Build Coastguard Worker public:
BPFDAGToDAGISel(BPFTargetMachine & TM)39*9880d681SAndroid Build Coastguard Worker explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {}
40*9880d681SAndroid Build Coastguard Worker
getPassName() const41*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
42*9880d681SAndroid Build Coastguard Worker return "BPF DAG->DAG Pattern Instruction Selection";
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker private:
46*9880d681SAndroid Build Coastguard Worker // Include the pieces autogenerated from the target description.
47*9880d681SAndroid Build Coastguard Worker #include "BPFGenDAGISel.inc"
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker void Select(SDNode *N) override;
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker // Complex Pattern for address selection.
52*9880d681SAndroid Build Coastguard Worker bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
53*9880d681SAndroid Build Coastguard Worker bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
54*9880d681SAndroid Build Coastguard Worker };
55*9880d681SAndroid Build Coastguard Worker }
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker // ComplexPattern used on BPF Load/Store instructions
SelectAddr(SDValue Addr,SDValue & Base,SDValue & Offset)58*9880d681SAndroid Build Coastguard Worker bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
59*9880d681SAndroid Build Coastguard Worker // if Address is FI, get the TargetFrameIndex.
60*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
61*9880d681SAndroid Build Coastguard Worker if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
62*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
63*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
64*9880d681SAndroid Build Coastguard Worker return true;
65*9880d681SAndroid Build Coastguard Worker }
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
68*9880d681SAndroid Build Coastguard Worker Addr.getOpcode() == ISD::TargetGlobalAddress)
69*9880d681SAndroid Build Coastguard Worker return false;
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker // Addresses of the form Addr+const or Addr|const
72*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
73*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
74*9880d681SAndroid Build Coastguard Worker if (isInt<32>(CN->getSExtValue())) {
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker // If the first operand is a FI, get the TargetFI Node
77*9880d681SAndroid Build Coastguard Worker if (FrameIndexSDNode *FIN =
78*9880d681SAndroid Build Coastguard Worker dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
79*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
80*9880d681SAndroid Build Coastguard Worker else
81*9880d681SAndroid Build Coastguard Worker Base = Addr.getOperand(0);
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
84*9880d681SAndroid Build Coastguard Worker return true;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker Base = Addr;
89*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
90*9880d681SAndroid Build Coastguard Worker return true;
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker // ComplexPattern used on BPF FI instruction
SelectFIAddr(SDValue Addr,SDValue & Base,SDValue & Offset)94*9880d681SAndroid Build Coastguard Worker bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
95*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker if (!CurDAG->isBaseWithConstantOffset(Addr))
98*9880d681SAndroid Build Coastguard Worker return false;
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker // Addresses of the form Addr+const or Addr|const
101*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
102*9880d681SAndroid Build Coastguard Worker if (isInt<32>(CN->getSExtValue())) {
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker // If the first operand is a FI, get the TargetFI Node
105*9880d681SAndroid Build Coastguard Worker if (FrameIndexSDNode *FIN =
106*9880d681SAndroid Build Coastguard Worker dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
107*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
108*9880d681SAndroid Build Coastguard Worker else
109*9880d681SAndroid Build Coastguard Worker return false;
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
112*9880d681SAndroid Build Coastguard Worker return true;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker return false;
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker
Select(SDNode * Node)118*9880d681SAndroid Build Coastguard Worker void BPFDAGToDAGISel::Select(SDNode *Node) {
119*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Node->getOpcode();
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker // Dump information about the Node being selected
122*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n');
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker // If we have a custom node, we already have selected!
125*9880d681SAndroid Build Coastguard Worker if (Node->isMachineOpcode()) {
126*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
127*9880d681SAndroid Build Coastguard Worker return;
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker // tablegen selection should be handled here.
131*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
132*9880d681SAndroid Build Coastguard Worker default: break;
133*9880d681SAndroid Build Coastguard Worker case ISD::SDIV: {
134*9880d681SAndroid Build Coastguard Worker DebugLoc Empty;
135*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL = Node->getDebugLoc();
136*9880d681SAndroid Build Coastguard Worker if (DL != Empty)
137*9880d681SAndroid Build Coastguard Worker errs() << "Error at line " << DL.getLine() << ": ";
138*9880d681SAndroid Build Coastguard Worker else
139*9880d681SAndroid Build Coastguard Worker errs() << "Error: ";
140*9880d681SAndroid Build Coastguard Worker errs() << "Unsupport signed division for DAG: ";
141*9880d681SAndroid Build Coastguard Worker Node->dump(CurDAG);
142*9880d681SAndroid Build Coastguard Worker errs() << "Please convert to unsigned div/mod.\n";
143*9880d681SAndroid Build Coastguard Worker break;
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker case ISD::INTRINSIC_W_CHAIN: {
146*9880d681SAndroid Build Coastguard Worker unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
147*9880d681SAndroid Build Coastguard Worker switch (IntNo) {
148*9880d681SAndroid Build Coastguard Worker case Intrinsic::bpf_load_byte:
149*9880d681SAndroid Build Coastguard Worker case Intrinsic::bpf_load_half:
150*9880d681SAndroid Build Coastguard Worker case Intrinsic::bpf_load_word: {
151*9880d681SAndroid Build Coastguard Worker SDLoc DL(Node);
152*9880d681SAndroid Build Coastguard Worker SDValue Chain = Node->getOperand(0);
153*9880d681SAndroid Build Coastguard Worker SDValue N1 = Node->getOperand(1);
154*9880d681SAndroid Build Coastguard Worker SDValue Skb = Node->getOperand(2);
155*9880d681SAndroid Build Coastguard Worker SDValue N3 = Node->getOperand(3);
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
158*9880d681SAndroid Build Coastguard Worker Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb, SDValue());
159*9880d681SAndroid Build Coastguard Worker Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
160*9880d681SAndroid Build Coastguard Worker break;
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker break;
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker case ISD::FrameIndex: {
167*9880d681SAndroid Build Coastguard Worker int FI = cast<FrameIndexSDNode>(Node)->getIndex();
168*9880d681SAndroid Build Coastguard Worker EVT VT = Node->getValueType(0);
169*9880d681SAndroid Build Coastguard Worker SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
170*9880d681SAndroid Build Coastguard Worker unsigned Opc = BPF::MOV_rr;
171*9880d681SAndroid Build Coastguard Worker if (Node->hasOneUse()) {
172*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
173*9880d681SAndroid Build Coastguard Worker return;
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI));
176*9880d681SAndroid Build Coastguard Worker return;
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker // Select the default instruction
181*9880d681SAndroid Build Coastguard Worker SelectCode(Node);
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
createBPFISelDag(BPFTargetMachine & TM)184*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) {
185*9880d681SAndroid Build Coastguard Worker return new BPFDAGToDAGISel(TM);
186*9880d681SAndroid Build Coastguard Worker }
187