PTX: Add intrinsic support for ntid, ctaid, and nctaid registers
[oota-llvm.git] / lib / Target / PTX / PTXISelDAGToDAG.cpp
1 //===-- 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"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 using namespace llvm;
21
22 namespace {
23 // PTXDAGToDAGISel - PTX specific code to select PTX machine
24 // instructions for SelectionDAG operations.
25 class 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
35     // Complex Pattern Selectors.
36     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
37     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
38     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
39
40     // Include the pieces auto'gened from the target description
41 #include "PTXGenDAGISel.inc"
42
43   private:
44     SDNode *SelectREAD_PARAM(SDNode *Node);
45
46     bool isImm(const SDValue &operand);
47     bool SelectImm(const SDValue &operand, SDValue &imm);
48
49     const PTXSubtarget& getSubtarget() const;
50 }; // class PTXDAGToDAGISel
51 } // namespace
52
53 // createPTXISelDag - This pass converts a legalized DAG into a
54 // PTX-specific DAG, ready for instruction scheduling
55 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
56                                      CodeGenOpt::Level OptLevel) {
57   return new PTXDAGToDAGISel(TM, OptLevel);
58 }
59
60 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
61                                  CodeGenOpt::Level OptLevel)
62   : SelectionDAGISel(TM, OptLevel) {}
63
64 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
65   if (Node->getOpcode() == PTXISD::READ_PARAM)
66     return SelectREAD_PARAM(Node);
67   else
68     return SelectCode(Node);
69 }
70
71 SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
72   SDValue  index = Node->getOperand(1);
73   DebugLoc dl    = Node->getDebugLoc();
74   unsigned opcode;
75
76   if (index.getOpcode() != ISD::TargetConstant)
77     llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
78
79   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
98   return PTXInstrInfo::
99     GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index);
100 }
101
102 // Match memory operand of the form [reg+reg]
103 bool 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
108   R1 = Addr;
109   R2 = CurDAG->getTargetConstant(0, MVT::i32);
110   return true;
111 }
112
113 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
114 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
115                                    SDValue &Offset) {
116   if (Addr.getOpcode() != ISD::ADD) {
117     // let SelectADDRii handle the [imm] case
118     if (isImm(Addr))
119       return false;
120     // it is [reg]
121     Base = Addr;
122     Offset = CurDAG->getTargetConstant(0, MVT::i32);
123     return true;
124   }
125
126   if (Addr.getNumOperands() < 2)
127     return false;
128
129   // let SelectADDRii handle the [imm+imm] case
130   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
131     return false;
132
133   // try [reg+imm] and [imm+reg]
134   for (int i = 0; i < 2; i ++)
135     if (SelectImm(Addr.getOperand(1-i), Offset)) {
136       Base = Addr.getOperand(i);
137       return true;
138     }
139
140   // neither [reg+imm] nor [imm+reg]
141   return false;
142 }
143
144 // Match memory operand of the form [imm+imm] and [imm]
145 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
146                                    SDValue &Offset) {
147   // is [imm+imm]?
148   if (Addr.getOpcode() == ISD::ADD) {
149     return SelectImm(Addr.getOperand(0), Base) &&
150            SelectImm(Addr.getOperand(1), Offset);
151   }
152
153   // is [imm]?
154   if (SelectImm(Addr, Base)) {
155     Offset = CurDAG->getTargetConstant(0, MVT::i32);
156     return true;
157   }
158
159   return false;
160 }
161
162 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
163   return ConstantSDNode::classof(operand.getNode());
164 }
165
166 bool 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 }
175
176 const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
177 {
178   return TM.getSubtarget<PTXSubtarget>();
179 }
180