PTX: Finish new calling convention implementation
[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 #include "llvm/Support/raw_ostream.h"
19
20 using namespace llvm;
21
22 namespace {
23 // PTXDAGToDAGISel - PTX specific code to select PTX machine
24 // instructions for SelectionDAG operations.
25 class PTXDAGToDAGISel : public SelectionDAGISel {
26   public:
27     PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
28
29     virtual const char *getPassName() const {
30       return "PTX DAG->DAG Pattern Instruction Selection";
31     }
32
33     SDNode *Select(SDNode *Node);
34
35     // Complex Pattern Selectors.
36     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
37     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
38     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
39
40     // Include the pieces auto'gened from the target description
41 #include "PTXGenDAGISel.inc"
42
43   private:
44     SDNode *SelectREAD_PARAM(SDNode *Node);
45
46     // We need this only because we can't match intruction BRAdp
47     // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
48     SDNode *SelectBRCOND(SDNode *Node);
49
50     bool isImm(const SDValue &operand);
51     bool SelectImm(const SDValue &operand, SDValue &imm);
52
53     const PTXSubtarget& getSubtarget() const;
54 }; // class PTXDAGToDAGISel
55 } // namespace
56
57 // createPTXISelDag - This pass converts a legalized DAG into a
58 // PTX-specific DAG, ready for instruction scheduling
59 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
60                                      CodeGenOpt::Level OptLevel) {
61   return new PTXDAGToDAGISel(TM, OptLevel);
62 }
63
64 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
65                                  CodeGenOpt::Level OptLevel)
66   : SelectionDAGISel(TM, OptLevel) {}
67
68 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
69   switch (Node->getOpcode()) {
70     case PTXISD::READ_PARAM:
71       return SelectREAD_PARAM(Node);
72     case ISD::BRCOND:
73       return SelectBRCOND(Node);
74     default:
75       return SelectCode(Node);
76   }
77 }
78
79 SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
80   SDValue  index = Node->getOperand(1);
81   DebugLoc dl    = Node->getDebugLoc();
82   unsigned opcode;
83
84   if (index.getOpcode() != ISD::TargetConstant)
85     llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
86
87   if (Node->getValueType(0) == MVT::i16) {
88     opcode = PTX::LDpiU16;
89   }
90   else if (Node->getValueType(0) == MVT::i32) {
91     opcode = PTX::LDpiU32;
92   }
93   else if (Node->getValueType(0) == MVT::i64) {
94     opcode = PTX::LDpiU64;
95   }
96   else if (Node->getValueType(0) == MVT::f32) {
97     opcode = PTX::LDpiF32;
98   }
99   else if (Node->getValueType(0) == MVT::f64) {
100     opcode = PTX::LDpiF64;
101   }
102   else {
103     llvm_unreachable("Unknown parameter type for ld.param");
104   }
105
106   return PTXInstrInfo::
107     GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index);
108 }
109
110 SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
111   assert(Node->getNumOperands() >= 3);
112
113   SDValue Chain  = Node->getOperand(0);
114   SDValue Pred   = Node->getOperand(1);
115   SDValue Target = Node->getOperand(2); // branch target
116   SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
117   DebugLoc dl = Node->getDebugLoc();
118
119   assert(Target.getOpcode()  == ISD::BasicBlock);
120   assert(Pred.getValueType() == MVT::i1);
121
122   // Emit BRAdp
123   SDValue Ops[] = { Target, Pred, PredOp, Chain };
124   return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
125 }
126
127 // Match memory operand of the form [reg+reg]
128 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
129   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
130       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
131     return false;
132
133   assert(Addr.getValueType().isSimple() && "Type must be simple");
134
135   R1 = Addr;
136   R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
137
138   return true;
139 }
140
141 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
142 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
143                                    SDValue &Offset) {
144   if (Addr.getOpcode() != ISD::ADD) {
145     // let SelectADDRii handle the [imm] case
146     if (isImm(Addr))
147       return false;
148     // it is [reg]
149
150     assert(Addr.getValueType().isSimple() && "Type must be simple");
151
152     Base = Addr;
153     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
154
155     return true;
156   }
157
158   if (Addr.getNumOperands() < 2)
159     return false;
160
161   // let SelectADDRii handle the [imm+imm] case
162   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
163     return false;
164
165   // try [reg+imm] and [imm+reg]
166   for (int i = 0; i < 2; i ++)
167     if (SelectImm(Addr.getOperand(1-i), Offset)) {
168       Base = Addr.getOperand(i);
169       return true;
170     }
171
172   // neither [reg+imm] nor [imm+reg]
173   return false;
174 }
175
176 // Match memory operand of the form [imm+imm] and [imm]
177 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
178                                    SDValue &Offset) {
179   // is [imm+imm]?
180   if (Addr.getOpcode() == ISD::ADD) {
181     return SelectImm(Addr.getOperand(0), Base) &&
182            SelectImm(Addr.getOperand(1), Offset);
183   }
184
185   // is [imm]?
186   if (SelectImm(Addr, Base)) {
187     assert(Addr.getValueType().isSimple() && "Type must be simple");
188
189     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
190
191     return true;
192   }
193
194   return false;
195 }
196
197 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
198   return ConstantSDNode::classof(operand.getNode());
199 }
200
201 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
202   SDNode *node = operand.getNode();
203   if (!ConstantSDNode::classof(node))
204     return false;
205
206   ConstantSDNode *CN = cast<ConstantSDNode>(node);
207   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
208                                   operand.getValueType());
209   return true;
210 }
211
212 const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
213 {
214   return TM.getSubtarget<PTXSubtarget>();
215 }
216