Well, the Constant matching pattern works. Can't say much about calls or globals...
[oota-llvm.git] / lib / Target / Alpha / AlphaISelDAGToDAG.cpp
1 //===-- AlphaISelDAGToDAG.cpp - Alpha pattern matching inst selector ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Andrew Lenharth and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a pattern matching instruction selector for Alpha,
11 // converting from a legalized dag to a Alpha dag.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Alpha.h"
16 #include "AlphaTargetMachine.h"
17 #include "AlphaISelLowering.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/SSARegMap.h"
21 #include "llvm/CodeGen/SelectionDAG.h"
22 #include "llvm/CodeGen/SelectionDAGISel.h"
23 #include "llvm/Target/TargetOptions.h"
24 #include "llvm/ADT/Statistic.h"
25 #include "llvm/Constants.h"
26 #include "llvm/GlobalValue.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/MathExtras.h"
29 #include <algorithm>
30 using namespace llvm;
31
32 namespace {
33
34   //===--------------------------------------------------------------------===//
35   /// AlphaDAGToDAGISel - Alpha specific code to select Alpha machine
36   /// instructions for SelectionDAG operations.
37   ///
38   class AlphaDAGToDAGISel : public SelectionDAGISel {
39     AlphaTargetLowering AlphaLowering;
40
41   public:
42     AlphaDAGToDAGISel(TargetMachine &TM)
43       : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {}
44
45     /// getI64Imm - Return a target constant with the specified value, of type
46     /// i64.
47     inline SDOperand getI64Imm(int64_t Imm) {
48       return CurDAG->getTargetConstant(Imm, MVT::i64);
49     }
50
51     // Select - Convert the specified operand from a target-independent to a
52     // target-specific node if it hasn't already been changed.
53     SDOperand Select(SDOperand Op);
54     
55     /// InstructionSelectBasicBlock - This callback is invoked by
56     /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
57     virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
58     
59     virtual const char *getPassName() const {
60       return "Alpha DAG->DAG Pattern Instruction Selection";
61     } 
62
63 // Include the pieces autogenerated from the target description.
64 #include "AlphaGenDAGISel.inc"
65     
66 private:
67     SDOperand getGlobalBaseReg();
68     SDOperand SelectCALL(SDOperand Op);
69
70   };
71 }
72
73 /// getGlobalBaseReg - Output the instructions required to put the
74 /// GOT address into a register.
75 ///
76 SDOperand AlphaDAGToDAGISel::getGlobalBaseReg() {
77   return CurDAG->getRegister(AlphaLowering.getVRegGP(), MVT::i64);
78 }
79
80 /// InstructionSelectBasicBlock - This callback is invoked by
81 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
82 void AlphaDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
83   DEBUG(BB->dump());
84   
85   // Select target instructions for the DAG.
86   DAG.setRoot(Select(DAG.getRoot()));
87   CodeGenMap.clear();
88   DAG.RemoveDeadNodes();
89   
90   // Emit machine code to BB. 
91   ScheduleAndEmitDAG(DAG);
92 }
93
94 // Select - Convert the specified operand from a target-independent to a
95 // target-specific node if it hasn't already been changed.
96 SDOperand AlphaDAGToDAGISel::Select(SDOperand Op) {
97   SDNode *N = Op.Val;
98   if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
99       N->getOpcode() < AlphaISD::FIRST_NUMBER)
100     return Op;   // Already selected.
101
102   // If this has already been converted, use it.
103   std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
104   if (CGMI != CodeGenMap.end()) return CGMI->second;
105   
106   switch (N->getOpcode()) {
107   default: break;
108   case ISD::TAILCALL:
109   case ISD::CALL: return SelectCALL(Op);
110
111   case ISD::DYNAMIC_STACKALLOC:
112   case ISD::ADD_PARTS:
113   case ISD::SUB_PARTS:
114   case ISD::SETCC:
115     assert(0 && "You want these too?");
116
117   case ISD::BR: {
118     CurDAG->SelectNodeTo(N, Alpha::BR_DAG, MVT::Other, N->getOperand(1),
119                          Select(N->getOperand(0)));
120     return SDOperand(N, 0);
121   }
122
123   case ISD::TokenFactor: {
124     SDOperand New;
125     if (N->getNumOperands() == 2) {
126       SDOperand Op0 = Select(N->getOperand(0));
127       SDOperand Op1 = Select(N->getOperand(1));
128       New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Op0, Op1);
129     } else {
130       std::vector<SDOperand> Ops;
131       for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
132         Ops.push_back(Select(N->getOperand(i)));
133       New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops);
134     }
135     
136     CodeGenMap[Op] = New;
137     return New;
138   }
139   case ISD::CopyFromReg: {
140     SDOperand Chain = Select(N->getOperand(0));
141     if (Chain == N->getOperand(0)) return Op; // No change
142     SDOperand New = CurDAG->getCopyFromReg(Chain,
143          cast<RegisterSDNode>(N->getOperand(1))->getReg(), N->getValueType(0));
144     return New.getValue(Op.ResNo);
145   }
146   case ISD::CopyToReg: {
147     SDOperand Chain = Select(N->getOperand(0));
148     SDOperand Reg = N->getOperand(1);
149     SDOperand Val = Select(N->getOperand(2));
150     SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other,
151                                     Chain, Reg, Val);
152     CodeGenMap[Op] = New;
153     return New;
154   }
155   case ISD::UNDEF:
156     if (N->getValueType(0) == MVT::i64)
157       CurDAG->SelectNodeTo(N, Alpha::IDEF, MVT::i64);
158 //     else if (N->getValueType(0) == MVT::f32)
159 //       CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F4, MVT::f32);
160 //     else 
161 //       CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F8, MVT::f64);
162     return SDOperand(N, 0);
163   case ISD::FrameIndex: {
164 //     int FI = cast<FrameIndexSDNode>(N)->getIndex();
165 //     CurDAG->SelectNodeTo(N, Alpha::LDA, MVT::i64,
166 //                          CurDAG->getTargetFrameIndex(FI, MVT::i32),
167 //                          getI32Imm(0));
168 //     return SDOperand(N, 0);
169     assert(0 && "Frame?, you are suppose to look through the window, not at the frame!");
170   }
171   case ISD::ConstantPool: {
172 //     Constant *C = cast<ConstantPoolSDNode>(N)->get();
173 //     SDOperand Tmp, CPI = CurDAG->getTargetConstantPool(C, MVT::i32);
174 //     if (PICEnabled)
175 //       Tmp = CurDAG->getTargetNode(PPC::ADDIS, MVT::i32, getGlobalBaseReg(),CPI);
176 //     else
177 //       Tmp = CurDAG->getTargetNode(PPC::LIS, MVT::i32, CPI);
178 //     CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, CPI);
179 //     return SDOperand(N, 0);
180     assert(0 && "Constants are overrated");
181   }
182   case ISD::GlobalAddress: {
183     GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
184     SDOperand GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64);
185     CurDAG->SelectNodeTo(N, Alpha::LDQl, MVT::i64, GA, getGlobalBaseReg());
186     return SDOperand(N, 0);
187   }
188
189   case ISD::CALLSEQ_START:
190   case ISD::CALLSEQ_END: {
191     unsigned Amt = cast<ConstantSDNode>(N->getOperand(1))->getValue();
192     unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ?
193                        Alpha::ADJUSTSTACKDOWN : Alpha::ADJUSTSTACKUP;
194     CurDAG->SelectNodeTo(N, Opc, MVT::Other,
195                          getI64Imm(Amt), Select(N->getOperand(0)));
196     return SDOperand(N, 0);
197   }
198   case ISD::RET: {
199     SDOperand Chain = Select(N->getOperand(0));     // Token chain.
200
201     if (N->getNumOperands() == 2) {
202       SDOperand Val = Select(N->getOperand(1));
203       if (N->getOperand(1).getValueType() == MVT::i64) {
204         Chain = CurDAG->getCopyToReg(Chain, Alpha::R0, Val);
205       }
206     }
207     //BuildMI(BB, Alpha::RET, 2, Alpha::R31).addReg(Alpha::R26).addImm(1);
208
209     // FIXME: add restoring of the RA to R26 to the chain
210     // Finally, select this to a ret instruction.
211     CurDAG->SelectNodeTo(N, Alpha::RETDAG, MVT::Other, Chain);
212     return SDOperand(N, 0);
213   }
214
215
216
217   }
218   
219   return SelectCode(Op);
220 }
221
222 SDOperand AlphaDAGToDAGISel::SelectCALL(SDOperand Op) {
223   SDNode *N = Op.Val;
224   SDOperand Chain = Select(N->getOperand(0));
225   SDOperand InFlag;  // Null incoming flag value.
226   SDOperand Addr = Select(N->getOperand(1));
227
228 //   unsigned CallOpcode;
229    std::vector<SDOperand> CallOperands;
230    std::vector<MVT::ValueType> TypeOperands;
231   
232    CallOperands.push_back(CurDAG->getCopyToReg(Chain, Alpha::R27, Addr));
233    CallOperands.push_back(getI64Imm(0));
234
235    //grab the arguments
236    for(int i = 2, e = N->getNumOperands(); i < e; ++i) {
237      CallOperands.push_back(Select(N->getOperand(i)));
238      TypeOperands.push_back(N->getOperand(i).getValueType());
239    }
240    static const unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
241                                        Alpha::R19, Alpha::R20, Alpha::R21};
242    static const unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
243                                          Alpha::F19, Alpha::F20, Alpha::F21};
244    
245    for (unsigned i = 0; i < std::min((size_t)6, CallOperands.size()); ++i) {
246      if (MVT::isInteger(TypeOperands[i])) {
247        Chain = CurDAG->getCopyToReg(Chain, args_int[i], CallOperands[i], InFlag);
248        InFlag = Chain.getValue(1);
249        CallOperands.push_back(CurDAG->getRegister(args_int[i], TypeOperands[i]));
250      } else {
251        assert(0 && "No FP support yet");
252      }
253    }
254    assert(CallOperands.size() <= 6 && "Too big a call");
255
256    // Finally, once everything is in registers to pass to the call, emit the
257    // call itself.
258    if (InFlag.Val)
259      CallOperands.push_back(InFlag);   // Strong dep on register copies.
260    else
261      CallOperands.push_back(Chain);    // Weak dep on whatever occurs before
262    Chain = CurDAG->getTargetNode(Alpha::JSR, MVT::Other, MVT::Flag, CallOperands);
263   
264    std::vector<SDOperand> CallResults;
265   
266    switch (N->getValueType(0)) {
267    default: assert(0 && "Unexpected ret value!");
268      case MVT::Other: break;
269    case MVT::i64:
270      Chain = CurDAG->getCopyFromReg(Chain, Alpha::R0, MVT::i64,
271                                     Chain.getValue(1)).getValue(1);
272      CallResults.push_back(Chain.getValue(0));
273      break;
274    }
275
276    CallResults.push_back(Chain);
277    for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
278      CodeGenMap[Op.getValue(i)] = CallResults[i];
279    return CallResults[Op.ResNo];
280 }
281
282
283 /// createAlphaISelDag - This pass converts a legalized DAG into a 
284 /// Alpha-specific DAG, ready for instruction scheduling.
285 ///
286 FunctionPass *llvm::createAlphaISelDag(TargetMachine &TM) {
287   return new AlphaDAGToDAGISel(TM);
288 }