ptx: add ld instruction and test
[oota-llvm.git] / lib / Target / PTX / PTXISelLowering.cpp
1 //===-- PTXISelLowering.cpp - PTX DAG Lowering Implementation -------------===//
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 implements the PTXTargetLowering class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "PTX.h"
15 #include "PTXISelLowering.h"
16 #include "PTXMachineFunctionInfo.h"
17 #include "PTXRegisterInfo.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/SelectionDAG.h"
22 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
23
24 using namespace llvm;
25
26 PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
27   : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
28   // Set up the register classes.
29   addRegisterClass(MVT::i1,  PTX::PredsRegisterClass);
30   addRegisterClass(MVT::i32, PTX::RRegs32RegisterClass);
31
32   setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
33
34   // Customize translation of memory addresses
35   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
36
37   // Compute derived properties from the register classes
38   computeRegisterProperties();
39 }
40
41 SDValue PTXTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
42   switch (Op.getOpcode()) {
43     default:                 llvm_unreachable("Unimplemented operand");
44     case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
45   }
46 }
47
48 const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
49   switch (Opcode) {
50     default:           llvm_unreachable("Unknown opcode");
51     case PTXISD::EXIT: return "PTXISD::EXIT";
52     case PTXISD::RET:  return "PTXISD::RET";
53   }
54 }
55
56 //===----------------------------------------------------------------------===//
57 //                      Custom Lower Operation
58 //===----------------------------------------------------------------------===//
59
60 SDValue PTXTargetLowering::
61 LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
62   EVT PtrVT = getPointerTy();
63   DebugLoc dl = Op.getDebugLoc();
64   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
65   return DAG.getTargetGlobalAddress(GV, dl, PtrVT);
66 }
67
68 //===----------------------------------------------------------------------===//
69 //                      Calling Convention Implementation
70 //===----------------------------------------------------------------------===//
71
72 namespace {
73 struct argmap_entry {
74   MVT::SimpleValueType VT;
75   TargetRegisterClass *RC;
76   TargetRegisterClass::iterator loc;
77
78   argmap_entry(MVT::SimpleValueType _VT, TargetRegisterClass *_RC)
79     : VT(_VT), RC(_RC), loc(_RC->begin()) {}
80
81   void reset() { loc = RC->begin(); }
82   bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; }
83 } argmap[] = {
84   argmap_entry(MVT::i1,  PTX::PredsRegisterClass),
85   argmap_entry(MVT::i32, PTX::RRegs32RegisterClass)
86 };
87 } // end anonymous namespace
88
89 static SDValue lower_kernel_argument(int i,
90                                      SDValue Chain,
91                                      DebugLoc dl,
92                                      MVT::SimpleValueType VT,
93                                      argmap_entry *entry,
94                                      SelectionDAG &DAG,
95                                      unsigned *argreg) {
96   // TODO
97   llvm_unreachable("Not implemented yet");
98 }
99
100 static SDValue lower_device_argument(int i,
101                                      SDValue Chain,
102                                      DebugLoc dl,
103                                      MVT::SimpleValueType VT,
104                                      argmap_entry *entry,
105                                      SelectionDAG &DAG,
106                                      unsigned *argreg) {
107   MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();
108
109   unsigned preg = *++(entry->loc); // allocate start from register 1
110   unsigned vreg = RegInfo.createVirtualRegister(entry->RC);
111   RegInfo.addLiveIn(preg, vreg);
112
113   *argreg = preg;
114   return DAG.getCopyFromReg(Chain, dl, vreg, VT);
115 }
116
117 typedef SDValue (*lower_argument_func)(int i,
118                                        SDValue Chain,
119                                        DebugLoc dl,
120                                        MVT::SimpleValueType VT,
121                                        argmap_entry *entry,
122                                        SelectionDAG &DAG,
123                                        unsigned *argreg);
124
125 SDValue PTXTargetLowering::
126   LowerFormalArguments(SDValue Chain,
127                        CallingConv::ID CallConv,
128                        bool isVarArg,
129                        const SmallVectorImpl<ISD::InputArg> &Ins,
130                        DebugLoc dl,
131                        SelectionDAG &DAG,
132                        SmallVectorImpl<SDValue> &InVals) const {
133   if (isVarArg) llvm_unreachable("PTX does not support varargs");
134
135   MachineFunction &MF = DAG.getMachineFunction();
136   PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
137
138   lower_argument_func lower_argument;
139
140   switch (CallConv) {
141     default:
142       llvm_unreachable("Unsupported calling convention");
143       break;
144     case CallingConv::PTX_Kernel:
145       MFI->setKernel();
146       lower_argument = lower_kernel_argument;
147       break;
148     case CallingConv::PTX_Device:
149       MFI->setKernel(false);
150       lower_argument = lower_device_argument;
151       break;
152   }
153
154   // Reset argmap before allocation
155   for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap);
156        i != e; ++ i)
157     i->reset();
158
159   for (int i = 0, e = Ins.size(); i != e; ++ i) {
160     MVT::SimpleValueType VT = Ins[i].VT.SimpleTy;
161
162     struct argmap_entry *entry = std::find(argmap,
163                                            argmap + array_lengthof(argmap), VT);
164     if (entry == argmap + array_lengthof(argmap))
165       llvm_unreachable("Type of argument is not supported");
166
167     unsigned reg;
168     SDValue arg = lower_argument(i, Chain, dl, VT, entry, DAG, &reg);
169     InVals.push_back(arg);
170
171     if (!MFI->isDoneAddArg())
172       MFI->addArgReg(reg);
173   }
174
175   // Make sure we don't add argument registers twice
176   if (!MFI->isDoneAddArg())
177     MFI->doneAddArg();
178
179   return Chain;
180 }
181
182 SDValue PTXTargetLowering::
183   LowerReturn(SDValue Chain,
184               CallingConv::ID CallConv,
185               bool isVarArg,
186               const SmallVectorImpl<ISD::OutputArg> &Outs,
187               const SmallVectorImpl<SDValue> &OutVals,
188               DebugLoc dl,
189               SelectionDAG &DAG) const {
190   if (isVarArg) llvm_unreachable("PTX does not support varargs");
191
192   switch (CallConv) {
193     default:
194       llvm_unreachable("Unsupported calling convention.");
195     case CallingConv::PTX_Kernel:
196       assert(Outs.size() == 0 && "Kernel must return void.");
197       return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
198     case CallingConv::PTX_Device:
199       assert(Outs.size() <= 1 && "Can at most return one value.");
200       break;
201   }
202
203   // PTX_Device
204
205   // return void
206   if (Outs.size() == 0)
207     return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
208
209   assert(Outs[0].VT == MVT::i32 && "Can return only basic types");
210
211   SDValue Flag;
212   unsigned reg = PTX::R0;
213
214   MachineFunction &MF = DAG.getMachineFunction();
215   PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
216   MFI->setRetReg(reg);
217
218   // If this is the first return lowered for this function, add the regs to the
219   // liveout set for the function
220   if (DAG.getMachineFunction().getRegInfo().liveout_empty())
221     DAG.getMachineFunction().getRegInfo().addLiveOut(reg);
222
223   // Copy the result values into the output registers
224   Chain = DAG.getCopyToReg(Chain, dl, reg, OutVals[0], Flag);
225
226   // Guarantee that all emitted copies are stuck together,
227   // avoiding something bad
228   Flag = Chain.getValue(1);
229
230   return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
231 }