1d8ea85acSTom Stellard //===-- llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp - Call lowering -----===//
2000c5af3STom Stellard //
3000c5af3STom Stellard //                     The LLVM Compiler Infrastructure
4000c5af3STom Stellard //
5000c5af3STom Stellard // This file is distributed under the University of Illinois Open Source
6000c5af3STom Stellard // License. See LICENSE.TXT for details.
7000c5af3STom Stellard //
8000c5af3STom Stellard //===----------------------------------------------------------------------===//
9000c5af3STom Stellard ///
10000c5af3STom Stellard /// \file
11000c5af3STom Stellard /// This file implements the lowering of LLVM calls to machine code calls for
12000c5af3STom Stellard /// GlobalISel.
13000c5af3STom Stellard ///
14000c5af3STom Stellard //===----------------------------------------------------------------------===//
15000c5af3STom Stellard 
16000c5af3STom Stellard #include "AMDGPUCallLowering.h"
17ca16621bSTom Stellard #include "AMDGPU.h"
18000c5af3STom Stellard #include "AMDGPUISelLowering.h"
19ca16621bSTom Stellard #include "AMDGPUSubtarget.h"
20ca16621bSTom Stellard #include "SIISelLowering.h"
21ca16621bSTom Stellard #include "SIMachineFunctionInfo.h"
226bda14b3SChandler Carruth #include "SIRegisterInfo.h"
23ca16621bSTom Stellard #include "llvm/CodeGen/CallingConvLower.h"
24000c5af3STom Stellard #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
25000c5af3STom Stellard #include "llvm/CodeGen/MachineInstrBuilder.h"
26000c5af3STom Stellard 
27000c5af3STom Stellard using namespace llvm;
28000c5af3STom Stellard 
29000c5af3STom Stellard AMDGPUCallLowering::AMDGPUCallLowering(const AMDGPUTargetLowering &TLI)
301a14bfa0SYaxun Liu   : CallLowering(&TLI), AMDGPUASI(TLI.getAMDGPUAS()) {
31000c5af3STom Stellard }
32000c5af3STom Stellard 
33000c5af3STom Stellard bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
34000c5af3STom Stellard                                      const Value *Val, unsigned VReg) const {
35*257882ffSTom Stellard   // FIXME: Add support for non-void returns.
36*257882ffSTom Stellard   if (Val)
37*257882ffSTom Stellard     return false;
38*257882ffSTom Stellard 
39ca16621bSTom Stellard   MIRBuilder.buildInstr(AMDGPU::S_ENDPGM);
40000c5af3STom Stellard   return true;
41000c5af3STom Stellard }
42000c5af3STom Stellard 
43ca16621bSTom Stellard unsigned AMDGPUCallLowering::lowerParameterPtr(MachineIRBuilder &MIRBuilder,
44ca16621bSTom Stellard                                                Type *ParamTy,
45ca16621bSTom Stellard                                                unsigned Offset) const {
46ca16621bSTom Stellard 
47ca16621bSTom Stellard   MachineFunction &MF = MIRBuilder.getMF();
488623e8d8SMatt Arsenault   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
49ca16621bSTom Stellard   MachineRegisterInfo &MRI = MF.getRegInfo();
50f1caa283SMatthias Braun   const Function &F = MF.getFunction();
51ca16621bSTom Stellard   const DataLayout &DL = F.getParent()->getDataLayout();
521a14bfa0SYaxun Liu   PointerType *PtrTy = PointerType::get(ParamTy, AMDGPUASI.CONSTANT_ADDRESS);
5352b4ce72SDaniel Sanders   LLT PtrType = getLLTForType(*PtrTy, DL);
54ca16621bSTom Stellard   unsigned DstReg = MRI.createGenericVirtualRegister(PtrType);
55ca16621bSTom Stellard   unsigned KernArgSegmentPtr =
568623e8d8SMatt Arsenault     MFI->getPreloadedReg(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
57ca16621bSTom Stellard   unsigned KernArgSegmentVReg = MRI.getLiveInVirtReg(KernArgSegmentPtr);
58ca16621bSTom Stellard 
59ca16621bSTom Stellard   unsigned OffsetReg = MRI.createGenericVirtualRegister(LLT::scalar(64));
60ca16621bSTom Stellard   MIRBuilder.buildConstant(OffsetReg, Offset);
61ca16621bSTom Stellard 
62ca16621bSTom Stellard   MIRBuilder.buildGEP(DstReg, KernArgSegmentVReg, OffsetReg);
63ca16621bSTom Stellard 
64ca16621bSTom Stellard   return DstReg;
65ca16621bSTom Stellard }
66ca16621bSTom Stellard 
67ca16621bSTom Stellard void AMDGPUCallLowering::lowerParameter(MachineIRBuilder &MIRBuilder,
68ca16621bSTom Stellard                                         Type *ParamTy, unsigned Offset,
69ca16621bSTom Stellard                                         unsigned DstReg) const {
70ca16621bSTom Stellard   MachineFunction &MF = MIRBuilder.getMF();
71f1caa283SMatthias Braun   const Function &F = MF.getFunction();
72ca16621bSTom Stellard   const DataLayout &DL = F.getParent()->getDataLayout();
731a14bfa0SYaxun Liu   PointerType *PtrTy = PointerType::get(ParamTy, AMDGPUASI.CONSTANT_ADDRESS);
74ca16621bSTom Stellard   MachinePointerInfo PtrInfo(UndefValue::get(PtrTy));
75ca16621bSTom Stellard   unsigned TypeSize = DL.getTypeStoreSize(ParamTy);
76ca16621bSTom Stellard   unsigned Align = DL.getABITypeAlignment(ParamTy);
77ca16621bSTom Stellard   unsigned PtrReg = lowerParameterPtr(MIRBuilder, ParamTy, Offset);
78ca16621bSTom Stellard 
79ca16621bSTom Stellard   MachineMemOperand *MMO =
80ca16621bSTom Stellard       MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad |
81ca16621bSTom Stellard                                        MachineMemOperand::MONonTemporal |
82ca16621bSTom Stellard                                        MachineMemOperand::MOInvariant,
83ca16621bSTom Stellard                                        TypeSize, Align);
84ca16621bSTom Stellard 
85ca16621bSTom Stellard   MIRBuilder.buildLoad(DstReg, PtrReg, *MMO);
86ca16621bSTom Stellard }
87ca16621bSTom Stellard 
88862758ecSTim Northover bool AMDGPUCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
89862758ecSTim Northover                                               const Function &F,
90406024a1STim Northover                                               ArrayRef<unsigned> VRegs) const {
91ca16621bSTom Stellard 
92ca16621bSTom Stellard   MachineFunction &MF = MIRBuilder.getMF();
93ca16621bSTom Stellard   const SISubtarget *Subtarget = static_cast<const SISubtarget *>(&MF.getSubtarget());
94ca16621bSTom Stellard   MachineRegisterInfo &MRI = MF.getRegInfo();
95ca16621bSTom Stellard   SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
96ca16621bSTom Stellard   const SIRegisterInfo *TRI = MF.getSubtarget<SISubtarget>().getRegisterInfo();
97ca16621bSTom Stellard   const DataLayout &DL = F.getParent()->getDataLayout();
98ca16621bSTom Stellard 
99ca16621bSTom Stellard   SmallVector<CCValAssign, 16> ArgLocs;
100ca16621bSTom Stellard   CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());
101ca16621bSTom Stellard 
102ca16621bSTom Stellard   // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
103ca16621bSTom Stellard   if (Info->hasPrivateSegmentBuffer()) {
104ca16621bSTom Stellard     unsigned PrivateSegmentBufferReg = Info->addPrivateSegmentBuffer(*TRI);
105ca16621bSTom Stellard     MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SReg_128RegClass);
106ca16621bSTom Stellard     CCInfo.AllocateReg(PrivateSegmentBufferReg);
107ca16621bSTom Stellard   }
108ca16621bSTom Stellard 
109ca16621bSTom Stellard   if (Info->hasDispatchPtr()) {
110ca16621bSTom Stellard     unsigned DispatchPtrReg = Info->addDispatchPtr(*TRI);
111ca16621bSTom Stellard     // FIXME: Need to add reg as live-in
112ca16621bSTom Stellard     CCInfo.AllocateReg(DispatchPtrReg);
113ca16621bSTom Stellard   }
114ca16621bSTom Stellard 
115ca16621bSTom Stellard   if (Info->hasQueuePtr()) {
116ca16621bSTom Stellard     unsigned QueuePtrReg = Info->addQueuePtr(*TRI);
117ca16621bSTom Stellard     // FIXME: Need to add reg as live-in
118ca16621bSTom Stellard     CCInfo.AllocateReg(QueuePtrReg);
119ca16621bSTom Stellard   }
120ca16621bSTom Stellard 
121ca16621bSTom Stellard   if (Info->hasKernargSegmentPtr()) {
122ca16621bSTom Stellard     unsigned InputPtrReg = Info->addKernargSegmentPtr(*TRI);
1230124b548SYaxun Liu     const LLT P2 = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
124ca16621bSTom Stellard     unsigned VReg = MRI.createGenericVirtualRegister(P2);
125ca16621bSTom Stellard     MRI.addLiveIn(InputPtrReg, VReg);
126ca16621bSTom Stellard     MIRBuilder.getMBB().addLiveIn(InputPtrReg);
127ca16621bSTom Stellard     MIRBuilder.buildCopy(VReg, InputPtrReg);
128ca16621bSTom Stellard     CCInfo.AllocateReg(InputPtrReg);
129ca16621bSTom Stellard   }
130ca16621bSTom Stellard 
131ca16621bSTom Stellard   if (Info->hasDispatchID()) {
132ca16621bSTom Stellard     unsigned DispatchIDReg = Info->addDispatchID(*TRI);
133ca16621bSTom Stellard     // FIXME: Need to add reg as live-in
134ca16621bSTom Stellard     CCInfo.AllocateReg(DispatchIDReg);
135ca16621bSTom Stellard   }
136ca16621bSTom Stellard 
137ca16621bSTom Stellard   if (Info->hasFlatScratchInit()) {
138ca16621bSTom Stellard     unsigned FlatScratchInitReg = Info->addFlatScratchInit(*TRI);
139ca16621bSTom Stellard     // FIXME: Need to add reg as live-in
140ca16621bSTom Stellard     CCInfo.AllocateReg(FlatScratchInitReg);
141ca16621bSTom Stellard   }
142ca16621bSTom Stellard 
143ca16621bSTom Stellard   unsigned NumArgs = F.arg_size();
144ca16621bSTom Stellard   Function::const_arg_iterator CurOrigArg = F.arg_begin();
145ca16621bSTom Stellard   const AMDGPUTargetLowering &TLI = *getTLI<AMDGPUTargetLowering>();
146c7709e1cSTom Stellard   unsigned PSInputNum = 0;
147c7709e1cSTom Stellard   BitVector Skipped(NumArgs);
148ca16621bSTom Stellard   for (unsigned i = 0; i != NumArgs; ++i, ++CurOrigArg) {
1499d8337d8STom Stellard     EVT ValEVT = TLI.getValueType(DL, CurOrigArg->getType());
1509d8337d8STom Stellard 
1519d8337d8STom Stellard     // We can only hanlde simple value types at the moment.
152ca16621bSTom Stellard     ISD::ArgFlagsTy Flags;
1539d8337d8STom Stellard     ArgInfo OrigArg{VRegs[i], CurOrigArg->getType()};
1549d8337d8STom Stellard     setArgFlags(OrigArg, i + 1, DL, F);
155ca16621bSTom Stellard     Flags.setOrigAlign(DL.getABITypeAlignment(CurOrigArg->getType()));
156c7709e1cSTom Stellard 
157c7709e1cSTom Stellard     if (F.getCallingConv() == CallingConv::AMDGPU_PS &&
158c7709e1cSTom Stellard         !OrigArg.Flags.isInReg() && !OrigArg.Flags.isByVal() &&
159c7709e1cSTom Stellard         PSInputNum <= 15) {
160c7709e1cSTom Stellard       if (CurOrigArg->use_empty() && !Info->isPSInputAllocated(PSInputNum)) {
161c7709e1cSTom Stellard         Skipped.set(i);
162c7709e1cSTom Stellard         ++PSInputNum;
163c7709e1cSTom Stellard         continue;
164c7709e1cSTom Stellard       }
165c7709e1cSTom Stellard 
166c7709e1cSTom Stellard       Info->markPSInputAllocated(PSInputNum);
167c7709e1cSTom Stellard       if (!CurOrigArg->use_empty())
168c7709e1cSTom Stellard         Info->markPSInputEnabled(PSInputNum);
169c7709e1cSTom Stellard 
170c7709e1cSTom Stellard       ++PSInputNum;
171c7709e1cSTom Stellard     }
172c7709e1cSTom Stellard 
173ca16621bSTom Stellard     CCAssignFn *AssignFn = CCAssignFnForCall(F.getCallingConv(),
174ca16621bSTom Stellard                                              /*IsVarArg=*/false);
175c7709e1cSTom Stellard 
176c7709e1cSTom Stellard     if (ValEVT.isVector()) {
177c7709e1cSTom Stellard       EVT ElemVT = ValEVT.getVectorElementType();
178c7709e1cSTom Stellard       if (!ValEVT.isSimple())
179c7709e1cSTom Stellard         return false;
180c7709e1cSTom Stellard       MVT ValVT = ElemVT.getSimpleVT();
181c7709e1cSTom Stellard       bool Res = AssignFn(i, ValVT, ValVT, CCValAssign::Full,
182c7709e1cSTom Stellard                           OrigArg.Flags, CCInfo);
183c7709e1cSTom Stellard       if (!Res)
184c7709e1cSTom Stellard         return false;
185c7709e1cSTom Stellard     } else {
186c7709e1cSTom Stellard       MVT ValVT = ValEVT.getSimpleVT();
187c7709e1cSTom Stellard       if (!ValEVT.isSimple())
188c7709e1cSTom Stellard         return false;
189ca16621bSTom Stellard       bool Res =
1909d8337d8STom Stellard           AssignFn(i, ValVT, ValVT, CCValAssign::Full, OrigArg.Flags, CCInfo);
1919d8337d8STom Stellard 
1929d8337d8STom Stellard       // Fail if we don't know how to handle this type.
1939d8337d8STom Stellard       if (Res)
1949d8337d8STom Stellard         return false;
195ca16621bSTom Stellard     }
196c7709e1cSTom Stellard   }
197ca16621bSTom Stellard 
198ca16621bSTom Stellard   Function::const_arg_iterator Arg = F.arg_begin();
1999d8337d8STom Stellard 
200c7709e1cSTom Stellard   if (F.getCallingConv() == CallingConv::AMDGPU_VS ||
201c7709e1cSTom Stellard       F.getCallingConv() == CallingConv::AMDGPU_PS) {
202c7709e1cSTom Stellard     for (unsigned i = 0, OrigArgIdx = 0;
203c7709e1cSTom Stellard          OrigArgIdx != NumArgs && i != ArgLocs.size(); ++Arg, ++OrigArgIdx) {
204c7709e1cSTom Stellard        if (Skipped.test(OrigArgIdx))
205c7709e1cSTom Stellard           continue;
206c7709e1cSTom Stellard       CCValAssign &VA = ArgLocs[i++];
207c7709e1cSTom Stellard       MRI.addLiveIn(VA.getLocReg(), VRegs[OrigArgIdx]);
2089d8337d8STom Stellard       MIRBuilder.getMBB().addLiveIn(VA.getLocReg());
209c7709e1cSTom Stellard       MIRBuilder.buildCopy(VRegs[OrigArgIdx], VA.getLocReg());
2109d8337d8STom Stellard     }
2119d8337d8STom Stellard     return true;
2129d8337d8STom Stellard   }
2139d8337d8STom Stellard 
214c7709e1cSTom Stellard   for (unsigned i = 0; i != ArgLocs.size(); ++i, ++Arg) {
215ca16621bSTom Stellard     // FIXME: We should be getting DebugInfo from the arguments some how.
216ca16621bSTom Stellard     CCValAssign &VA = ArgLocs[i];
217ca16621bSTom Stellard     lowerParameter(MIRBuilder, Arg->getType(),
218ca16621bSTom Stellard                    VA.getLocMemOffset() +
219ca16621bSTom Stellard                    Subtarget->getExplicitKernelArgOffset(MF), VRegs[i]);
220ca16621bSTom Stellard   }
221ca16621bSTom Stellard 
222000c5af3STom Stellard   return true;
223000c5af3STom Stellard }
224