ptx: remove reg-reg addressing mode and st.const
[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
19 using namespace llvm;
20
21 namespace {
22 // PTXDAGToDAGISel - PTX specific code to select PTX machine
23 // instructions for SelectionDAG operations.
24 class 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
34     // Complex Pattern Selectors.
35     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
36     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
37     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
38
39     // Include the pieces auto'gened from the target description
40 #include "PTXGenDAGISel.inc"
41
42   private:
43     bool isImm(const SDValue &operand);
44     bool SelectImm(const SDValue &operand, SDValue &imm);
45 }; // class PTXDAGToDAGISel
46 } // namespace
47
48 // createPTXISelDag - This pass converts a legalized DAG into a
49 // PTX-specific DAG, ready for instruction scheduling
50 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
51                                      CodeGenOpt::Level OptLevel) {
52   return new PTXDAGToDAGISel(TM, OptLevel);
53 }
54
55 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
56                                  CodeGenOpt::Level OptLevel)
57   : SelectionDAGISel(TM, OptLevel) {}
58
59 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
60   // SelectCode() is auto'gened
61   return SelectCode(Node);
62 }
63
64 // Match memory operand of the form [reg+reg]
65 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
66   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
67       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
68     return false;
69
70   R1 = Addr;
71   R2 = CurDAG->getTargetConstant(0, MVT::i32);
72   return true;
73 }
74
75 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
76 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
77                                    SDValue &Offset) {
78   if (Addr.getOpcode() != ISD::ADD) {
79     // let SelectADDRii handle the [imm] case
80     if (isImm(Addr))
81       return false;
82     // it is [reg]
83     Base = Addr;
84     Offset = CurDAG->getTargetConstant(0, MVT::i32);
85     return true;
86   }
87
88   if (Addr.getNumOperands() < 2)
89     return false;
90
91   // let SelectADDRii handle the [imm+imm] case
92   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
93     return false;
94
95   // try [reg+imm] and [imm+reg]
96   for (int i = 0; i < 2; i ++)
97     if (SelectImm(Addr.getOperand(1-i), Offset)) {
98       Base = Addr.getOperand(i);
99       return true;
100     }
101
102   // neither [reg+imm] nor [imm+reg]
103   return false;
104 }
105
106 // Match memory operand of the form [imm+imm] and [imm]
107 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
108                                    SDValue &Offset) {
109   // is [imm+imm]?
110   if (Addr.getOpcode() == ISD::ADD) {
111     return SelectImm(Addr.getOperand(0), Base) &&
112            SelectImm(Addr.getOperand(1), Offset);
113   }
114
115   // is [imm]?
116   if (SelectImm(Addr, Base)) {
117     Offset = CurDAG->getTargetConstant(0, MVT::i32);
118     return true;
119   }
120
121   return false;
122 }
123
124 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
125   return ConstantSDNode::classof(operand.getNode());
126 }
127
128 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
129   SDNode *node = operand.getNode();
130   if (!ConstantSDNode::classof(node))
131     return false;
132
133   ConstantSDNode *CN = cast<ConstantSDNode>(node);
134   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32);
135   return true;
136 }