blob: 9adfa624b29ed4a77a8bf960deba63ba01c57f60 [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 Chiou88d33672011-03-18 11:08:52 +000045 // We need this only because we can't match intruction BRAdp
46 // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
47 SDNode *SelectBRCOND(SDNode *Node);
48
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000049 bool isImm(const SDValue &operand);
50 bool SelectImm(const SDValue &operand, SDValue &imm);
Che-Liang Chiouf48817c2011-03-02 07:36:48 +000051
52 const PTXSubtarget& getSubtarget() const;
Eric Christopher50880d02010-09-18 18:52:28 +000053}; // class PTXDAGToDAGISel
54} // namespace
55
56// createPTXISelDag - This pass converts a legalized DAG into a
57// PTX-specific DAG, ready for instruction scheduling
58FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
59 CodeGenOpt::Level OptLevel) {
60 return new PTXDAGToDAGISel(TM, OptLevel);
61}
62
63PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
64 CodeGenOpt::Level OptLevel)
65 : SelectionDAGISel(TM, OptLevel) {}
66
67SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000068 switch (Node->getOpcode()) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +000069 case ISD::BRCOND:
70 return SelectBRCOND(Node);
71 default:
72 return SelectCode(Node);
73 }
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000074}
75
Che-Liang Chiou88d33672011-03-18 11:08:52 +000076SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
77 assert(Node->getNumOperands() >= 3);
78
79 SDValue Chain = Node->getOperand(0);
80 SDValue Pred = Node->getOperand(1);
81 SDValue Target = Node->getOperand(2); // branch target
82 SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
83 DebugLoc dl = Node->getDebugLoc();
84
85 assert(Target.getOpcode() == ISD::BasicBlock);
86 assert(Pred.getValueType() == MVT::i1);
87
88 // Emit BRAdp
89 SDValue Ops[] = { Target, Pred, PredOp, Chain };
90 return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
91}
92
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000093// Match memory operand of the form [reg+reg]
94bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
95 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
96 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
97 return false;
98
Justin Holewinskid6625762011-03-23 16:58:51 +000099 assert(Addr.getValueType().isSimple() && "Type must be simple");
100
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000101 R1 = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000102 R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
103
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000104 return true;
105}
106
107// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000108bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
109 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000110 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000111 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000112 if (isImm(Addr))
113 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000114 // it is [reg]
Justin Holewinskid6625762011-03-23 16:58:51 +0000115
116 assert(Addr.getValueType().isSimple() && "Type must be simple");
117
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000118 Base = Addr;
Justin Holewinskid6625762011-03-23 16:58:51 +0000119 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
120
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000121 return true;
122 }
123
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000124 if (Addr.getNumOperands() < 2)
125 return false;
126
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000127 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000128 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000129 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000130
131 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000132 for (int i = 0; i < 2; i ++)
133 if (SelectImm(Addr.getOperand(1-i), Offset)) {
134 Base = Addr.getOperand(i);
135 return true;
136 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000137
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000138 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000139 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000140}
141
142// Match memory operand of the form [imm+imm] and [imm]
143bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
144 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000145 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000146 if (Addr.getOpcode() == ISD::ADD) {
147 return SelectImm(Addr.getOperand(0), Base) &&
148 SelectImm(Addr.getOperand(1), Offset);
149 }
150
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000151 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000152 if (SelectImm(Addr, Base)) {
Justin Holewinskid6625762011-03-23 16:58:51 +0000153 assert(Addr.getValueType().isSimple() && "Type must be simple");
154
155 Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
156
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000157 return true;
158 }
159
160 return false;
161}
162
163bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
164 return ConstantSDNode::classof(operand.getNode());
165}
166
167bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
168 SDNode *node = operand.getNode();
169 if (!ConstantSDNode::classof(node))
170 return false;
171
172 ConstantSDNode *CN = cast<ConstantSDNode>(node);
Justin Holewinskid6625762011-03-23 16:58:51 +0000173 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
174 operand.getValueType());
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000175 return true;
176}
Che-Liang Chiouf48817c2011-03-02 07:36:48 +0000177
178const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
179{
180 return TM.getSubtarget<PTXSubtarget>();
181}
182