blob: 1cae8f33bb6071e244ea1d1b8f2419708589f635 [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 Chiou8e5d01c2011-02-10 12:01:24 +000045 SDNode *SelectREAD_PARAM(SDNode *Node);
Justin Holewinski67a91842011-06-23 18:10:03 +000046 //SDNode *SelectSTORE_PARAM(SDNode *Node);
47
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
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()) {
72 case PTXISD::READ_PARAM:
73 return SelectREAD_PARAM(Node);
Justin Holewinski67a91842011-06-23 18:10:03 +000074 // case PTXISD::STORE_PARAM:
75 // return SelectSTORE_PARAM(Node);
Che-Liang Chiou88d33672011-03-18 11:08:52 +000076 case ISD::BRCOND:
77 return SelectBRCOND(Node);
78 default:
79 return SelectCode(Node);
80 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000081}
82
83SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000084 SDValue index = Node->getOperand(1);
85 DebugLoc dl = Node->getDebugLoc();
86 unsigned opcode;
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000087
88 if (index.getOpcode() != ISD::TargetConstant)
89 llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
90
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000091 if (Node->getValueType(0) == MVT::i16) {
92 opcode = PTX::LDpiU16;
Justin Holewinski67a91842011-06-23 18:10:03 +000093 } else if (Node->getValueType(0) == MVT::i32) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000094 opcode = PTX::LDpiU32;
Justin Holewinski67a91842011-06-23 18:10:03 +000095 } else if (Node->getValueType(0) == MVT::i64) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000096 opcode = PTX::LDpiU64;
Justin Holewinski67a91842011-06-23 18:10:03 +000097 } else if (Node->getValueType(0) == MVT::f32) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000098 opcode = PTX::LDpiF32;
Justin Holewinski67a91842011-06-23 18:10:03 +000099 } else if (Node->getValueType(0) == MVT::f64) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +0000100 opcode = PTX::LDpiF64;
Justin Holewinski67a91842011-06-23 18:10:03 +0000101 } else {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +0000102 llvm_unreachable("Unknown parameter type for ld.param");
103 }
104
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +0000105 return PTXInstrInfo::
Che-Liang Chioufd8978b2011-03-02 03:20:28 +0000106 GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index);
Eric Christopher50880d02010-09-18 18:52:28 +0000107}
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000108
Justin Holewinski67a91842011-06-23 18:10:03 +0000109// SDNode *PTXDAGToDAGISel::SelectSTORE_PARAM(SDNode *Node) {
110// SDValue Chain = Node->getOperand(0);
111// SDValue index = Node->getOperand(1);
112// SDValue value = Node->getOperand(2);
113// DebugLoc dl = Node->getDebugLoc();
114// unsigned opcode;
115
116// if (index.getOpcode() != ISD::TargetConstant)
117// llvm_unreachable("STORE_PARAM: index is not ISD::TargetConstant");
118
119// if (value->getValueType(0) == MVT::i16) {
120// opcode = PTX::STpiU16;
121// } else if (value->getValueType(0) == MVT::i32) {
122// opcode = PTX::STpiU32;
123// } else if (value->getValueType(0) == MVT::i64) {
124// opcode = PTX::STpiU64;
125// } else if (value->getValueType(0) == MVT::f32) {
126// opcode = PTX::STpiF32;
127// } else if (value->getValueType(0) == MVT::f64) {
128// opcode = PTX::STpiF64;
129// } else {
130// llvm_unreachable("Unknown parameter type for st.param");
131// }
132
133// SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
134// SDValue PredReg = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
135// SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
136// SDValue Ops[] = { Chain, index, value, PredReg, PredOp };
137// //SDNode *RetNode = PTXInstrInfo::
138// // GetPTXMachineNode(CurDAG, opcode, dl, VTs, index, value);
139// SDNode *RetNode = CurDAG->getMachineNode(opcode, dl, VTs, Ops, array_lengthof(Ops));
140// DEBUG(dbgs() << "SelectSTORE_PARAM: Selected: ");
141// RetNode->dumpr(CurDAG);
142// return RetNode;
143// }
144
Che-Liang Chiou88d33672011-03-18 11:08:52 +0000145SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
146 assert(Node->getNumOperands() >= 3);
147
148 SDValue Chain = Node->getOperand(0);
149 SDValue Pred = Node->getOperand(1);
150 SDValue Target = Node->getOperand(2); // branch target
151 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
152 DebugLoc dl = Node->getDebugLoc();
153
154 assert(Target.getOpcode() == ISD::BasicBlock);
155 assert(Pred.getValueType() == MVT::i1);
156
157 // Emit BRAdp
158 SDValue Ops[] = { Target, Pred, PredOp, Chain };
159 return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
160}
161
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000162// Match memory operand of the form [reg+reg]
163bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
164 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
165 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
166 return false;
167
Justin Holewinskid6625762011-03-23 16:58:51 +0000168 assert(Addr.getValueType().isSimple() && "Type must be simple");
169
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000170 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000171 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
172
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000173 return true;
174}
175
176// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000177bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
178 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000179 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000180 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000181 if (isImm(Addr))
182 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000183 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000184
185 assert(Addr.getValueType().isSimple() && "Type must be simple");
186
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000187 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000188 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
189
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000190 return true;
191 }
192
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000193 if (Addr.getNumOperands() < 2)
194 return false;
195
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000196 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000197 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000198 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000199
200 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000201 for (int i = 0; i < 2; i ++)
202 if (SelectImm(Addr.getOperand(1-i), Offset)) {
203 Base = Addr.getOperand(i);
204 return true;
205 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000206
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000207 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000208 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000209}
210
211// Match memory operand of the form [imm+imm] and [imm]
212bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
213 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000214 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000215 if (Addr.getOpcode() == ISD::ADD) {
216 return SelectImm(Addr.getOperand(0), Base) &&
217 SelectImm(Addr.getOperand(1), Offset);
218 }
219
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000220 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000221 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000222 assert(Addr.getValueType().isSimple() && "Type must be simple");
223
224 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
225
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000226 return true;
227 }
228
229 return false;
230}
231
232bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
233 return ConstantSDNode::classof(operand.getNode());
234}
235
236bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
237 SDNode *node = operand.getNode();
238 if (!ConstantSDNode::classof(node))
239 return false;
240
241 ConstantSDNode *CN = cast<ConstantSDNode>(node);
Justin Holewinskid6625762011-03-23 16:58:51 +0000242 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
243 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000244 return true;
245}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000246
247const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
248{
249 return TM.getSubtarget<PTXSubtarget>();
250}
251