blob: 685b24ecfcc33736751e352d7eb6ce046a243dc3 [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);
40
Eric Christopher50880d02010-09-18 18:52:28 +000041 // Include the pieces auto'gened from the target description
42#include "PTXGenDAGISel.inc"
43
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000044 private:
Che-Liang Chiou88d33672011-03-18 11:08:52 +000045 // We need this only because we can't match intruction BRAdp
46 // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
47 SDNode *SelectBRCOND(SDNode *Node);
48
Justin Holewinski5422a0f2011-09-22 16:45:46 +000049 SDNode *SelectREADPARAM(SDNode *Node);
50 SDNode *SelectWRITEPARAM(SDNode *Node);
51
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000052 bool isImm(const SDValue &operand);
53 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000054
55 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000056}; // class PTXDAGToDAGISel
57} // namespace
58
59// createPTXISelDag - This pass converts a legalized DAG into a
60// PTX-specific DAG, ready for instruction scheduling
61FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
62 CodeGenOpt::Level OptLevel) {
63 return new PTXDAGToDAGISel(TM, OptLevel);
64}
65
66PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
67 CodeGenOpt::Level OptLevel)
68 : SelectionDAGISel(TM, OptLevel) {}
69
70SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000071 switch (Node->getOpcode()) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000072 case ISD::BRCOND:
73 return SelectBRCOND(Node);
Justin Holewinski5422a0f2011-09-22 16:45:46 +000074 case PTXISD::READ_PARAM:
75 return SelectREADPARAM(Node);
76 case PTXISD::WRITE_PARAM:
77 return SelectWRITEPARAM(Node);
Che-Liang Chiou88d33672011-03-18 11:08:52 +000078 default:
79 return SelectCode(Node);
80 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000081}
82
Che-Liang Chiou88d33672011-03-18 11:08:52 +000083SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
84 assert(Node->getNumOperands() >= 3);
85
86 SDValue Chain = Node->getOperand(0);
87 SDValue Pred = Node->getOperand(1);
88 SDValue Target = Node->getOperand(2); // branch target
89 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
90 DebugLoc dl = Node->getDebugLoc();
91
92 assert(Target.getOpcode() == ISD::BasicBlock);
93 assert(Pred.getValueType() == MVT::i1);
94
95 // Emit BRAdp
96 SDValue Ops[] = { Target, Pred, PredOp, Chain };
97 return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
98}
99
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000100SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
101 SDValue Chain = Node->getOperand(0);
102 SDValue Index = Node->getOperand(1);
103
104 int OpCode;
105
106 // Get the type of parameter we are reading
107 EVT VT = Node->getValueType(0);
108 assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
109
110 MVT Type = VT.getSimpleVT();
111
112 if (Type == MVT::i1)
113 OpCode = PTX::READPARAMPRED;
114 else if (Type == MVT::i16)
115 OpCode = PTX::READPARAMI16;
116 else if (Type == MVT::i32)
117 OpCode = PTX::READPARAMI32;
118 else if (Type == MVT::i64)
119 OpCode = PTX::READPARAMI64;
120 else if (Type == MVT::f32)
121 OpCode = PTX::READPARAMF32;
122 else if (Type == MVT::f64)
123 OpCode = PTX::READPARAMF64;
124
125 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
126 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
127 DebugLoc dl = Node->getDebugLoc();
128
129 SDValue Ops[] = { Index, Pred, PredOp, Chain };
130 return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
131}
132
133SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
134
135 SDValue Chain = Node->getOperand(0);
136 SDValue Value = Node->getOperand(1);
137
138 int OpCode;
139
140 //Node->dumpr(CurDAG);
141
142 // Get the type of parameter we are writing
143 EVT VT = Value->getValueType(0);
144 assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
145
146 MVT Type = VT.getSimpleVT();
147
148 if (Type == MVT::i1)
149 OpCode = PTX::WRITEPARAMPRED;
150 else if (Type == MVT::i16)
151 OpCode = PTX::WRITEPARAMI16;
152 else if (Type == MVT::i32)
153 OpCode = PTX::WRITEPARAMI32;
154 else if (Type == MVT::i64)
155 OpCode = PTX::WRITEPARAMI64;
156 else if (Type == MVT::f32)
157 OpCode = PTX::WRITEPARAMF32;
158 else if (Type == MVT::f64)
159 OpCode = PTX::WRITEPARAMF64;
160 else
161 llvm_unreachable("Invalid type in SelectWRITEPARAM");
162
163 SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
164 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
165 DebugLoc dl = Node->getDebugLoc();
166
167 SDValue Ops[] = { Value, Pred, PredOp, Chain };
168 SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
169
170 //dbgs() << "SelectWRITEPARAM produced:\n\t";
171 //Ret->dumpr(CurDAG);
172
173 return Ret;
174}
175
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000176// Match memory operand of the form [reg+reg]
177bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
178 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
179 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
180 return false;
181
Justin Holewinskid6625762011-03-23 16:58:51 +0000182 assert(Addr.getValueType().isSimple() && "Type must be simple");
183
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000184 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000185 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
186
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000187 return true;
188}
189
190// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000191bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
192 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000193 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000194 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000195 if (isImm(Addr))
196 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000197 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000198
199 assert(Addr.getValueType().isSimple() && "Type must be simple");
200
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000201 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000202 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
203
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000204 return true;
205 }
206
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000207 if (Addr.getNumOperands() < 2)
208 return false;
209
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000210 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000211 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000212 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000213
214 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000215 for (int i = 0; i < 2; i ++)
216 if (SelectImm(Addr.getOperand(1-i), Offset)) {
217 Base = Addr.getOperand(i);
218 return true;
219 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000220
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000221 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000222 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000223}
224
225// Match memory operand of the form [imm+imm] and [imm]
226bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
227 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000228 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000229 if (Addr.getOpcode() == ISD::ADD) {
230 return SelectImm(Addr.getOperand(0), Base) &&
231 SelectImm(Addr.getOperand(1), Offset);
232 }
233
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000234 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000235 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000236 assert(Addr.getValueType().isSimple() && "Type must be simple");
237
238 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
239
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000240 return true;
241 }
242
243 return false;
244}
245
246bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
247 return ConstantSDNode::classof(operand.getNode());
248}
249
250bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
251 SDNode *node = operand.getNode();
252 if (!ConstantSDNode::classof(node))
253 return false;
254
255 ConstantSDNode *CN = cast<ConstantSDNode>(node);
Justin Holewinskid6625762011-03-23 16:58:51 +0000256 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
257 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000258 return true;
259}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000260
261const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
262{
263 return TM.getSubtarget<PTXSubtarget>();
264}
265