1 //===- SIMachineFunctionInfo.cpp - SI Machine Function Info ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SIMachineFunctionInfo.h"
10 #include "AMDGPUArgumentUsageInfo.h"
11 #include "AMDGPUTargetMachine.h"
12 #include "AMDGPUSubtarget.h"
13 #include "SIRegisterInfo.h"
14 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
15 #include "Utils/AMDGPUBaseInfo.h"
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/IR/CallingConv.h"
22 #include "llvm/IR/Function.h"
23 #include <cassert>
24 #include <vector>
25 
26 #define MAX_LANES 64
27 
28 using namespace llvm;
29 
30 SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
31   : AMDGPUMachineFunction(MF),
32     PrivateSegmentBuffer(false),
33     DispatchPtr(false),
34     QueuePtr(false),
35     KernargSegmentPtr(false),
36     DispatchID(false),
37     FlatScratchInit(false),
38     WorkGroupIDX(false),
39     WorkGroupIDY(false),
40     WorkGroupIDZ(false),
41     WorkGroupInfo(false),
42     PrivateSegmentWaveByteOffset(false),
43     WorkItemIDX(false),
44     WorkItemIDY(false),
45     WorkItemIDZ(false),
46     ImplicitBufferPtr(false),
47     ImplicitArgPtr(false),
48     GITPtrHigh(0xffffffff),
49     HighBitsOf32BitAddress(0),
50     GDSSize(0) {
51   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
52   const Function &F = MF.getFunction();
53   FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
54   WavesPerEU = ST.getWavesPerEU(F);
55 
56   Occupancy = ST.computeOccupancy(MF, getLDSSize());
57   CallingConv::ID CC = F.getCallingConv();
58   const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
59 
60   // FIXME: Should have analysis or something rather than attribute to detect
61   // calls.
62   const bool HasCalls = FrameInfo.hasCalls() || F.hasFnAttribute("amdgpu-calls");
63 
64   // Enable all kernel inputs if we have the fixed ABI. Don't bother if we don't
65   // have any calls.
66   const bool UseFixedABI = AMDGPUTargetMachine::EnableFixedFunctionABI &&
67                            (!isEntryFunction() || HasCalls);
68 
69   if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL) {
70     if (!F.arg_empty())
71       KernargSegmentPtr = true;
72     WorkGroupIDX = true;
73     WorkItemIDX = true;
74   } else if (CC == CallingConv::AMDGPU_PS) {
75     PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
76   }
77 
78   if (!isEntryFunction()) {
79     // Non-entry functions have no special inputs for now, other registers
80     // required for scratch access.
81     ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
82     ScratchWaveOffsetReg = AMDGPU::SGPR33;
83 
84     // TODO: Pick a high register, and shift down, similar to a kernel.
85     FrameOffsetReg = AMDGPU::SGPR34;
86     StackPtrOffsetReg = AMDGPU::SGPR32;
87 
88     ArgInfo.PrivateSegmentBuffer =
89       ArgDescriptor::createRegister(ScratchRSrcReg);
90     ArgInfo.PrivateSegmentWaveByteOffset =
91       ArgDescriptor::createRegister(ScratchWaveOffsetReg);
92 
93     if (F.hasFnAttribute("amdgpu-implicitarg-ptr"))
94       ImplicitArgPtr = true;
95   } else {
96     if (F.hasFnAttribute("amdgpu-implicitarg-ptr")) {
97       KernargSegmentPtr = true;
98       MaxKernArgAlign = std::max(ST.getAlignmentForImplicitArgPtr(),
99                                  MaxKernArgAlign);
100     }
101   }
102 
103   if (UseFixedABI) {
104     WorkGroupIDX = true;
105     WorkGroupIDY = true;
106     WorkGroupIDZ = true;
107     WorkItemIDX = true;
108     WorkItemIDY = true;
109     WorkItemIDZ = true;
110     ImplicitArgPtr = true;
111   } else {
112     if (F.hasFnAttribute("amdgpu-work-group-id-x"))
113       WorkGroupIDX = true;
114 
115     if (F.hasFnAttribute("amdgpu-work-group-id-y"))
116       WorkGroupIDY = true;
117 
118     if (F.hasFnAttribute("amdgpu-work-group-id-z"))
119       WorkGroupIDZ = true;
120 
121     if (F.hasFnAttribute("amdgpu-work-item-id-x"))
122       WorkItemIDX = true;
123 
124     if (F.hasFnAttribute("amdgpu-work-item-id-y"))
125       WorkItemIDY = true;
126 
127     if (F.hasFnAttribute("amdgpu-work-item-id-z"))
128       WorkItemIDZ = true;
129   }
130 
131   bool HasStackObjects = FrameInfo.hasStackObjects();
132 
133   if (isEntryFunction()) {
134     // X, XY, and XYZ are the only supported combinations, so make sure Y is
135     // enabled if Z is.
136     if (WorkItemIDZ)
137       WorkItemIDY = true;
138 
139     PrivateSegmentWaveByteOffset = true;
140 
141     // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
142     if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
143         (CC == CallingConv::AMDGPU_HS || CC == CallingConv::AMDGPU_GS))
144       ArgInfo.PrivateSegmentWaveByteOffset =
145           ArgDescriptor::createRegister(AMDGPU::SGPR5);
146   }
147 
148   bool isAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
149   if (isAmdHsaOrMesa) {
150     PrivateSegmentBuffer = true;
151 
152     if (UseFixedABI) {
153       DispatchPtr = true;
154       QueuePtr = true;
155 
156       // FIXME: We don't need this?
157       DispatchID = true;
158     } else {
159       if (F.hasFnAttribute("amdgpu-dispatch-ptr"))
160         DispatchPtr = true;
161 
162       if (F.hasFnAttribute("amdgpu-queue-ptr"))
163         QueuePtr = true;
164 
165       if (F.hasFnAttribute("amdgpu-dispatch-id"))
166         DispatchID = true;
167     }
168   } else if (ST.isMesaGfxShader(F)) {
169     ImplicitBufferPtr = true;
170   }
171 
172   if (UseFixedABI || F.hasFnAttribute("amdgpu-kernarg-segment-ptr"))
173     KernargSegmentPtr = true;
174 
175   if (ST.hasFlatAddressSpace() && isEntryFunction() && isAmdHsaOrMesa) {
176     auto hasNonSpillStackObjects = [&]() {
177       // Avoid expensive checking if there's no stack objects.
178       if (!HasStackObjects)
179         return false;
180       for (auto OI = FrameInfo.getObjectIndexBegin(),
181                 OE = FrameInfo.getObjectIndexEnd(); OI != OE; ++OI)
182         if (!FrameInfo.isSpillSlotObjectIndex(OI))
183           return true;
184       // All stack objects are spill slots.
185       return false;
186     };
187     // TODO: This could be refined a lot. The attribute is a poor way of
188     // detecting calls that may require it before argument lowering.
189     if (HasCalls || hasNonSpillStackObjects())
190       FlatScratchInit = true;
191   }
192 
193   Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
194   StringRef S = A.getValueAsString();
195   if (!S.empty())
196     S.consumeInteger(0, GITPtrHigh);
197 
198   A = F.getFnAttribute("amdgpu-32bit-address-high-bits");
199   S = A.getValueAsString();
200   if (!S.empty())
201     S.consumeInteger(0, HighBitsOf32BitAddress);
202 
203   S = F.getFnAttribute("amdgpu-gds-size").getValueAsString();
204   if (!S.empty())
205     S.consumeInteger(0, GDSSize);
206 }
207 
208 void SIMachineFunctionInfo::limitOccupancy(const MachineFunction &MF) {
209   limitOccupancy(getMaxWavesPerEU());
210   const GCNSubtarget& ST = MF.getSubtarget<GCNSubtarget>();
211   limitOccupancy(ST.getOccupancyWithLocalMemSize(getLDSSize(),
212                  MF.getFunction()));
213 }
214 
215 unsigned SIMachineFunctionInfo::addPrivateSegmentBuffer(
216   const SIRegisterInfo &TRI) {
217   ArgInfo.PrivateSegmentBuffer =
218     ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
219     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SGPR_128RegClass));
220   NumUserSGPRs += 4;
221   return ArgInfo.PrivateSegmentBuffer.getRegister();
222 }
223 
224 unsigned SIMachineFunctionInfo::addDispatchPtr(const SIRegisterInfo &TRI) {
225   ArgInfo.DispatchPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
226     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
227   NumUserSGPRs += 2;
228   return ArgInfo.DispatchPtr.getRegister();
229 }
230 
231 unsigned SIMachineFunctionInfo::addQueuePtr(const SIRegisterInfo &TRI) {
232   ArgInfo.QueuePtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
233     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
234   NumUserSGPRs += 2;
235   return ArgInfo.QueuePtr.getRegister();
236 }
237 
238 unsigned SIMachineFunctionInfo::addKernargSegmentPtr(const SIRegisterInfo &TRI) {
239   ArgInfo.KernargSegmentPtr
240     = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
241     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
242   NumUserSGPRs += 2;
243   return ArgInfo.KernargSegmentPtr.getRegister();
244 }
245 
246 unsigned SIMachineFunctionInfo::addDispatchID(const SIRegisterInfo &TRI) {
247   ArgInfo.DispatchID = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
248     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
249   NumUserSGPRs += 2;
250   return ArgInfo.DispatchID.getRegister();
251 }
252 
253 unsigned SIMachineFunctionInfo::addFlatScratchInit(const SIRegisterInfo &TRI) {
254   ArgInfo.FlatScratchInit = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
255     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
256   NumUserSGPRs += 2;
257   return ArgInfo.FlatScratchInit.getRegister();
258 }
259 
260 unsigned SIMachineFunctionInfo::addImplicitBufferPtr(const SIRegisterInfo &TRI) {
261   ArgInfo.ImplicitBufferPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
262     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
263   NumUserSGPRs += 2;
264   return ArgInfo.ImplicitBufferPtr.getRegister();
265 }
266 
267 static bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg) {
268   for (unsigned I = 0; CSRegs[I]; ++I) {
269     if (CSRegs[I] == Reg)
270       return true;
271   }
272 
273   return false;
274 }
275 
276 /// \p returns true if \p NumLanes slots are available in VGPRs already used for
277 /// SGPR spilling.
278 //
279 // FIXME: This only works after processFunctionBeforeFrameFinalized
280 bool SIMachineFunctionInfo::haveFreeLanesForSGPRSpill(const MachineFunction &MF,
281                                                       unsigned NumNeed) const {
282   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
283   unsigned WaveSize = ST.getWavefrontSize();
284   return NumVGPRSpillLanes + NumNeed <= WaveSize * SpillVGPRs.size();
285 }
286 
287 /// Reserve a slice of a VGPR to support spilling for FrameIndex \p FI.
288 bool SIMachineFunctionInfo::allocateSGPRSpillToVGPR(MachineFunction &MF,
289                                                     int FI) {
290   std::vector<SpilledReg> &SpillLanes = SGPRToVGPRSpills[FI];
291 
292   // This has already been allocated.
293   if (!SpillLanes.empty())
294     return true;
295 
296   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
297   const SIRegisterInfo *TRI = ST.getRegisterInfo();
298   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
299   MachineRegisterInfo &MRI = MF.getRegInfo();
300   unsigned WaveSize = ST.getWavefrontSize();
301 
302   unsigned Size = FrameInfo.getObjectSize(FI);
303   assert(Size >= 4 && Size <= 64 && "invalid sgpr spill size");
304   assert(TRI->spillSGPRToVGPR() && "not spilling SGPRs to VGPRs");
305 
306   int NumLanes = Size / 4;
307 
308   const MCPhysReg *CSRegs = MRI.getCalleeSavedRegs();
309 
310   // Make sure to handle the case where a wide SGPR spill may span between two
311   // VGPRs.
312   for (int I = 0; I < NumLanes; ++I, ++NumVGPRSpillLanes) {
313     unsigned LaneVGPR;
314     unsigned VGPRIndex = (NumVGPRSpillLanes % WaveSize);
315 
316     if (VGPRIndex == 0) {
317       LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF);
318       if (LaneVGPR == AMDGPU::NoRegister) {
319         // We have no VGPRs left for spilling SGPRs. Reset because we will not
320         // partially spill the SGPR to VGPRs.
321         SGPRToVGPRSpills.erase(FI);
322         NumVGPRSpillLanes -= I;
323         return false;
324       }
325 
326       Optional<int> CSRSpillFI;
327       if ((FrameInfo.hasCalls() || !isEntryFunction()) && CSRegs &&
328           isCalleeSavedReg(CSRegs, LaneVGPR)) {
329         CSRSpillFI = FrameInfo.CreateSpillStackObject(4, 4);
330       }
331 
332       SpillVGPRs.push_back(SGPRSpillVGPRCSR(LaneVGPR, CSRSpillFI));
333 
334       // Add this register as live-in to all blocks to avoid machine verifer
335       // complaining about use of an undefined physical register.
336       for (MachineBasicBlock &BB : MF)
337         BB.addLiveIn(LaneVGPR);
338     } else {
339       LaneVGPR = SpillVGPRs.back().VGPR;
340     }
341 
342     SpillLanes.push_back(SpilledReg(LaneVGPR, VGPRIndex));
343   }
344 
345   return true;
346 }
347 
348 /// Reserve AGPRs or VGPRs to support spilling for FrameIndex \p FI.
349 /// Either AGPR is spilled to VGPR to vice versa.
350 /// Returns true if a \p FI can be eliminated completely.
351 bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
352                                                     int FI,
353                                                     bool isAGPRtoVGPR) {
354   MachineRegisterInfo &MRI = MF.getRegInfo();
355   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
356   const GCNSubtarget &ST =  MF.getSubtarget<GCNSubtarget>();
357 
358   assert(ST.hasMAIInsts() && FrameInfo.isSpillSlotObjectIndex(FI));
359 
360   auto &Spill = VGPRToAGPRSpills[FI];
361 
362   // This has already been allocated.
363   if (!Spill.Lanes.empty())
364     return Spill.FullyAllocated;
365 
366   unsigned Size = FrameInfo.getObjectSize(FI);
367   unsigned NumLanes = Size / 4;
368   Spill.Lanes.resize(NumLanes, AMDGPU::NoRegister);
369 
370   const TargetRegisterClass &RC =
371       isAGPRtoVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::AGPR_32RegClass;
372   auto Regs = RC.getRegisters();
373 
374   auto &SpillRegs = isAGPRtoVGPR ? SpillAGPR : SpillVGPR;
375   const SIRegisterInfo *TRI = ST.getRegisterInfo();
376   Spill.FullyAllocated = true;
377 
378   // FIXME: Move allocation logic out of MachineFunctionInfo and initialize
379   // once.
380   BitVector OtherUsedRegs;
381   OtherUsedRegs.resize(TRI->getNumRegs());
382 
383   const uint32_t *CSRMask =
384       TRI->getCallPreservedMask(MF, MF.getFunction().getCallingConv());
385   if (CSRMask)
386     OtherUsedRegs.setBitsInMask(CSRMask);
387 
388   // TODO: Should include register tuples, but doesn't matter with current
389   // usage.
390   for (MCPhysReg Reg : SpillAGPR)
391     OtherUsedRegs.set(Reg);
392   for (MCPhysReg Reg : SpillVGPR)
393     OtherUsedRegs.set(Reg);
394 
395   SmallVectorImpl<MCPhysReg>::const_iterator NextSpillReg = Regs.begin();
396   for (unsigned I = 0; I < NumLanes; ++I) {
397     NextSpillReg = std::find_if(
398         NextSpillReg, Regs.end(), [&MRI, &OtherUsedRegs](MCPhysReg Reg) {
399           return MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg) &&
400                  !OtherUsedRegs[Reg];
401         });
402 
403     if (NextSpillReg == Regs.end()) { // Registers exhausted
404       Spill.FullyAllocated = false;
405       break;
406     }
407 
408     OtherUsedRegs.set(*NextSpillReg);
409     SpillRegs.push_back(*NextSpillReg);
410     Spill.Lanes[I] = *NextSpillReg++;
411   }
412 
413   return Spill.FullyAllocated;
414 }
415 
416 void SIMachineFunctionInfo::removeDeadFrameIndices(MachineFrameInfo &MFI) {
417   // The FP spill hasn't been inserted yet, so keep it around.
418   for (auto &R : SGPRToVGPRSpills) {
419     if (R.first != FramePointerSaveIndex)
420       MFI.RemoveStackObject(R.first);
421   }
422 
423   // All other SPGRs must be allocated on the default stack, so reset the stack
424   // ID.
425   for (int i = MFI.getObjectIndexBegin(), e = MFI.getObjectIndexEnd(); i != e;
426        ++i)
427     if (i != FramePointerSaveIndex)
428       MFI.setStackID(i, TargetStackID::Default);
429 
430   for (auto &R : VGPRToAGPRSpills) {
431     if (R.second.FullyAllocated)
432       MFI.RemoveStackObject(R.first);
433   }
434 }
435 
436 MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
437   assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
438   return AMDGPU::SGPR0 + NumUserSGPRs;
439 }
440 
441 MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
442   return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
443 }
444 
445 static yaml::StringValue regToString(unsigned Reg,
446                                      const TargetRegisterInfo &TRI) {
447   yaml::StringValue Dest;
448   {
449     raw_string_ostream OS(Dest.Value);
450     OS << printReg(Reg, &TRI);
451   }
452   return Dest;
453 }
454 
455 static Optional<yaml::SIArgumentInfo>
456 convertArgumentInfo(const AMDGPUFunctionArgInfo &ArgInfo,
457                     const TargetRegisterInfo &TRI) {
458   yaml::SIArgumentInfo AI;
459 
460   auto convertArg = [&](Optional<yaml::SIArgument> &A,
461                         const ArgDescriptor &Arg) {
462     if (!Arg)
463       return false;
464 
465     // Create a register or stack argument.
466     yaml::SIArgument SA = yaml::SIArgument::createArgument(Arg.isRegister());
467     if (Arg.isRegister()) {
468       raw_string_ostream OS(SA.RegisterName.Value);
469       OS << printReg(Arg.getRegister(), &TRI);
470     } else
471       SA.StackOffset = Arg.getStackOffset();
472     // Check and update the optional mask.
473     if (Arg.isMasked())
474       SA.Mask = Arg.getMask();
475 
476     A = SA;
477     return true;
478   };
479 
480   bool Any = false;
481   Any |= convertArg(AI.PrivateSegmentBuffer, ArgInfo.PrivateSegmentBuffer);
482   Any |= convertArg(AI.DispatchPtr, ArgInfo.DispatchPtr);
483   Any |= convertArg(AI.QueuePtr, ArgInfo.QueuePtr);
484   Any |= convertArg(AI.KernargSegmentPtr, ArgInfo.KernargSegmentPtr);
485   Any |= convertArg(AI.DispatchID, ArgInfo.DispatchID);
486   Any |= convertArg(AI.FlatScratchInit, ArgInfo.FlatScratchInit);
487   Any |= convertArg(AI.PrivateSegmentSize, ArgInfo.PrivateSegmentSize);
488   Any |= convertArg(AI.WorkGroupIDX, ArgInfo.WorkGroupIDX);
489   Any |= convertArg(AI.WorkGroupIDY, ArgInfo.WorkGroupIDY);
490   Any |= convertArg(AI.WorkGroupIDZ, ArgInfo.WorkGroupIDZ);
491   Any |= convertArg(AI.WorkGroupInfo, ArgInfo.WorkGroupInfo);
492   Any |= convertArg(AI.PrivateSegmentWaveByteOffset,
493                     ArgInfo.PrivateSegmentWaveByteOffset);
494   Any |= convertArg(AI.ImplicitArgPtr, ArgInfo.ImplicitArgPtr);
495   Any |= convertArg(AI.ImplicitBufferPtr, ArgInfo.ImplicitBufferPtr);
496   Any |= convertArg(AI.WorkItemIDX, ArgInfo.WorkItemIDX);
497   Any |= convertArg(AI.WorkItemIDY, ArgInfo.WorkItemIDY);
498   Any |= convertArg(AI.WorkItemIDZ, ArgInfo.WorkItemIDZ);
499 
500   if (Any)
501     return AI;
502 
503   return None;
504 }
505 
506 yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
507   const llvm::SIMachineFunctionInfo& MFI,
508   const TargetRegisterInfo &TRI)
509   : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
510     MaxKernArgAlign(MFI.getMaxKernArgAlign()),
511     LDSSize(MFI.getLDSSize()),
512     IsEntryFunction(MFI.isEntryFunction()),
513     NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
514     MemoryBound(MFI.isMemoryBound()),
515     WaveLimiter(MFI.needsWaveLimiter()),
516     HighBitsOf32BitAddress(MFI.get32BitAddressHighBits()),
517     ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
518     ScratchWaveOffsetReg(regToString(MFI.getScratchWaveOffsetReg(), TRI)),
519     FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
520     StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)),
521     ArgInfo(convertArgumentInfo(MFI.getArgInfo(), TRI)),
522     Mode(MFI.getMode()) {}
523 
524 void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
525   MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
526 }
527 
528 bool SIMachineFunctionInfo::initializeBaseYamlFields(
529   const yaml::SIMachineFunctionInfo &YamlMFI) {
530   ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
531   MaxKernArgAlign = assumeAligned(YamlMFI.MaxKernArgAlign);
532   LDSSize = YamlMFI.LDSSize;
533   HighBitsOf32BitAddress = YamlMFI.HighBitsOf32BitAddress;
534   IsEntryFunction = YamlMFI.IsEntryFunction;
535   NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
536   MemoryBound = YamlMFI.MemoryBound;
537   WaveLimiter = YamlMFI.WaveLimiter;
538   return false;
539 }
540