blob: b3c85da7b4461662a967dff06d872f1a1b68bcbb [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"
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000018#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000019
20using namespace llvm;
21
22namespace {
23// PTXDAGToDAGISel - PTX specific code to select PTX machine
24// instructions for SelectionDAG operations.
25class 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
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000035 // Complex Pattern Selectors.
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000036 bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000037 bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
38 bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
39
Eric Christopher50880d02010-09-18 18:52:28 +000040 // Include the pieces auto'gened from the target description
41#include "PTXGenDAGISel.inc"
42
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000043 private:
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000044 SDNode *SelectREAD_PARAM(SDNode *Node);
45
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
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000050 bool isImm(const SDValue &operand);
51 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000052
53 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000054}; // class PTXDAGToDAGISel
55} // namespace
56
57// createPTXISelDag - This pass converts a legalized DAG into a
58// PTX-specific DAG, ready for instruction scheduling
59FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
60 CodeGenOpt::Level OptLevel) {
61 return new PTXDAGToDAGISel(TM, OptLevel);
62}
63
64PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
65 CodeGenOpt::Level OptLevel)
66 : SelectionDAGISel(TM, OptLevel) {}
67
68SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000069 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 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000077}
78
79SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000080 SDValue index = Node->getOperand(1);
81 DebugLoc dl = Node->getDebugLoc();
82 unsigned opcode;
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000083
84 if (index.getOpcode() != ISD::TargetConstant)
85 llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
86
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000087 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
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +0000106 return PTXInstrInfo::
Che-Liang Chioufd8978b2011-03-02 03:20:28 +0000107 GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index);
Eric Christopher50880d02010-09-18 18:52:28 +0000108}
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000109
Che-Liang Chiou88d33672011-03-18 11:08:52 +0000110SDNode *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
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000127// Match memory operand of the form [reg+reg]
128bool 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
Justin Holewinskid6625762011-03-23 16:58:51 +0000133 assert(Addr.getValueType().isSimple() && "Type must be simple");
134
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000135 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000136 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
137
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000138 return true;
139}
140
141// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000142bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
143 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000144 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000145 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000146 if (isImm(Addr))
147 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000148 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000149
150 assert(Addr.getValueType().isSimple() && "Type must be simple");
151
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000152 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000153 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
154
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000155 return true;
156 }
157
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000158 if (Addr.getNumOperands() < 2)
159 return false;
160
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000161 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000162 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000163 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000164
165 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000166 for (int i = 0; i < 2; i ++)
167 if (SelectImm(Addr.getOperand(1-i), Offset)) {
168 Base = Addr.getOperand(i);
169 return true;
170 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000171
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000172 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000173 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000174}
175
176// Match memory operand of the form [imm+imm] and [imm]
177bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
178 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000179 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000180 if (Addr.getOpcode() == ISD::ADD) {
181 return SelectImm(Addr.getOperand(0), Base) &&
182 SelectImm(Addr.getOperand(1), Offset);
183 }
184
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000185 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000186 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000187 assert(Addr.getValueType().isSimple() && "Type must be simple");
188
189 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
190
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000191 return true;
192 }
193
194 return false;
195}
196
197bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
198 return ConstantSDNode::classof(operand.getNode());
199}
200
201bool 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);
Justin Holewinskid6625762011-03-23 16:58:51 +0000207 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
208 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000209 return true;
210}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000211
212const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
213{
214 return TM.getSubtarget<PTXSubtarget>();
215}
216