blob: fe2d25a3b43c43e6618fbf499dd6ff97a435c3d3 [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 Chioufc7072c2010-12-22 10:38:51 +000046 bool isImm(const SDValue &operand);
47 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000048
49 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000050}; // class PTXDAGToDAGISel
51} // namespace
52
53// createPTXISelDag - This pass converts a legalized DAG into a
54// PTX-specific DAG, ready for instruction scheduling
55FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
56 CodeGenOpt::Level OptLevel) {
57 return new PTXDAGToDAGISel(TM, OptLevel);
58}
59
60PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
61 CodeGenOpt::Level OptLevel)
62 : SelectionDAGISel(TM, OptLevel) {}
63
64SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000065 if (Node->getOpcode() == PTXISD::READ_PARAM)
66 return SelectREAD_PARAM(Node);
67 else
68 return SelectCode(Node);
69}
70
71SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000072 SDValue index = Node->getOperand(1);
73 DebugLoc dl = Node->getDebugLoc();
74 unsigned opcode;
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000075
76 if (index.getOpcode() != ISD::TargetConstant)
77 llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
78
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000079 if (Node->getValueType(0) == MVT::i16) {
80 opcode = PTX::LDpiU16;
81 }
82 else if (Node->getValueType(0) == MVT::i32) {
83 opcode = PTX::LDpiU32;
84 }
85 else if (Node->getValueType(0) == MVT::i64) {
86 opcode = PTX::LDpiU64;
87 }
88 else if (Node->getValueType(0) == MVT::f32) {
89 opcode = PTX::LDpiF32;
90 }
91 else if (Node->getValueType(0) == MVT::f64) {
92 opcode = PTX::LDpiF64;
93 }
94 else {
95 llvm_unreachable("Unknown parameter type for ld.param");
96 }
97
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000098 return PTXInstrInfo::
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000099 GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index);
Eric Christopher50880d02010-09-18 18:52:28 +0000100}
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000101
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000102// Match memory operand of the form [reg+reg]
103bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
104 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
105 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
106 return false;
107
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000108 R1 = Addr;
109 R2 = CurDAG->getTargetConstant(0, MVT::i32);
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000110 return true;
111}
112
113// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000114bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
115 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000116 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000117 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000118 if (isImm(Addr))
119 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000120 // it is [reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000121 Base = Addr;
122 Offset = CurDAG->getTargetConstant(0, MVT::i32);
123 return true;
124 }
125
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000126 if (Addr.getNumOperands() < 2)
127 return false;
128
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000129 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000130 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000131 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000132
133 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000134 for (int i = 0; i < 2; i ++)
135 if (SelectImm(Addr.getOperand(1-i), Offset)) {
136 Base = Addr.getOperand(i);
137 return true;
138 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000139
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000140 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000141 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000142}
143
144// Match memory operand of the form [imm+imm] and [imm]
145bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
146 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000147 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000148 if (Addr.getOpcode() == ISD::ADD) {
149 return SelectImm(Addr.getOperand(0), Base) &&
150 SelectImm(Addr.getOperand(1), Offset);
151 }
152
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000153 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000154 if (SelectImm(Addr, Base)) {
155 Offset = CurDAG->getTargetConstant(0, MVT::i32);
156 return true;
157 }
158
159 return false;
160}
161
162bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
163 return ConstantSDNode::classof(operand.getNode());
164}
165
166bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
167 SDNode *node = operand.getNode();
168 if (!ConstantSDNode::classof(node))
169 return false;
170
171 ConstantSDNode *CN = cast<ConstantSDNode>(node);
172 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32);
173 return true;
174}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000175
176const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
177{
178 return TM.getSubtarget<PTXSubtarget>();
179}
180