ptx: add ld instruction and test
[oota-llvm.git] / lib / Target / PTX / PTXISelDAGToDAG.cpp
1 //===-- PTXISelDAGToDAG.cpp - A dag to dag inst selector for PTX ----------===//
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 an instruction selector for the PTX target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "PTX.h"
15 #include "PTXTargetMachine.h"
16 #include "llvm/CodeGen/SelectionDAGISel.h"
17 #include "llvm/DerivedTypes.h"
18
19 using namespace llvm;
20
21 namespace {
22 // PTXDAGToDAGISel - PTX specific code to select PTX machine
23 // instructions for SelectionDAG operations.
24 class PTXDAGToDAGISel : public SelectionDAGISel {
25   public:
26     PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
27
28     virtual const char *getPassName() const {
29       return "PTX DAG->DAG Pattern Instruction Selection";
30     }
31
32     SDNode *Select(SDNode *Node);
33
34     // Complex Pattern Selectors.
35     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
36     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
37     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
38
39     // Include the pieces auto'gened from the target description
40 #include "PTXGenDAGISel.inc"
41
42   private:
43     bool isImm(const SDValue &operand);
44     bool SelectImm(const SDValue &operand, SDValue &imm);
45 }; // class PTXDAGToDAGISel
46 } // namespace
47
48 // createPTXISelDag - This pass converts a legalized DAG into a
49 // PTX-specific DAG, ready for instruction scheduling
50 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
51                                      CodeGenOpt::Level OptLevel) {
52   return new PTXDAGToDAGISel(TM, OptLevel);
53 }
54
55 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
56                                  CodeGenOpt::Level OptLevel)
57   : SelectionDAGISel(TM, OptLevel) {}
58
59 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
60   // SelectCode() is auto'gened
61   return SelectCode(Node);
62 }
63
64 // Match memory operand of the form [reg+reg]
65 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
66   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
67       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
68     return false;
69
70   R1 = Addr.getOperand(0);
71   R2 = Addr.getOperand(1);
72   return true;
73 }
74
75 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
76 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
77                                    SDValue &Offset) {
78   if (Addr.getOpcode() != ISD::ADD) {
79     if (isImm(Addr))
80       return false;
81     // is [reg] but not [imm]
82     Base = Addr;
83     Offset = CurDAG->getTargetConstant(0, MVT::i32);
84     return true;
85   }
86
87   // let SelectADDRii handle the [imm+imm] case
88   if (Addr.getNumOperands() >= 2 &&
89       isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
90     return false;
91
92   // try [reg+imm] and [imm+reg]
93   for (int i = 0; i < 2; i ++)
94     if (SelectImm(Addr.getOperand(1-i), Offset)) {
95       Base = Addr.getOperand(i);
96       return true;
97     }
98
99   // either [reg+imm] and [imm+reg]
100   for (int i = 0; i < 2; i ++)
101     if (SelectImm(Addr.getOperand(1-i), Offset)) {
102       Base = Addr.getOperand(i);
103       return true;
104     }
105
106   return false;
107 }
108
109 // Match memory operand of the form [imm+imm] and [imm]
110 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
111                                    SDValue &Offset) {
112   // is [imm+imm]?
113   if (Addr.getOpcode() == ISD::ADD) {
114     return SelectImm(Addr.getOperand(0), Base) &&
115            SelectImm(Addr.getOperand(1), Offset);
116   }
117
118   // is [imm]?
119   if (SelectImm(Addr, Base)) {
120     Offset = CurDAG->getTargetConstant(0, MVT::i32);
121     return true;
122   }
123
124   return false;
125 }
126
127 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
128   return ConstantSDNode::classof(operand.getNode());
129 }
130
131 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
132   SDNode *node = operand.getNode();
133   if (!ConstantSDNode::classof(node))
134     return false;
135
136   ConstantSDNode *CN = cast<ConstantSDNode>(node);
137   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32);
138   return true;
139 }