blob: c722e8acb086e327918468ce075e4ac7cd4a707d [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"
Justin Holewinskif47dfba2011-09-27 18:12:55 +000015#include "PTXMachineFunctionInfo.h"
Eric Christopher50880d02010-09-18 18:52:28 +000016#include "PTXTargetMachine.h"
Justin Holewinskif47dfba2011-09-27 18:12:55 +000017#include "llvm/ADT/StringExtras.h"
Eric Christopher50880d02010-09-18 18:52:28 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000019#include "llvm/DerivedTypes.h"
Justin Holewinski67a91842011-06-23 18:10:03 +000020#include "llvm/Support/Debug.h"
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000021#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000022
23using namespace llvm;
24
25namespace {
26// PTXDAGToDAGISel - PTX specific code to select PTX machine
27// instructions for SelectionDAG operations.
28class PTXDAGToDAGISel : public SelectionDAGISel {
29 public:
30 PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
31
32 virtual const char *getPassName() const {
33 return "PTX DAG->DAG Pattern Instruction Selection";
34 }
35
36 SDNode *Select(SDNode *Node);
37
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000038 // Complex Pattern Selectors.
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000039 bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000040 bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
41 bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000042 bool SelectADDRlocal(SDValue &Addr, SDValue &Base, SDValue &Offset);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000043
Eric Christopher50880d02010-09-18 18:52:28 +000044 // Include the pieces auto'gened from the target description
45#include "PTXGenDAGISel.inc"
46
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000047 private:
Che-Liang Chiou88d33672011-03-18 11:08:52 +000048 // We need this only because we can't match intruction BRAdp
49 // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
50 SDNode *SelectBRCOND(SDNode *Node);
51
Justin Holewinski5422a0f2011-09-22 16:45:46 +000052 SDNode *SelectREADPARAM(SDNode *Node);
53 SDNode *SelectWRITEPARAM(SDNode *Node);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000054 SDNode *SelectFrameIndex(SDNode *Node);
Justin Holewinski5422a0f2011-09-22 16:45:46 +000055
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000056 bool isImm(const SDValue &operand);
57 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000058
59 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000060}; // class PTXDAGToDAGISel
61} // namespace
62
63// createPTXISelDag - This pass converts a legalized DAG into a
64// PTX-specific DAG, ready for instruction scheduling
65FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
66 CodeGenOpt::Level OptLevel) {
67 return new PTXDAGToDAGISel(TM, OptLevel);
68}
69
70PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
71 CodeGenOpt::Level OptLevel)
72 : SelectionDAGISel(TM, OptLevel) {}
73
74SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000075 switch (Node->getOpcode()) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000076 case ISD::BRCOND:
77 return SelectBRCOND(Node);
Justin Holewinski5422a0f2011-09-22 16:45:46 +000078 case PTXISD::READ_PARAM:
79 return SelectREADPARAM(Node);
80 case PTXISD::WRITE_PARAM:
81 return SelectWRITEPARAM(Node);
Justin Holewinski6b8990d2011-09-26 16:20:25 +000082 case ISD::FrameIndex:
83 return SelectFrameIndex(Node);
Che-Liang Chiou88d33672011-03-18 11:08:52 +000084 default:
85 return SelectCode(Node);
86 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000087}
88
Che-Liang Chiou88d33672011-03-18 11:08:52 +000089SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
90 assert(Node->getNumOperands() >= 3);
91
92 SDValue Chain = Node->getOperand(0);
93 SDValue Pred = Node->getOperand(1);
94 SDValue Target = Node->getOperand(2); // branch target
95 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
96 DebugLoc dl = Node->getDebugLoc();
97
98 assert(Target.getOpcode() == ISD::BasicBlock);
99 assert(Pred.getValueType() == MVT::i1);
100
101 // Emit BRAdp
102 SDValue Ops[] = { Target, Pred, PredOp, Chain };
103 return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
104}
105
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000106SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
107 SDValue Chain = Node->getOperand(0);
108 SDValue Index = Node->getOperand(1);
109
110 int OpCode;
111
112 // Get the type of parameter we are reading
113 EVT VT = Node->getValueType(0);
114 assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
115
116 MVT Type = VT.getSimpleVT();
117
118 if (Type == MVT::i1)
119 OpCode = PTX::READPARAMPRED;
120 else if (Type == MVT::i16)
121 OpCode = PTX::READPARAMI16;
122 else if (Type == MVT::i32)
123 OpCode = PTX::READPARAMI32;
124 else if (Type == MVT::i64)
125 OpCode = PTX::READPARAMI64;
126 else if (Type == MVT::f32)
127 OpCode = PTX::READPARAMF32;
128 else if (Type == MVT::f64)
129 OpCode = PTX::READPARAMF64;
130
131 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
132 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
133 DebugLoc dl = Node->getDebugLoc();
134
135 SDValue Ops[] = { Index, Pred, PredOp, Chain };
136 return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
137}
138
139SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
140
141 SDValue Chain = Node->getOperand(0);
142 SDValue Value = Node->getOperand(1);
143
144 int OpCode;
145
146 //Node->dumpr(CurDAG);
147
148 // Get the type of parameter we are writing
149 EVT VT = Value->getValueType(0);
150 assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
151
152 MVT Type = VT.getSimpleVT();
153
154 if (Type == MVT::i1)
155 OpCode = PTX::WRITEPARAMPRED;
156 else if (Type == MVT::i16)
157 OpCode = PTX::WRITEPARAMI16;
158 else if (Type == MVT::i32)
159 OpCode = PTX::WRITEPARAMI32;
160 else if (Type == MVT::i64)
161 OpCode = PTX::WRITEPARAMI64;
162 else if (Type == MVT::f32)
163 OpCode = PTX::WRITEPARAMF32;
164 else if (Type == MVT::f64)
165 OpCode = PTX::WRITEPARAMF64;
166 else
167 llvm_unreachable("Invalid type in SelectWRITEPARAM");
168
169 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
170 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
171 DebugLoc dl = Node->getDebugLoc();
172
173 SDValue Ops[] = { Value, Pred, PredOp, Chain };
174 SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
175
176 //dbgs() << "SelectWRITEPARAM produced:\n\t";
177 //Ret->dumpr(CurDAG);
178
179 return Ret;
180}
181
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000182SDNode *PTXDAGToDAGISel::SelectFrameIndex(SDNode *Node) {
183 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
184 //dbgs() << "Selecting FrameIndex at index " << FI << "\n";
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000185 //SDValue TFI = CurDAG->getTargetFrameIndex(FI, Node->getValueType(0));
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000186
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000187 PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000188
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000189 SDValue FrameSymbol = CurDAG->getTargetExternalSymbol(MFI->getFrameSymbol(FI),
190 Node->getValueType(0));
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000191
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000192 return FrameSymbol.getNode();
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000193}
194
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000195// Match memory operand of the form [reg+reg]
196bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
197 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
198 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
199 return false;
200
Justin Holewinskid6625762011-03-23 16:58:51 +0000201 assert(Addr.getValueType().isSimple() && "Type must be simple");
202
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000203 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000204 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
205
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000206 return true;
207}
208
209// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000210bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
211 SDValue &Offset) {
Justin Holewinski63602ed2011-09-26 18:57:22 +0000212 // FrameIndex addresses are handled separately
213 //errs() << "SelectADDRri: ";
214 //Addr.getNode()->dumpr();
215 if (isa<FrameIndexSDNode>(Addr)) {
216 //errs() << "Failure\n";
217 return false;
218 }
219
220 if (CurDAG->isBaseWithConstantOffset(Addr)) {
221 Base = Addr.getOperand(0);
222 if (isa<FrameIndexSDNode>(Base)) {
223 //errs() << "Failure\n";
224 return false;
225 }
226 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
227 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
228 //errs() << "Success\n";
229 return true;
230 }
231
232 /*if (Addr.getNumOperands() == 1) {
233 Base = Addr;
234 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
235 errs() << "Success\n";
236 return true;
237 }*/
238
239 //errs() << "SelectADDRri fails on: ";
240 //Addr.getNode()->dumpr();
241
242 if (isImm(Addr)) {
243 //errs() << "Failure\n";
244 return false;
245 }
246
247 Base = Addr;
248 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
249
250 //errs() << "Success\n";
251 return true;
252
253 /*if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000254 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000255 if (isImm(Addr))
256 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000257 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000258
259 assert(Addr.getValueType().isSimple() && "Type must be simple");
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000260 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000261 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
262
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000263 return true;
264 }
265
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000266 if (Addr.getNumOperands() < 2)
267 return false;
268
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000269 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000270 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000271 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000272
273 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000274 for (int i = 0; i < 2; i ++)
275 if (SelectImm(Addr.getOperand(1-i), Offset)) {
276 Base = Addr.getOperand(i);
277 return true;
278 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000279
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000280 // neither [reg+imm] nor [imm+reg]
Justin Holewinski63602ed2011-09-26 18:57:22 +0000281 return false;*/
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000282}
283
284// Match memory operand of the form [imm+imm] and [imm]
285bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
286 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000287 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000288 if (Addr.getOpcode() == ISD::ADD) {
289 return SelectImm(Addr.getOperand(0), Base) &&
290 SelectImm(Addr.getOperand(1), Offset);
291 }
292
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000293 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000294 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000295 assert(Addr.getValueType().isSimple() && "Type must be simple");
296
297 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
298
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000299 return true;
300 }
301
302 return false;
303}
304
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000305// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
306bool PTXDAGToDAGISel::SelectADDRlocal(SDValue &Addr, SDValue &Base,
307 SDValue &Offset) {
Justin Holewinski63602ed2011-09-26 18:57:22 +0000308 //errs() << "SelectADDRlocal: ";
309 //Addr.getNode()->dumpr();
310 if (isa<FrameIndexSDNode>(Addr)) {
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000311 Base = Addr;
312 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
Justin Holewinski63602ed2011-09-26 18:57:22 +0000313 //errs() << "Success\n";
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000314 return true;
315 }
316
Justin Holewinski63602ed2011-09-26 18:57:22 +0000317 if (CurDAG->isBaseWithConstantOffset(Addr)) {
318 Base = Addr.getOperand(0);
319 if (!isa<FrameIndexSDNode>(Base)) {
320 //errs() << "Failure\n";
321 return false;
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000322 }
Justin Holewinski63602ed2011-09-26 18:57:22 +0000323 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
324 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
325 //errs() << "Offset: ";
326 //Offset.getNode()->dumpr();
327 //errs() << "Success\n";
328 return true;
329 }
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000330
Justin Holewinski63602ed2011-09-26 18:57:22 +0000331 //errs() << "Failure\n";
Justin Holewinski6b8990d2011-09-26 16:20:25 +0000332 return false;
333}
334
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000335bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
336 return ConstantSDNode::classof(operand.getNode());
337}
338
339bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
340 SDNode *node = operand.getNode();
341 if (!ConstantSDNode::classof(node))
342 return false;
343
344 ConstantSDNode *CN = cast<ConstantSDNode>(node);
Justin Holewinskid6625762011-03-23 16:58:51 +0000345 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
346 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000347 return true;
348}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000349
350const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
351{
352 return TM.getSubtarget<PTXSubtarget>();
353}
354