1 //===-- llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp - Call lowering -----===//
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 /// \file
11 /// This file implements the lowering of LLVM calls to machine code calls for
12 /// GlobalISel.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "AMDGPUCallLowering.h"
17 #include "AMDGPU.h"
18 #include "AMDGPUISelLowering.h"
19 #include "AMDGPUSubtarget.h"
20 #include "SIISelLowering.h"
21 #include "SIMachineFunctionInfo.h"
22 #include "SIRegisterInfo.h"
23 #include "llvm/CodeGen/CallingConvLower.h"
24 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 
27 using namespace llvm;
28 
29 AMDGPUCallLowering::AMDGPUCallLowering(const AMDGPUTargetLowering &TLI)
30   : CallLowering(&TLI), AMDGPUASI(TLI.getAMDGPUAS()) {
31 }
32 
33 bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
34                                      const Value *Val, unsigned VReg) const {
35   MIRBuilder.buildInstr(AMDGPU::S_ENDPGM);
36   return true;
37 }
38 
39 unsigned AMDGPUCallLowering::lowerParameterPtr(MachineIRBuilder &MIRBuilder,
40                                                Type *ParamTy,
41                                                unsigned Offset) const {
42 
43   MachineFunction &MF = MIRBuilder.getMF();
44   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
45   MachineRegisterInfo &MRI = MF.getRegInfo();
46   const Function &F = MF.getFunction();
47   const DataLayout &DL = F.getParent()->getDataLayout();
48   PointerType *PtrTy = PointerType::get(ParamTy, AMDGPUASI.CONSTANT_ADDRESS);
49   LLT PtrType = getLLTForType(*PtrTy, DL);
50   unsigned DstReg = MRI.createGenericVirtualRegister(PtrType);
51   unsigned KernArgSegmentPtr =
52     MFI->getPreloadedReg(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
53   unsigned KernArgSegmentVReg = MRI.getLiveInVirtReg(KernArgSegmentPtr);
54 
55   unsigned OffsetReg = MRI.createGenericVirtualRegister(LLT::scalar(64));
56   MIRBuilder.buildConstant(OffsetReg, Offset);
57 
58   MIRBuilder.buildGEP(DstReg, KernArgSegmentVReg, OffsetReg);
59 
60   return DstReg;
61 }
62 
63 void AMDGPUCallLowering::lowerParameter(MachineIRBuilder &MIRBuilder,
64                                         Type *ParamTy, unsigned Offset,
65                                         unsigned DstReg) const {
66   MachineFunction &MF = MIRBuilder.getMF();
67   const Function &F = MF.getFunction();
68   const DataLayout &DL = F.getParent()->getDataLayout();
69   PointerType *PtrTy = PointerType::get(ParamTy, AMDGPUASI.CONSTANT_ADDRESS);
70   MachinePointerInfo PtrInfo(UndefValue::get(PtrTy));
71   unsigned TypeSize = DL.getTypeStoreSize(ParamTy);
72   unsigned Align = DL.getABITypeAlignment(ParamTy);
73   unsigned PtrReg = lowerParameterPtr(MIRBuilder, ParamTy, Offset);
74 
75   MachineMemOperand *MMO =
76       MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad |
77                                        MachineMemOperand::MONonTemporal |
78                                        MachineMemOperand::MOInvariant,
79                                        TypeSize, Align);
80 
81   MIRBuilder.buildLoad(DstReg, PtrReg, *MMO);
82 }
83 
84 bool AMDGPUCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
85                                               const Function &F,
86                                               ArrayRef<unsigned> VRegs) const {
87 
88   MachineFunction &MF = MIRBuilder.getMF();
89   const SISubtarget *Subtarget = static_cast<const SISubtarget *>(&MF.getSubtarget());
90   MachineRegisterInfo &MRI = MF.getRegInfo();
91   SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
92   const SIRegisterInfo *TRI = MF.getSubtarget<SISubtarget>().getRegisterInfo();
93   const DataLayout &DL = F.getParent()->getDataLayout();
94 
95   SmallVector<CCValAssign, 16> ArgLocs;
96   CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());
97 
98   // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
99   if (Info->hasPrivateSegmentBuffer()) {
100     unsigned PrivateSegmentBufferReg = Info->addPrivateSegmentBuffer(*TRI);
101     MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SReg_128RegClass);
102     CCInfo.AllocateReg(PrivateSegmentBufferReg);
103   }
104 
105   if (Info->hasDispatchPtr()) {
106     unsigned DispatchPtrReg = Info->addDispatchPtr(*TRI);
107     // FIXME: Need to add reg as live-in
108     CCInfo.AllocateReg(DispatchPtrReg);
109   }
110 
111   if (Info->hasQueuePtr()) {
112     unsigned QueuePtrReg = Info->addQueuePtr(*TRI);
113     // FIXME: Need to add reg as live-in
114     CCInfo.AllocateReg(QueuePtrReg);
115   }
116 
117   if (Info->hasKernargSegmentPtr()) {
118     unsigned InputPtrReg = Info->addKernargSegmentPtr(*TRI);
119     const LLT P2 = LLT::pointer(2, 64);
120     unsigned VReg = MRI.createGenericVirtualRegister(P2);
121     MRI.addLiveIn(InputPtrReg, VReg);
122     MIRBuilder.getMBB().addLiveIn(InputPtrReg);
123     MIRBuilder.buildCopy(VReg, InputPtrReg);
124     CCInfo.AllocateReg(InputPtrReg);
125   }
126 
127   if (Info->hasDispatchID()) {
128     unsigned DispatchIDReg = Info->addDispatchID(*TRI);
129     // FIXME: Need to add reg as live-in
130     CCInfo.AllocateReg(DispatchIDReg);
131   }
132 
133   if (Info->hasFlatScratchInit()) {
134     unsigned FlatScratchInitReg = Info->addFlatScratchInit(*TRI);
135     // FIXME: Need to add reg as live-in
136     CCInfo.AllocateReg(FlatScratchInitReg);
137   }
138 
139   unsigned NumArgs = F.arg_size();
140   Function::const_arg_iterator CurOrigArg = F.arg_begin();
141   const AMDGPUTargetLowering &TLI = *getTLI<AMDGPUTargetLowering>();
142   for (unsigned i = 0; i != NumArgs; ++i, ++CurOrigArg) {
143     EVT ValEVT = TLI.getValueType(DL, CurOrigArg->getType());
144 
145     // We can only hanlde simple value types at the moment.
146     if (!ValEVT.isSimple())
147       return false;
148     MVT ValVT = ValEVT.getSimpleVT();
149     ISD::ArgFlagsTy Flags;
150     ArgInfo OrigArg{VRegs[i], CurOrigArg->getType()};
151     setArgFlags(OrigArg, i + 1, DL, F);
152     Flags.setOrigAlign(DL.getABITypeAlignment(CurOrigArg->getType()));
153     CCAssignFn *AssignFn = CCAssignFnForCall(F.getCallingConv(),
154                                              /*IsVarArg=*/false);
155     bool Res =
156         AssignFn(i, ValVT, ValVT, CCValAssign::Full, OrigArg.Flags, CCInfo);
157 
158     // Fail if we don't know how to handle this type.
159     if (Res)
160       return false;
161   }
162 
163   Function::const_arg_iterator Arg = F.arg_begin();
164 
165   if (F.getCallingConv() == CallingConv::AMDGPU_VS) {
166     for (unsigned i = 0; i != NumArgs; ++i, ++Arg) {
167       CCValAssign &VA = ArgLocs[i];
168       MRI.addLiveIn(VA.getLocReg(), VRegs[i]);
169       MIRBuilder.getMBB().addLiveIn(VA.getLocReg());
170       MIRBuilder.buildCopy(VRegs[i], VA.getLocReg());
171     }
172     return true;
173   }
174 
175   for (unsigned i = 0; i != NumArgs; ++i, ++Arg) {
176     // FIXME: We should be getting DebugInfo from the arguments some how.
177     CCValAssign &VA = ArgLocs[i];
178     lowerParameter(MIRBuilder, Arg->getType(),
179                    VA.getLocMemOffset() +
180                    Subtarget->getExplicitKernelArgOffset(MF), VRegs[i]);
181   }
182 
183   return true;
184 }
185