blob: d99d49075d89c2626549a7c2c45480a366a83389 [file] [log] [blame]
Eric Christopher50880d02010-09-18 18:52:28 +00001//===-- 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"
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000017#include "llvm/DerivedTypes.h"
Justin Holewinski67a91842011-06-23 18:10:03 +000018#include "llvm/Support/Debug.h"
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000019#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000020
21using namespace llvm;
22
23namespace {
24// PTXDAGToDAGISel - PTX specific code to select PTX machine
25// instructions for SelectionDAG operations.
26class PTXDAGToDAGISel : public SelectionDAGISel {
27 public:
28 PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
29
30 virtual const char *getPassName() const {
31 return "PTX DAG->DAG Pattern Instruction Selection";
32 }
33
34 SDNode *Select(SDNode *Node);
35
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000036 // Complex Pattern Selectors.
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000037 bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000038 bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
39 bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000040 bool SelectADDRlocal(SDValue &Addr, SDValue &Base, SDValue &Offset);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000041
Eric Christopher50880d02010-09-18 18:52:28 +000042 // Include the pieces auto'gened from the target description
43#include "PTXGenDAGISel.inc"
44
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000045 private:
Che-Liang Chiou88d33672011-03-18 11:08:52 +000046 // 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
Justin Holewinski5422a0f2011-09-22 16:45:46 +000050 SDNode *SelectREADPARAM(SDNode *Node);
51 SDNode *SelectWRITEPARAM(SDNode *Node);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000052 SDNode *SelectFrameIndex(SDNode *Node);
Justin Holewinski5422a0f2011-09-22 16:45:46 +000053
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000054 bool isImm(const SDValue &operand);
55 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000056
57 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000058}; // class PTXDAGToDAGISel
59} // namespace
60
61// createPTXISelDag - This pass converts a legalized DAG into a
62// PTX-specific DAG, ready for instruction scheduling
63FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
64 CodeGenOpt::Level OptLevel) {
65 return new PTXDAGToDAGISel(TM, OptLevel);
66}
67
68PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
69 CodeGenOpt::Level OptLevel)
70 : SelectionDAGISel(TM, OptLevel) {}
71
72SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000073 switch (Node->getOpcode()) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000074 case ISD::BRCOND:
75 return SelectBRCOND(Node);
Justin Holewinski5422a0f2011-09-22 16:45:46 +000076 case PTXISD::READ_PARAM:
77 return SelectREADPARAM(Node);
78 case PTXISD::WRITE_PARAM:
79 return SelectWRITEPARAM(Node);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000080 case ISD::FrameIndex:
81 return SelectFrameIndex(Node);
Che-Liang Chiou88d33672011-03-18 11:08:52 +000082 default:
83 return SelectCode(Node);
84 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000085}
86
Che-Liang Chiou88d33672011-03-18 11:08:52 +000087SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
88 assert(Node->getNumOperands() >= 3);
89
90 SDValue Chain = Node->getOperand(0);
91 SDValue Pred = Node->getOperand(1);
92 SDValue Target = Node->getOperand(2); // branch target
93 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
94 DebugLoc dl = Node->getDebugLoc();
95
96 assert(Target.getOpcode() == ISD::BasicBlock);
97 assert(Pred.getValueType() == MVT::i1);
98
99 // Emit BRAdp
100 SDValue Ops[] = { Target, Pred, PredOp, Chain };
101 return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
102}
103
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000104SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
105 SDValue Chain = Node->getOperand(0);
106 SDValue Index = Node->getOperand(1);
107
108 int OpCode;
109
110 // Get the type of parameter we are reading
111 EVT VT = Node->getValueType(0);
112 assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
113
114 MVT Type = VT.getSimpleVT();
115
116 if (Type == MVT::i1)
117 OpCode = PTX::READPARAMPRED;
118 else if (Type == MVT::i16)
119 OpCode = PTX::READPARAMI16;
120 else if (Type == MVT::i32)
121 OpCode = PTX::READPARAMI32;
122 else if (Type == MVT::i64)
123 OpCode = PTX::READPARAMI64;
124 else if (Type == MVT::f32)
125 OpCode = PTX::READPARAMF32;
126 else if (Type == MVT::f64)
127 OpCode = PTX::READPARAMF64;
128
129 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
130 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
131 DebugLoc dl = Node->getDebugLoc();
132
133 SDValue Ops[] = { Index, Pred, PredOp, Chain };
134 return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
135}
136
137SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
138
139 SDValue Chain = Node->getOperand(0);
140 SDValue Value = Node->getOperand(1);
141
142 int OpCode;
143
144 //Node->dumpr(CurDAG);
145
146 // Get the type of parameter we are writing
147 EVT VT = Value->getValueType(0);
148 assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
149
150 MVT Type = VT.getSimpleVT();
151
152 if (Type == MVT::i1)
153 OpCode = PTX::WRITEPARAMPRED;
154 else if (Type == MVT::i16)
155 OpCode = PTX::WRITEPARAMI16;
156 else if (Type == MVT::i32)
157 OpCode = PTX::WRITEPARAMI32;
158 else if (Type == MVT::i64)
159 OpCode = PTX::WRITEPARAMI64;
160 else if (Type == MVT::f32)
161 OpCode = PTX::WRITEPARAMF32;
162 else if (Type == MVT::f64)
163 OpCode = PTX::WRITEPARAMF64;
164 else
165 llvm_unreachable("Invalid type in SelectWRITEPARAM");
166
167 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
168 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
169 DebugLoc dl = Node->getDebugLoc();
170
171 SDValue Ops[] = { Value, Pred, PredOp, Chain };
172 SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
173
174 //dbgs() << "SelectWRITEPARAM produced:\n\t";
175 //Ret->dumpr(CurDAG);
176
177 return Ret;
178}
179
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000180SDNode *PTXDAGToDAGISel::SelectFrameIndex(SDNode *Node) {
181 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
182 //dbgs() << "Selecting FrameIndex at index " << FI << "\n";
183 SDValue TFI = CurDAG->getTargetFrameIndex(FI, Node->getValueType(0));
184
185 //unsigned OpCode = PTX::LOAD_LOCAL_F32;
186
187 //for (SDNode::use_iterator i = Node->use_begin(), e = Node->use_end();
188 // i != e; ++i) {
189 // SDNode *Use = *i;
190 // dbgs() << "USE: ";
191 // Use->dumpr(CurDAG);
192 //}
193
194 return Node;
195 //return CurDAG->getMachineNode(OpCode, Node->getDebugLoc(),
196 // Node->getValueType(0), TFI);
197}
198
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000199// Match memory operand of the form [reg+reg]
200bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
201 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
202 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
203 return false;
204
Justin Holewinskid6625762011-03-23 16:58:51 +0000205 assert(Addr.getValueType().isSimple() && "Type must be simple");
206
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000207 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000208 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
209
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000210 return true;
211}
212
213// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000214bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
215 SDValue &Offset) {
Justin Holewinski63602ed2011-09-26 18:57:22 +0000216 // FrameIndex addresses are handled separately
217 //errs() << "SelectADDRri: ";
218 //Addr.getNode()->dumpr();
219 if (isa<FrameIndexSDNode>(Addr)) {
220 //errs() << "Failure\n";
221 return false;
222 }
223
224 if (CurDAG->isBaseWithConstantOffset(Addr)) {
225 Base = Addr.getOperand(0);
226 if (isa<FrameIndexSDNode>(Base)) {
227 //errs() << "Failure\n";
228 return false;
229 }
230 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
231 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
232 //errs() << "Success\n";
233 return true;
234 }
235
236 /*if (Addr.getNumOperands() == 1) {
237 Base = Addr;
238 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
239 errs() << "Success\n";
240 return true;
241 }*/
242
243 //errs() << "SelectADDRri fails on: ";
244 //Addr.getNode()->dumpr();
245
246 if (isImm(Addr)) {
247 //errs() << "Failure\n";
248 return false;
249 }
250
251 Base = Addr;
252 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
253
254 //errs() << "Success\n";
255 return true;
256
257 /*if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000258 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000259 if (isImm(Addr))
260 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000261 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000262
263 assert(Addr.getValueType().isSimple() && "Type must be simple");
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000264 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000265 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
266
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000267 return true;
268 }
269
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000270 if (Addr.getNumOperands() < 2)
271 return false;
272
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000273 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000274 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000275 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000276
277 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000278 for (int i = 0; i < 2; i ++)
279 if (SelectImm(Addr.getOperand(1-i), Offset)) {
280 Base = Addr.getOperand(i);
281 return true;
282 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000283
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000284 // neither [reg+imm] nor [imm+reg]
Justin Holewinski63602ed2011-09-26 18:57:22 +0000285 return false;*/
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000286}
287
288// Match memory operand of the form [imm+imm] and [imm]
289bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
290 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000291 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000292 if (Addr.getOpcode() == ISD::ADD) {
293 return SelectImm(Addr.getOperand(0), Base) &&
294 SelectImm(Addr.getOperand(1), Offset);
295 }
296
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000297 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000298 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000299 assert(Addr.getValueType().isSimple() && "Type must be simple");
300
301 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
302
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000303 return true;
304 }
305
306 return false;
307}
308
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000309// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
310bool PTXDAGToDAGISel::SelectADDRlocal(SDValue &Addr, SDValue &Base,
311 SDValue &Offset) {
Justin Holewinski63602ed2011-09-26 18:57:22 +0000312 //errs() << "SelectADDRlocal: ";
313 //Addr.getNode()->dumpr();
314 if (isa<FrameIndexSDNode>(Addr)) {
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000315 Base = Addr;
316 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
Justin Holewinski63602ed2011-09-26 18:57:22 +0000317 //errs() << "Success\n";
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000318 return true;
319 }
320
Justin Holewinski63602ed2011-09-26 18:57:22 +0000321 if (CurDAG->isBaseWithConstantOffset(Addr)) {
322 Base = Addr.getOperand(0);
323 if (!isa<FrameIndexSDNode>(Base)) {
324 //errs() << "Failure\n";
325 return false;
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000326 }
Justin Holewinski63602ed2011-09-26 18:57:22 +0000327 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
328 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
329 //errs() << "Offset: ";
330 //Offset.getNode()->dumpr();
331 //errs() << "Success\n";
332 return true;
333 }
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000334
Justin Holewinski63602ed2011-09-26 18:57:22 +0000335 //errs() << "Failure\n";
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000336 return false;
337}
338
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000339bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
340 return ConstantSDNode::classof(operand.getNode());
341}
342
343bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
344 SDNode *node = operand.getNode();
345 if (!ConstantSDNode::classof(node))
346 return false;
347
348 ConstantSDNode *CN = cast<ConstantSDNode>(node);
Justin Holewinskid6625762011-03-23 16:58:51 +0000349 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
350 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000351 return true;
352}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000353
354const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
355{
356 return TM.getSubtarget<PTXSubtarget>();
357}
358