]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / 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 "PTXMachineFunctionInfo.h"
16 #include "PTXTargetMachine.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/CodeGen/SelectionDAGISel.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22
23 using namespace llvm;
24
25 namespace {
26 // PTXDAGToDAGISel - PTX specific code to select PTX machine
27 // instructions for SelectionDAG operations.
28 class PTXDAGToDAGISel : public SelectionDAGISel {
29   public:
30     PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
31
32     virtual const char *getPassName() const {
33       return "PTX DAG->DAG Pattern Instruction Selection";
34     }
35
36     SDNode *Select(SDNode *Node);
37
38     // Complex Pattern Selectors.
39     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
40     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
41     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
42     bool SelectADDRlocal(SDValue &Addr, SDValue &Base, SDValue &Offset);
43
44     // Include the pieces auto'gened from the target description
45 #include "PTXGenDAGISel.inc"
46
47   private:
48     // 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
52     SDNode *SelectREADPARAM(SDNode *Node);
53     SDNode *SelectWRITEPARAM(SDNode *Node);
54     SDNode *SelectFrameIndex(SDNode *Node);
55
56     bool isImm(const SDValue &operand);
57     bool SelectImm(const SDValue &operand, SDValue &imm);
58
59     const PTXSubtarget& getSubtarget() const;
60 }; // class PTXDAGToDAGISel
61 } // namespace
62
63 // createPTXISelDag - This pass converts a legalized DAG into a
64 // PTX-specific DAG, ready for instruction scheduling
65 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
66                                      CodeGenOpt::Level OptLevel) {
67   return new PTXDAGToDAGISel(TM, OptLevel);
68 }
69
70 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
71                                  CodeGenOpt::Level OptLevel)
72   : SelectionDAGISel(TM, OptLevel) {}
73
74 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
75   switch (Node->getOpcode()) {
76     case ISD::BRCOND:
77       return SelectBRCOND(Node);
78     case PTXISD::READ_PARAM:
79       return SelectREADPARAM(Node);
80     case PTXISD::WRITE_PARAM:
81       return SelectWRITEPARAM(Node);
82     case ISD::FrameIndex:
83       return SelectFrameIndex(Node);
84     default:
85       return SelectCode(Node);
86   }
87 }
88
89 SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
90   assert(Node->getNumOperands() >= 3);
91
92   SDValue Chain  = Node->getOperand(0);
93   SDValue Pred   = Node->getOperand(1);
94   SDValue Target = Node->getOperand(2); // branch target
95   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::Normal, MVT::i32);
96   DebugLoc dl = Node->getDebugLoc();
97
98   assert(Target.getOpcode()  == ISD::BasicBlock);
99   assert(Pred.getValueType() == MVT::i1);
100
101   // Emit BRAdp
102   SDValue Ops[] = { Target, Pred, PredOp, Chain };
103   return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
104 }
105
106 SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
107   SDValue Chain = Node->getOperand(0);
108   SDValue Index = Node->getOperand(1);
109
110   int OpCode;
111
112   // Get the type of parameter we are reading
113   EVT VT = Node->getValueType(0);
114   assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
115
116   MVT Type = VT.getSimpleVT();
117
118   if (Type == MVT::i1)
119     OpCode = PTX::READPARAMPRED;
120   else if (Type == MVT::i16)
121     OpCode = PTX::READPARAMI16;
122   else if (Type == MVT::i32)
123     OpCode = PTX::READPARAMI32;
124   else if (Type == MVT::i64)
125     OpCode = PTX::READPARAMI64;
126   else if (Type == MVT::f32)
127     OpCode = PTX::READPARAMF32;
128   else {
129     assert(Type == MVT::f64 && "Unexpected type!");
130     OpCode = PTX::READPARAMF64;
131   }
132
133   SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
134   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
135   DebugLoc dl = Node->getDebugLoc();
136
137   SDValue Ops[] = { Index, Pred, PredOp, Chain };
138   return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
139 }
140
141 SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
142
143   SDValue Chain = Node->getOperand(0);
144   SDValue Value = Node->getOperand(1);
145
146   int OpCode;
147
148   //Node->dumpr(CurDAG);
149
150   // Get the type of parameter we are writing
151   EVT VT = Value->getValueType(0);
152   assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
153
154   MVT Type = VT.getSimpleVT();
155
156   if (Type == MVT::i1)
157     OpCode = PTX::WRITEPARAMPRED;
158   else if (Type == MVT::i16)
159     OpCode = PTX::WRITEPARAMI16;
160   else if (Type == MVT::i32)
161     OpCode = PTX::WRITEPARAMI32;
162   else if (Type == MVT::i64)
163     OpCode = PTX::WRITEPARAMI64;
164   else if (Type == MVT::f32)
165     OpCode = PTX::WRITEPARAMF32;
166   else if (Type == MVT::f64)
167     OpCode = PTX::WRITEPARAMF64;
168   else
169     llvm_unreachable("Invalid type in SelectWRITEPARAM");
170
171   SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
172   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
173   DebugLoc dl = Node->getDebugLoc();
174
175   SDValue Ops[] = { Value, Pred, PredOp, Chain };
176   SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
177
178   //dbgs() << "SelectWRITEPARAM produced:\n\t";
179   //Ret->dumpr(CurDAG);
180
181   return Ret;
182 }
183
184 SDNode *PTXDAGToDAGISel::SelectFrameIndex(SDNode *Node) {
185   int FI = cast<FrameIndexSDNode>(Node)->getIndex();
186   //dbgs() << "Selecting FrameIndex at index " << FI << "\n";
187   //SDValue TFI = CurDAG->getTargetFrameIndex(FI, Node->getValueType(0));
188
189   PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
190
191   SDValue FrameSymbol = CurDAG->getTargetExternalSymbol(MFI->getFrameSymbol(FI),
192                                                         Node->getValueType(0));
193
194   return FrameSymbol.getNode();
195 }
196
197 // Match memory operand of the form [reg+reg]
198 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
199   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
200       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
201     return false;
202
203   assert(Addr.getValueType().isSimple() && "Type must be simple");
204
205   R1 = Addr;
206   R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
207
208   return true;
209 }
210
211 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
212 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
213                                    SDValue &Offset) {
214   // FrameIndex addresses are handled separately
215   //errs() << "SelectADDRri: ";
216   //Addr.getNode()->dumpr();
217   if (isa<FrameIndexSDNode>(Addr)) {
218     //errs() << "Failure\n";
219     return false;
220   }
221
222   if (CurDAG->isBaseWithConstantOffset(Addr)) {
223     Base = Addr.getOperand(0);
224     if (isa<FrameIndexSDNode>(Base)) {
225       //errs() << "Failure\n";
226       return false;
227     }
228     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
229     Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
230     //errs() << "Success\n";
231     return true;
232   }
233
234   /*if (Addr.getNumOperands() == 1) {
235     Base = Addr;
236     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
237     errs() << "Success\n";
238     return true;
239   }*/
240
241   //errs() << "SelectADDRri fails on: ";
242   //Addr.getNode()->dumpr();
243
244   if (isImm(Addr)) {
245     //errs() << "Failure\n";
246     return false;
247   }
248
249   Base = Addr;
250   Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
251
252   //errs() << "Success\n";
253   return true;
254
255   /*if (Addr.getOpcode() != ISD::ADD) {
256     // let SelectADDRii handle the [imm] case
257     if (isImm(Addr))
258       return false;
259     // it is [reg]
260
261     assert(Addr.getValueType().isSimple() && "Type must be simple");
262     Base = Addr;
263     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
264
265     return true;
266   }
267
268   if (Addr.getNumOperands() < 2)
269     return false;
270
271   // let SelectADDRii handle the [imm+imm] case
272   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
273     return false;
274
275   // try [reg+imm] and [imm+reg]
276   for (int i = 0; i < 2; i ++)
277     if (SelectImm(Addr.getOperand(1-i), Offset)) {
278       Base = Addr.getOperand(i);
279       return true;
280     }
281
282   // neither [reg+imm] nor [imm+reg]
283   return false;*/
284 }
285
286 // Match memory operand of the form [imm+imm] and [imm]
287 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
288                                    SDValue &Offset) {
289   // is [imm+imm]?
290   if (Addr.getOpcode() == ISD::ADD) {
291     return SelectImm(Addr.getOperand(0), Base) &&
292            SelectImm(Addr.getOperand(1), Offset);
293   }
294
295   // is [imm]?
296   if (SelectImm(Addr, Base)) {
297     assert(Addr.getValueType().isSimple() && "Type must be simple");
298
299     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
300
301     return true;
302   }
303
304   return false;
305 }
306
307 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
308 bool PTXDAGToDAGISel::SelectADDRlocal(SDValue &Addr, SDValue &Base,
309                                       SDValue &Offset) {
310   //errs() << "SelectADDRlocal: ";
311   //Addr.getNode()->dumpr();
312   if (isa<FrameIndexSDNode>(Addr)) {
313     Base = Addr;
314     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
315     //errs() << "Success\n";
316     return true;
317   }
318
319   if (CurDAG->isBaseWithConstantOffset(Addr)) {
320     Base = Addr.getOperand(0);
321     if (!isa<FrameIndexSDNode>(Base)) {
322       //errs() << "Failure\n";
323       return false;
324     }
325     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
326     Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
327     //errs() << "Offset: ";
328     //Offset.getNode()->dumpr();
329     //errs() << "Success\n";
330     return true;
331   }
332
333   //errs() << "Failure\n";
334   return false;
335 }
336
337 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
338   return ConstantSDNode::classof(operand.getNode());
339 }
340
341 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
342   SDNode *node = operand.getNode();
343   if (!ConstantSDNode::classof(node))
344     return false;
345
346   ConstantSDNode *CN = cast<ConstantSDNode>(node);
347   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
348                                   operand.getValueType());
349   return true;
350 }
351
352 const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
353 {
354   return TM.getSubtarget<PTXSubtarget>();
355 }
356