blob: efb0e8b1af77991c8a5f8466fc0cf920018649c8 [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"
Eric Christopher50880d02010-09-18 18:52:28 +000018
19using namespace llvm;
20
21namespace {
22// PTXDAGToDAGISel - PTX specific code to select PTX machine
23// instructions for SelectionDAG operations.
24class PTXDAGToDAGISel : public SelectionDAGISel {
25 public:
26 PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
27
28 virtual const char *getPassName() const {
29 return "PTX DAG->DAG Pattern Instruction Selection";
30 }
31
32 SDNode *Select(SDNode *Node);
33
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000034 // Complex Pattern Selectors.
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000035 bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000036 bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
37 bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
38
Eric Christopher50880d02010-09-18 18:52:28 +000039 // Include the pieces auto'gened from the target description
40#include "PTXGenDAGISel.inc"
41
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000042 private:
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000043 SDNode *SelectREAD_PARAM(SDNode *Node);
44
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000045 bool isImm(const SDValue &operand);
46 bool SelectImm(const SDValue &operand, SDValue &imm);
Eric Christopher50880d02010-09-18 18:52:28 +000047}; // class PTXDAGToDAGISel
48} // namespace
49
50// createPTXISelDag - This pass converts a legalized DAG into a
51// PTX-specific DAG, ready for instruction scheduling
52FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
53 CodeGenOpt::Level OptLevel) {
54 return new PTXDAGToDAGISel(TM, OptLevel);
55}
56
57PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
58 CodeGenOpt::Level OptLevel)
59 : SelectionDAGISel(TM, OptLevel) {}
60
61SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +000062 if (Node->getOpcode() == PTXISD::READ_PARAM)
63 return SelectREAD_PARAM(Node);
64 else
65 return SelectCode(Node);
66}
67
68SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) {
69 SDValue index = Node->getOperand(1);
70 DebugLoc dl = Node->getDebugLoc();
71
72 if (index.getOpcode() != ISD::TargetConstant)
73 llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant");
74
75 return PTXInstrInfo::
76 GetPTXMachineNode(CurDAG, PTX::LDpi, dl, MVT::i32, index);
Eric Christopher50880d02010-09-18 18:52:28 +000077}
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000078
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000079// Match memory operand of the form [reg+reg]
80bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
81 if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
82 isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
83 return false;
84
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +000085 R1 = Addr;
86 R2 = CurDAG->getTargetConstant(0, MVT::i32);
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000087 return true;
88}
89
90// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +000091bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
92 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000093 if (Addr.getOpcode() != ISD::ADD) {
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +000094 // let SelectADDRii handle the [imm] case
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000095 if (isImm(Addr))
96 return false;
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +000097 // it is [reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +000098 Base = Addr;
99 Offset = CurDAG->getTargetConstant(0, MVT::i32);
100 return true;
101 }
102
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000103 if (Addr.getNumOperands() < 2)
104 return false;
105
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000106 // let SelectADDRii handle the [imm+imm] case
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000107 if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000108 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000109
110 // try [reg+imm] and [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000111 for (int i = 0; i < 2; i ++)
112 if (SelectImm(Addr.getOperand(1-i), Offset)) {
113 Base = Addr.getOperand(i);
114 return true;
115 }
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000116
Che-Liang Chiouc88e91b2011-01-01 11:58:58 +0000117 // neither [reg+imm] nor [imm+reg]
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000118 return false;
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000119}
120
121// Match memory operand of the form [imm+imm] and [imm]
122bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
123 SDValue &Offset) {
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000124 // is [imm+imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000125 if (Addr.getOpcode() == ISD::ADD) {
126 return SelectImm(Addr.getOperand(0), Base) &&
127 SelectImm(Addr.getOperand(1), Offset);
128 }
129
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000130 // is [imm]?
Che-Liang Chiou3f8e6172010-11-30 07:34:44 +0000131 if (SelectImm(Addr, Base)) {
132 Offset = CurDAG->getTargetConstant(0, MVT::i32);
133 return true;
134 }
135
136 return false;
137}
138
139bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
140 return ConstantSDNode::classof(operand.getNode());
141}
142
143bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
144 SDNode *node = operand.getNode();
145 if (!ConstantSDNode::classof(node))
146 return false;
147
148 ConstantSDNode *CN = cast<ConstantSDNode>(node);
149 imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32);
150 return true;
151}