LLVM 24.0.0git
SIMachineFunctionInfo.cpp
Go to the documentation of this file.
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
10#include "AMDGPUSubtarget.h"
11#include "GCNSubtarget.h"
12#include "SIRegisterInfo.h"
20#include "llvm/IR/CallingConv.h"
22#include "llvm/IR/Function.h"
23#include <cassert>
24#include <optional>
25
26enum { MAX_LANES = 64 };
27
28using namespace llvm;
29
30// TODO -- delete this flag once we have more robust mechanisms to allocate the
31// optimal RC for Opc and Dest of MFMA. In particular, there are high RP cases
32// where it is better to produce the VGPR form (e.g. if there are VGPR users
33// of the MFMA result).
35 "amdgpu-mfma-vgpr-form",
36 cl::desc("Whether to force use VGPR for Opc and Dest of MFMA. If "
37 "unspecified, default to compiler heuristics"),
40
42 const SITargetLowering *TLI = STI->getTargetLowering();
43 return static_cast<const GCNTargetMachine &>(TLI->getTargetMachine());
44}
45
47
49 const GCNSubtarget *STI)
50 : AMDGPUMachineFunctionInfo(F, *STI), Mode(F, *STI),
51 GWSResourcePSV(getTM(STI)), UserSGPRInfo(F, *STI), WorkGroupIDX(false),
52 WorkGroupIDY(false), WorkGroupIDZ(false), WorkGroupInfo(false),
53 LDSKernelId(false), PrivateSegmentWaveByteOffset(false),
54 WorkItemIDX(false), WorkItemIDY(false), WorkItemIDZ(false),
55 ImplicitArgPtr(false), GITPtrHigh(0xffffffff), HighBitsOf32BitAddress(0),
56 IsWholeWaveFunction(F.getCallingConv() ==
57 CallingConv::AMDGPU_Gfx_WholeWave) {
58 const GCNSubtarget &ST = *STI;
59 FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
60 WavesPerEU = ST.getWavesPerEU(F);
61 MaxNumWorkGroups = AMDGPU::getMaxNumWorkGroups(F);
62 assert(MaxNumWorkGroups.size() == 3);
63
64 DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
65 Occupancy = ST.computeOccupancy(F, getLDSSize()).second;
66 CallingConv::ID CC = F.getCallingConv();
67
68 VRegFlags.reserve(1024);
69
70 const bool IsKernel = CC == CallingConv::AMDGPU_KERNEL ||
72
73 if (IsKernel) {
74 WorkGroupIDX = true;
75 WorkItemIDX = true;
76 } else if (CC == CallingConv::AMDGPU_PS) {
77 PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
78 }
79
80 if (ST.hasGFX90AInsts()) {
81 // FIXME: Extract logic out of getMaxNumVectorRegs; we need to apply the
82 // allocation granule and clamping.
83 auto [MinNumAGPRAttr, MaxNumAGPRAttr] =
84 AMDGPU::getIntegerPairAttribute(F, "amdgpu-agpr-alloc", {~0u, ~0u},
85 /*OnlyFirstRequired=*/true);
86 MinNumAGPRs = MinNumAGPRAttr;
87 }
88
89 if (!isEntryFunction()) {
90 if (CC != CallingConv::AMDGPU_Gfx &&
93
94 FrameOffsetReg = AMDGPU::SGPR33;
95 StackPtrOffsetReg = AMDGPU::SGPR32;
96
97 if (!ST.hasFlatScratchEnabled()) {
98 // Non-entry functions have no special inputs for now, other registers
99 // required for scratch access.
100 ScratchRSrcReg = AMDGPU::isChainCC(CC)
101 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
102 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
103
104 ArgInfo.PrivateSegmentBuffer =
105 ArgDescriptor::createRegister(ScratchRSrcReg);
106 }
107
108 if (!F.hasFnAttribute("amdgpu-no-implicitarg-ptr") &&
110 ImplicitArgPtr = true;
111 } else {
112 ImplicitArgPtr = false;
114 std::max(ST.getAlignmentForImplicitArgPtr(), MaxKernArgAlign);
115 }
116
117 if (!AMDGPU::isGraphics(CC) ||
119 ST.hasArchitectedSGPRs())) {
120 if (IsKernel || !F.hasFnAttribute("amdgpu-no-workgroup-id-x") ||
121 !F.hasFnAttribute("amdgpu-no-cluster-id-x"))
122 WorkGroupIDX = true;
123
124 if (!F.hasFnAttribute("amdgpu-no-workgroup-id-y") ||
125 !F.hasFnAttribute("amdgpu-no-cluster-id-y"))
126 WorkGroupIDY = true;
127
128 if (!F.hasFnAttribute("amdgpu-no-workgroup-id-z") ||
129 !F.hasFnAttribute("amdgpu-no-cluster-id-z"))
130 WorkGroupIDZ = true;
131 }
132
133 if (!AMDGPU::isGraphics(CC)) {
134 if (IsKernel || !F.hasFnAttribute("amdgpu-no-workitem-id-x"))
135 WorkItemIDX = true;
136
137 if (!F.hasFnAttribute("amdgpu-no-workitem-id-y") &&
138 ST.getMaxWorkitemID(F, 1) != 0)
139 WorkItemIDY = true;
140
141 if (!F.hasFnAttribute("amdgpu-no-workitem-id-z") &&
142 ST.getMaxWorkitemID(F, 2) != 0)
143 WorkItemIDZ = true;
144
145 if (!IsKernel && !F.hasFnAttribute("amdgpu-no-lds-kernel-id"))
146 LDSKernelId = true;
147 }
148
149 if (isEntryFunction()) {
150 // X, XY, and XYZ are the only supported combinations, so make sure Y is
151 // enabled if Z is.
152 if (WorkItemIDZ)
153 WorkItemIDY = true;
154
155 if (!ST.hasArchitectedFlatScratch()) {
156 PrivateSegmentWaveByteOffset = true;
157
158 // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
159 if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
161 ArgInfo.PrivateSegmentWaveByteOffset =
162 ArgDescriptor::createRegister(AMDGPU::SGPR5);
163 }
164 }
165
166 Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
167 StringRef S = A.getValueAsString();
168 if (!S.empty())
169 S.consumeInteger(0, GITPtrHigh);
170
171 A = F.getFnAttribute("amdgpu-32bit-address-high-bits");
172 S = A.getValueAsString();
173 if (!S.empty())
174 S.consumeInteger(0, HighBitsOf32BitAddress);
175
176 MaxMemoryClusterDWords = F.getFnAttributeAsParsedInteger(
177 "amdgpu-max-memory-cluster-dwords", DefaultMemoryClusterDWordsLimit);
178
179 // On GFX908, in order to guarantee copying between AGPRs, we need a scratch
180 // VGPR available at all times. For now, reserve highest available VGPR. After
181 // RA, shift it to the lowest available unused VGPR if the one exist.
182 if (ST.hasMAIInsts() && !ST.hasGFX90AInsts()) {
183 VGPRForAGPRCopy =
184 AMDGPU::VGPR_32RegClass.getRegister(ST.getMaxNumVGPRs(F) - 1);
185 }
186
187 ClusterDims = AMDGPU::ClusterDimsAttr::get(F);
188}
189
196
199 const GCNSubtarget& ST = MF.getSubtarget<GCNSubtarget>();
200 limitOccupancy(ST.getOccupancyWithWorkGroupSizes(MF).second);
201}
202
204 const SIRegisterInfo &TRI) {
205 ArgInfo.PrivateSegmentBuffer =
206 ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
207 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SGPR_128RegClass));
208 NumUserSGPRs += 4;
209 return ArgInfo.PrivateSegmentBuffer.getRegister();
210}
211
213 ArgInfo.DispatchPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
214 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
215 NumUserSGPRs += 2;
216 return ArgInfo.DispatchPtr.getRegister();
217}
218
220 ArgInfo.QueuePtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
221 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
222 NumUserSGPRs += 2;
223 return ArgInfo.QueuePtr.getRegister();
224}
225
227 ArgInfo.KernargSegmentPtr
228 = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
229 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
230 NumUserSGPRs += 2;
231 return ArgInfo.KernargSegmentPtr.getRegister();
232}
233
235 ArgInfo.DispatchID = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
236 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
237 NumUserSGPRs += 2;
238 return ArgInfo.DispatchID.getRegister();
239}
240
242 ArgInfo.FlatScratchInit = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
243 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
244 NumUserSGPRs += 2;
245 return ArgInfo.FlatScratchInit.getRegister();
246}
247
249 ArgInfo.PrivateSegmentSize = ArgDescriptor::createRegister(getNextUserSGPR());
250 NumUserSGPRs += 1;
251 return ArgInfo.PrivateSegmentSize.getRegister();
252}
253
255 ArgInfo.ImplicitBufferPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
256 getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
257 NumUserSGPRs += 2;
258 return ArgInfo.ImplicitBufferPtr.getRegister();
259}
260
262 ArgInfo.LDSKernelId = ArgDescriptor::createRegister(getNextUserSGPR());
263 NumUserSGPRs += 1;
264 return ArgInfo.LDSKernelId.getRegister();
265}
266
268 const SIRegisterInfo &TRI, const TargetRegisterClass *RC,
269 unsigned AllocSizeDWord, int KernArgIdx, int PaddingSGPRs) {
270 auto [It, Inserted] = ArgInfo.PreloadKernArgs.try_emplace(KernArgIdx);
271 assert(Inserted && "Preload kernel argument allocated twice.");
272 NumUserSGPRs += PaddingSGPRs;
273 // If the available register tuples are aligned with the kernarg to be
274 // preloaded use that register, otherwise we need to use a set of SGPRs and
275 // merge them.
276 if (!ArgInfo.FirstKernArgPreloadReg)
277 ArgInfo.FirstKernArgPreloadReg = getNextUserSGPR();
278 Register PreloadReg =
279 TRI.getMatchingSuperReg(getNextUserSGPR(), AMDGPU::sub0, RC);
280 auto &Regs = It->second.Regs;
281 if (PreloadReg &&
282 (RC == &AMDGPU::SReg_32RegClass || RC == &AMDGPU::SReg_64RegClass)) {
283 Regs.push_back(PreloadReg);
284 NumUserSGPRs += AllocSizeDWord;
285 } else {
286 Regs.reserve(AllocSizeDWord);
287 for (unsigned I = 0; I < AllocSizeDWord; ++I) {
288 Regs.push_back(getNextUserSGPR());
289 NumUserSGPRs++;
290 }
291 }
292
293 // Track the actual number of SGPRs that HW will preload to.
294 UserSGPRInfo.allocKernargPreloadSGPRs(AllocSizeDWord + PaddingSGPRs);
295 return &Regs;
296}
297
299 uint64_t Size, Align Alignment) {
300 // Skip if it is an entry function or the register is already added.
301 if (isEntryFunction() || WWMSpills.count(VGPR))
302 return;
303
304 // Skip if this is a function with the amdgpu_cs_chain or
305 // amdgpu_cs_chain_preserve calling convention and this is a scratch register.
306 // We never need to allocate a spill for these because we don't even need to
307 // restore the inactive lanes for them (they're scratchier than the usual
308 // scratch registers). We only need to do this if we have calls to
309 // llvm.amdgcn.cs.chain (otherwise there's no one to save them for, since
310 // chain functions do not return) and the function did not contain a call to
311 // llvm.amdgcn.init.whole.wave (since in that case there are no inactive lanes
312 // when entering the function).
313 if (isChainFunction() &&
316 return;
317
318 WWMSpills.insert(std::make_pair(
319 VGPR, MF.getFrameInfo().CreateSpillStackObject(Size, Alignment)));
320}
321
322// Separate out the callee-saved and scratch registers.
324 MachineFunction &MF,
325 SmallVectorImpl<std::pair<Register, int>> &CalleeSavedRegs,
326 SmallVectorImpl<std::pair<Register, int>> &ScratchRegs) const {
327 const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
328 for (auto &Reg : WWMSpills) {
329 if (isCalleeSavedReg(CSRegs, Reg.first))
330 CalleeSavedRegs.push_back(Reg);
331 else
332 ScratchRegs.push_back(Reg);
333 }
334}
335
337 MCPhysReg Reg) const {
338 for (unsigned I = 0; CSRegs[I]; ++I) {
339 if (CSRegs[I] == Reg)
340 return true;
341 }
342
343 return false;
344}
345
348 BitVector &SavedVGPRs) {
349 const SIRegisterInfo *TRI = MF.getSubtarget<GCNSubtarget>().getRegisterInfo();
351 for (unsigned I = 0, E = WWMVGPRs.size(); I < E; ++I) {
352 Register Reg = WWMVGPRs[I];
353 Register NewReg =
354 TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF);
355 if (!NewReg || NewReg >= Reg)
356 break;
357
358 MRI.replaceRegWith(Reg, NewReg);
359
360 // Update various tables with the new VGPR.
361 WWMVGPRs[I] = NewReg;
362 WWMReservedRegs.remove(Reg);
363 WWMReservedRegs.insert(NewReg);
364 MRI.reserveReg(NewReg, TRI);
365
366 // Replace the register in SpillPhysVGPRs. This is needed to look for free
367 // lanes while spilling special SGPRs like FP, BP, etc. during PEI.
368 auto *RegItr = llvm::find(SpillPhysVGPRs, Reg);
369 if (RegItr != SpillPhysVGPRs.end()) {
370 unsigned Idx = std::distance(SpillPhysVGPRs.begin(), RegItr);
371 SpillPhysVGPRs[Idx] = NewReg;
372
373 // For replacing registers used in the CFI instructions.
374 MF.replaceFrameInstRegister(Reg, NewReg);
375 }
376
377 // The generic `determineCalleeSaves` might have set the old register if it
378 // is in the CSR range.
379 SavedVGPRs.reset(Reg);
380
381 for (MachineBasicBlock &MBB : MF) {
382 MBB.removeLiveIn(Reg);
383 MBB.sortUniqueLiveIns();
384 }
385
386 Reg = NewReg;
387 }
388}
389
390bool SIMachineFunctionInfo::allocateVirtualVGPRForSGPRSpills(
391 MachineFunction &MF, int FI, unsigned LaneIndex) {
393 Register LaneVGPR;
394 if (!LaneIndex) {
395 LaneVGPR = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
396 SpillVGPRs.push_back(LaneVGPR);
397 } else {
398 LaneVGPR = SpillVGPRs.back();
399 }
400
401 SGPRSpillsToVirtualVGPRLanes[FI].emplace_back(LaneVGPR, LaneIndex);
402 return true;
403}
404
405bool SIMachineFunctionInfo::allocatePhysicalVGPRForSGPRSpills(
406 MachineFunction &MF, int FI, unsigned LaneIndex, bool IsPrologEpilog) {
407 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
408 const SIRegisterInfo *TRI = ST.getRegisterInfo();
409 MachineRegisterInfo &MRI = MF.getRegInfo();
410 Register LaneVGPR;
411 if (!LaneIndex) {
412 // Find the highest available register if called before RA to ensure the
413 // lowest registers are available for allocation. The LaneVGPR, in that
414 // case, will be shifted back to the lowest range after VGPR allocation.
415 LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF,
416 !IsPrologEpilog);
417 if (LaneVGPR == AMDGPU::NoRegister) {
418 // We have no VGPRs left for spilling SGPRs. Reset because we will not
419 // partially spill the SGPR to VGPRs.
420 SGPRSpillsToPhysicalVGPRLanes.erase(FI);
421 return false;
422 }
423
424 if (IsPrologEpilog)
425 allocateWWMSpill(MF, LaneVGPR);
426
427 reserveWWMRegister(LaneVGPR);
428 for (MachineBasicBlock &MBB : MF) {
429 MBB.addLiveIn(LaneVGPR);
431 }
432 SpillPhysVGPRs.push_back(LaneVGPR);
433 } else {
434 LaneVGPR = SpillPhysVGPRs.back();
435 }
436
437 SGPRSpillsToPhysicalVGPRLanes[FI].emplace_back(LaneVGPR, LaneIndex);
438 return true;
439}
440
442 MachineFunction &MF, int FI, bool SpillToPhysVGPRLane,
443 bool IsPrologEpilog) {
444 std::vector<SIRegisterInfo::SpilledReg> &SpillLanes =
445 SpillToPhysVGPRLane ? SGPRSpillsToPhysicalVGPRLanes[FI]
446 : SGPRSpillsToVirtualVGPRLanes[FI];
447
448 // This has already been allocated.
449 if (!SpillLanes.empty())
450 return true;
451
452 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
453 MachineFrameInfo &FrameInfo = MF.getFrameInfo();
454 unsigned WaveSize = ST.getWavefrontSize();
455
456 unsigned Size = FrameInfo.getObjectSize(FI);
457 unsigned NumLanes = Size / 4;
458
459 if (NumLanes > WaveSize)
460 return false;
461
462 assert(Size >= 4 && "invalid sgpr spill size");
463 assert(ST.getRegisterInfo()->spillSGPRToVGPR() &&
464 "not spilling SGPRs to VGPRs");
465
466 unsigned &NumSpillLanes = SpillToPhysVGPRLane ? NumPhysicalVGPRSpillLanes
467 : NumVirtualVGPRSpillLanes;
468
469 for (unsigned I = 0; I < NumLanes; ++I, ++NumSpillLanes) {
470 unsigned LaneIndex = (NumSpillLanes % WaveSize);
471
472 bool Allocated = SpillToPhysVGPRLane
473 ? allocatePhysicalVGPRForSGPRSpills(MF, FI, LaneIndex,
474 IsPrologEpilog)
475 : allocateVirtualVGPRForSGPRSpills(MF, FI, LaneIndex);
476 if (!Allocated) {
477 NumSpillLanes -= I;
478 return false;
479 }
480 }
481
482 return true;
483}
484
485/// Reserve AGPRs or VGPRs to support spilling for FrameIndex \p FI.
486/// Either AGPR is spilled to VGPR to vice versa.
487/// Returns true if a \p FI can be eliminated completely.
489 int FI,
490 bool isAGPRtoVGPR) {
492 MachineFrameInfo &FrameInfo = MF.getFrameInfo();
493 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
494
495 assert(ST.hasMAIInsts() && FrameInfo.isSpillSlotObjectIndex(FI));
496
497 auto &Spill = VGPRToAGPRSpills[FI];
498
499 // This has already been allocated.
500 if (!Spill.Lanes.empty())
501 return Spill.FullyAllocated;
502
503 unsigned Size = FrameInfo.getObjectSize(FI);
504 unsigned NumLanes = Size / 4;
505 Spill.Lanes.resize(NumLanes, AMDGPU::NoRegister);
506
507 const TargetRegisterClass &RC =
508 isAGPRtoVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::AGPR_32RegClass;
509 auto Regs = RC.getRegisters();
510
511 auto &SpillRegs = isAGPRtoVGPR ? SpillAGPR : SpillVGPR;
512 const SIRegisterInfo *TRI = ST.getRegisterInfo();
513 Spill.FullyAllocated = true;
514
515 // FIXME: Move allocation logic out of MachineFunctionInfo and initialize
516 // once.
517 BitVector OtherUsedRegs;
518 OtherUsedRegs.resize(TRI->getNumRegs());
519
520 const uint32_t *CSRMask =
521 TRI->getCallPreservedMask(MF, MF.getFunction().getCallingConv());
522 if (CSRMask)
523 OtherUsedRegs.setBitsInMask(CSRMask);
524
525 // TODO: Should include register tuples, but doesn't matter with current
526 // usage.
527 for (MCPhysReg Reg : SpillAGPR)
528 OtherUsedRegs.set(Reg);
529 for (MCPhysReg Reg : SpillVGPR)
530 OtherUsedRegs.set(Reg);
531
532 SmallVectorImpl<MCPhysReg>::const_iterator NextSpillReg = Regs.begin();
533 for (int I = NumLanes - 1; I >= 0; --I) {
534 NextSpillReg = std::find_if(
535 NextSpillReg, Regs.end(), [&MRI, &OtherUsedRegs](MCPhysReg Reg) {
536 return MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg) &&
537 !OtherUsedRegs[Reg];
538 });
539
540 if (NextSpillReg == Regs.end()) { // Registers exhausted
541 Spill.FullyAllocated = false;
542 break;
543 }
544
545 OtherUsedRegs.set(*NextSpillReg);
546 SpillRegs.push_back(*NextSpillReg);
547 MRI.reserveReg(*NextSpillReg, TRI);
548 Spill.Lanes[I] = *NextSpillReg++;
549 }
550
551 return Spill.FullyAllocated;
552}
553
555 MachineFrameInfo &MFI, bool ResetSGPRSpillStackIDs) {
556 // Remove dead frame indices from function frame, however keep FP & BP since
557 // spills for them haven't been inserted yet. And also make sure to remove the
558 // frame indices from `SGPRSpillsToVirtualVGPRLanes` data structure,
559 // otherwise, it could result in an unexpected side effect and bug, in case of
560 // any re-mapping of freed frame indices by later pass(es) like "stack slot
561 // coloring".
562 for (auto &R : SGPRSpillsToVirtualVGPRLanes)
563 MFI.RemoveStackObject(R.first);
564 SGPRSpillsToVirtualVGPRLanes.clear();
565
566 // Remove the dead frame indices of CSR SGPRs which are spilled to physical
567 // VGPR lanes during SILowerSGPRSpills pass.
568 if (!ResetSGPRSpillStackIDs) {
569 for (auto &R : SGPRSpillsToPhysicalVGPRLanes)
570 MFI.RemoveStackObject(R.first);
571 SGPRSpillsToPhysicalVGPRLanes.clear();
572 }
573 bool HaveSGPRToMemory = false;
574
575 if (ResetSGPRSpillStackIDs) {
576 // All other SGPRs must be allocated on the default stack, so reset the
577 // stack ID.
578 for (int I = MFI.getObjectIndexBegin(), E = MFI.getObjectIndexEnd(); I != E;
579 ++I) {
583 HaveSGPRToMemory = true;
584 }
585 }
586 }
587 }
588
589 for (auto &R : VGPRToAGPRSpills) {
590 if (R.second.IsDead)
591 MFI.RemoveStackObject(R.first);
592 }
593
594 return HaveSGPRToMemory;
595}
596
598 const SIRegisterInfo &TRI) {
599 if (ScavengeFI)
600 return *ScavengeFI;
601
602 ScavengeFI =
603 MFI.CreateStackObject(TRI.getSpillSize(AMDGPU::SGPR_32RegClass),
604 TRI.getSpillAlign(AMDGPU::SGPR_32RegClass), false);
605 return *ScavengeFI;
606}
607
608MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
609 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
610 return AMDGPU::SGPR0 + NumUserSGPRs;
611}
612
613MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
614 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
615}
616
617void SIMachineFunctionInfo::MRI_NoteNewVirtualRegister(Register Reg) {
618 VRegFlags.grow(Reg);
619}
620
621void SIMachineFunctionInfo::MRI_NoteCloneVirtualRegister(Register NewReg,
622 Register SrcReg) {
623 VRegFlags.grow(NewReg);
624 VRegFlags[NewReg] = VRegFlags[SrcReg];
625}
626
629 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
630 if (!ST.isAmdPalOS())
631 return Register();
632 Register GitPtrLo = AMDGPU::SGPR0; // Low GIT address passed in
633 if (ST.hasMergedShaders()) {
634 switch (MF.getFunction().getCallingConv()) {
637 // Low GIT address is passed in s8 rather than s0 for an LS+HS or
638 // ES+GS merged shader on gfx9+.
639 GitPtrLo = AMDGPU::SGPR8;
640 return GitPtrLo;
641 default:
642 return GitPtrLo;
643 }
644 }
645 return GitPtrLo;
646}
647
649 const TargetRegisterInfo &TRI) {
651 {
652 raw_string_ostream OS(Dest.Value);
653 OS << printReg(Reg, &TRI);
654 }
655 return Dest;
656}
657
658static std::optional<yaml::SIArgumentInfo>
660 const TargetRegisterInfo &TRI) {
662
663 auto convertArg = [&](std::optional<yaml::SIArgument> &A,
664 const ArgDescriptor &Arg) {
665 if (!Arg)
666 return false;
667
668 // Create a register or stack argument.
670 if (Arg.isRegister()) {
672 OS << printReg(Arg.getRegister(), &TRI);
673 } else
674 SA.StackOffset = Arg.getStackOffset();
675 // Check and update the optional mask.
676 if (Arg.isMasked())
677 SA.Mask = Arg.getMask();
678
679 A = std::move(SA);
680 return true;
681 };
682
683 bool Any = false;
684 Any |= convertArg(AI.PrivateSegmentBuffer, ArgInfo.PrivateSegmentBuffer);
685 Any |= convertArg(AI.DispatchPtr, ArgInfo.DispatchPtr);
686 Any |= convertArg(AI.QueuePtr, ArgInfo.QueuePtr);
687 Any |= convertArg(AI.KernargSegmentPtr, ArgInfo.KernargSegmentPtr);
688 Any |= convertArg(AI.DispatchID, ArgInfo.DispatchID);
689 Any |= convertArg(AI.FlatScratchInit, ArgInfo.FlatScratchInit);
690 Any |= convertArg(AI.LDSKernelId, ArgInfo.LDSKernelId);
691 Any |= convertArg(AI.PrivateSegmentSize, ArgInfo.PrivateSegmentSize);
692 Any |= convertArg(AI.WorkGroupIDX, ArgInfo.WorkGroupIDX);
693 Any |= convertArg(AI.WorkGroupIDY, ArgInfo.WorkGroupIDY);
694 Any |= convertArg(AI.WorkGroupIDZ, ArgInfo.WorkGroupIDZ);
695 Any |= convertArg(AI.WorkGroupInfo, ArgInfo.WorkGroupInfo);
696 Any |= convertArg(AI.PrivateSegmentWaveByteOffset,
697 ArgInfo.PrivateSegmentWaveByteOffset);
698 Any |= convertArg(AI.ImplicitArgPtr, ArgInfo.ImplicitArgPtr);
699 Any |= convertArg(AI.ImplicitBufferPtr, ArgInfo.ImplicitBufferPtr);
700 Any |= convertArg(AI.WorkItemIDX, ArgInfo.WorkItemIDX);
701 Any |= convertArg(AI.WorkItemIDY, ArgInfo.WorkItemIDY);
702 Any |= convertArg(AI.WorkItemIDZ, ArgInfo.WorkItemIDZ);
703
704 // Write FirstKernArgPreloadReg separately, since it's a Register,
705 // not ArgDescriptor.
706 if (ArgInfo.FirstKernArgPreloadReg) {
707 Register Reg = ArgInfo.FirstKernArgPreloadReg;
708 assert(Reg.isPhysical() &&
709 "FirstKernArgPreloadReg must be a physical register");
710
713 OS << printReg(Reg, &TRI);
714
716 Any = true;
717 }
718
719 if (Any)
720 return AI;
721
722 return std::nullopt;
723}
724
727 const llvm::MachineFunction &MF)
728 : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
729 MaxKernArgAlign(MFI.getMaxKernArgAlign()), LDSSize(MFI.getLDSSize()),
730 GDSSize(MFI.getGDSSize()), DynLDSAlign(MFI.getDynLDSAlign()),
731 IsEntryFunction(MFI.isEntryFunction()), MemoryBound(MFI.isMemoryBound()),
732 WaveLimiter(MFI.needsWaveLimiter()),
733 HasSpilledSGPRs(MFI.hasSpilledSGPRs()),
734 HasSpilledVGPRs(MFI.hasSpilledVGPRs()),
735 HasNoWWMPoolSGPRSpillFallback(MFI.hasNoWWMPoolSGPRSpillFallback()),
736 NumWaveDispatchSGPRs(MFI.getNumWaveDispatchSGPRs()),
737 NumWaveDispatchVGPRs(MFI.getNumWaveDispatchVGPRs()),
738 HighBitsOf32BitAddress(MFI.get32BitAddressHighBits()),
739 Occupancy(MFI.getOccupancy()),
740 ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
741 FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
742 StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)),
743 BytesInStackArgArea(MFI.getBytesInStackArgArea()),
744 ReturnsVoid(MFI.returnsVoid()),
745 ArgInfo(convertArgumentInfo(MFI.getArgInfo(), TRI)),
746 PSInputAddr(MFI.getPSInputAddr()), PSInputEnable(MFI.getPSInputEnable()),
747 MaxMemoryClusterDWords(MFI.getMaxMemoryClusterDWords()),
748 Mode(MFI.getMode()), HasInitWholeWave(MFI.hasInitWholeWave()),
749 IsWholeWaveFunction(MFI.isWholeWaveFunction()),
750 DynamicVGPRBlockSize(MFI.getDynamicVGPRBlockSize()),
751 ScratchReservedForDynamicVGPRs(MFI.getScratchReservedForDynamicVGPRs()),
752 NumKernargPreloadSGPRs(MFI.getNumKernargPreloadedSGPRs()),
753 MinNumAGPRs(MFI.getMinNumAGPRs()) {
754 for (Register Reg : MFI.getSGPRSpillPhysVGPRs())
755 SpillPhysVGPRS.push_back(regToString(Reg, TRI));
756
757 for (Register Reg : MFI.getWWMReservedRegs())
758 WWMReservedRegs.push_back(regToString(Reg, TRI));
759
760 if (MFI.getLongBranchReservedReg())
762 if (MFI.getVGPRForAGPRCopy())
764
765 if (MFI.getSGPRForEXECCopy())
767
768 auto SFI = MFI.getOptionalScavengeFI();
769 if (SFI)
771}
772
776
778 const yaml::SIMachineFunctionInfo &YamlMFI, const MachineFunction &MF,
782 LDSSize = YamlMFI.LDSSize;
783 GDSSize = YamlMFI.GDSSize;
784 DynLDSAlign = YamlMFI.DynLDSAlign;
785 PSInputAddr = YamlMFI.PSInputAddr;
786 PSInputEnable = YamlMFI.PSInputEnable;
787 MaxMemoryClusterDWords = YamlMFI.MaxMemoryClusterDWords;
788 HighBitsOf32BitAddress = YamlMFI.HighBitsOf32BitAddress;
789 Occupancy = YamlMFI.Occupancy;
791 MemoryBound = YamlMFI.MemoryBound;
792 WaveLimiter = YamlMFI.WaveLimiter;
793 HasSpilledSGPRs = YamlMFI.HasSpilledSGPRs;
794 HasSpilledVGPRs = YamlMFI.HasSpilledVGPRs;
795 HasNoWWMPoolSGPRSpillFallback = YamlMFI.HasNoWWMPoolSGPRSpillFallback;
796 NumWaveDispatchSGPRs = YamlMFI.NumWaveDispatchSGPRs;
797 NumWaveDispatchVGPRs = YamlMFI.NumWaveDispatchVGPRs;
798 BytesInStackArgArea = YamlMFI.BytesInStackArgArea;
799 ReturnsVoid = YamlMFI.ReturnsVoid;
800 IsWholeWaveFunction = YamlMFI.IsWholeWaveFunction;
801 MinNumAGPRs = YamlMFI.MinNumAGPRs;
802 // This can also be set by the function attribute, MFI has higher precedence
803 // though.
804 if (YamlMFI.DynamicVGPRBlockSize != std::nullopt)
805 DynamicVGPRBlockSize = *YamlMFI.DynamicVGPRBlockSize;
806
807 UserSGPRInfo.allocKernargPreloadSGPRs(YamlMFI.NumKernargPreloadSGPRs);
808
809 if (YamlMFI.ScavengeFI) {
810 auto FIOrErr = YamlMFI.ScavengeFI->getFI(MF.getFrameInfo());
811 if (!FIOrErr) {
812 // Create a diagnostic for a the frame index.
813 const MemoryBuffer &Buffer =
814 *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
815
816 Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1, 1,
817 SourceMgr::DK_Error, toString(FIOrErr.takeError()),
818 "", {}, {});
819 SourceRange = YamlMFI.ScavengeFI->SourceRange;
820 return true;
821 }
822 ScavengeFI = *FIOrErr;
823 } else {
824 ScavengeFI = std::nullopt;
825 }
826 return false;
827}
828
830 auto [MinNumAGPR, MaxNumAGPR] =
831 AMDGPU::getIntegerPairAttribute(F, "amdgpu-agpr-alloc", {~0u, ~0u},
832 /*OnlyFirstRequired=*/true);
833 return MinNumAGPR != 0u;
834}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Base class for AMDGPU specific classes of TargetSubtarget.
MachineBasicBlock & MBB
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
AMD GCN specific subclass of TargetSubtarget.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
const GCNTargetMachine & getTM(const GCNSubtarget *STI)
static cl::opt< bool, true > MFMAVGPRFormOpt("amdgpu-mfma-vgpr-form", cl::desc("Whether to force use VGPR for Opc and Dest of MFMA. If " "unspecified, default to compiler heuristics"), cl::location(SIMachineFunctionInfo::MFMAVGPRForm), cl::init(true), cl::Hidden)
static std::optional< yaml::SIArgumentInfo > convertArgumentInfo(const AMDGPUFunctionArgInfo &ArgInfo, const TargetRegisterInfo &TRI)
static yaml::StringValue regToString(Register Reg, const TargetRegisterInfo &TRI)
Interface definition for SIRegisterInfo.
Align DynLDSAlign
Align for dynamic shared memory if any.
AMDGPUMachineFunctionInfo(const Function &F, const AMDGPUSubtarget &ST)
uint32_t LDSSize
Number of bytes in the LDS that are being used.
static ClusterDimsAttr get(const Function &F)
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
BitVector & reset()
Reset all bits in the bitvector.
Definition BitVector.h:409
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
Definition BitVector.h:355
BitVector & set()
Set all bits in the bitvector.
Definition BitVector.h:366
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords=~0u)
Add '1' bits from Mask to this vector.
Definition BitVector.h:742
void push_back(bool Val)
Definition BitVector.h:505
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
const SITargetLowering * getTargetLowering() const override
ArrayRef< MCPhysReg > getRegisters() const
LLVM_ABI void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setStackID(int ObjectIdx, uint8_t ID)
bool hasTailCall() const
Returns true if the function contains a tail call.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
void RemoveStackObject(int ObjectIdx)
Remove or mark dead a statically sized stack object.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
uint8_t getStackID(int ObjectIdx) const
int getObjectIndexBegin() const
Return the minimum frame object index.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void replaceFrameInstRegister(MCRegister From, MCRegister To)
Replace all references to register.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * cloneInfo(const Ty &Old)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
void reserveReg(MCRegister PhysReg, const TargetRegisterInfo *TRI)
reserveReg – Mark a register as reserved so checks like isAllocatable will not suggest using it.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI, const MachineFunction &MF, PerFunctionMIParsingState &PFS, SMDiagnostic &Error, SMRange &SourceRange)
void shiftWwmVGPRsToLowestRange(MachineFunction &MF, SmallVectorImpl< Register > &WWMVGPRs, BitVector &SavedVGPRs)
Register addPrivateSegmentSize(const SIRegisterInfo &TRI)
void allocateWWMSpill(MachineFunction &MF, Register VGPR, uint64_t Size=4, Align Alignment=Align(4))
Register addDispatchPtr(const SIRegisterInfo &TRI)
Register addFlatScratchInit(const SIRegisterInfo &TRI)
ArrayRef< Register > getSGPRSpillPhysVGPRs() const
int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI)
Register addQueuePtr(const SIRegisterInfo &TRI)
SIMachineFunctionInfo(const SIMachineFunctionInfo &MFI)=default
Register getGITPtrLoReg(const MachineFunction &MF) const
bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR)
Reserve AGPRs or VGPRs to support spilling for FrameIndex FI.
void splitWWMSpillRegisters(MachineFunction &MF, SmallVectorImpl< std::pair< Register, int > > &CalleeSavedRegs, SmallVectorImpl< std::pair< Register, int > > &ScratchRegs) const
bool mayUseAGPRs(const Function &F) const
bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg) const
bool allocateSGPRSpillToVGPRLane(MachineFunction &MF, int FI, bool SpillToPhysVGPRLane=false, bool IsPrologEpilog=false)
Register addKernargSegmentPtr(const SIRegisterInfo &TRI)
Register addDispatchID(const SIRegisterInfo &TRI)
bool removeDeadFrameIndices(MachineFrameInfo &MFI, bool ResetSGPRSpillStackIDs)
If ResetSGPRSpillStackIDs is true, reset the stack ID from sgpr-spill to the default stack.
MachineFunctionInfo * clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, const DenseMap< MachineBasicBlock *, MachineBasicBlock * > &Src2DstMBB) const override
Make a functionally equivalent copy of this MachineFunctionInfo in MF.
bool checkIndexInPrologEpilogSGPRSpills(int FI) const
Register addPrivateSegmentBuffer(const SIRegisterInfo &TRI)
const ReservedRegSet & getWWMReservedRegs() const
std::optional< int > getOptionalScavengeFI() const
Register addImplicitBufferPtr(const SIRegisterInfo &TRI)
void limitOccupancy(const MachineFunction &MF)
SmallVectorImpl< MCRegister > * addPreloadedKernArg(const SIRegisterInfo &TRI, const TargetRegisterClass *RC, unsigned AllocSizeDWord, int KernArgIdx, int PaddingSGPRs)
static bool isChainScratchRegister(Register VGPR)
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition SourceMgr.h:308
Represents a location in source code.
Definition SMLoc.h:22
Represents a range in source code.
Definition SMLoc.h:47
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
typename SuperClass::const_iterator const_iterator
unsigned getMainFileID() const
Definition SourceMgr.h:151
const MemoryBuffer * getMemoryBuffer(unsigned i) const
Definition SourceMgr.h:144
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:519
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
const TargetMachine & getTargetMachine() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A raw_ostream that writes to an std::string.
unsigned getInitialPSInputAddr(const Function &F)
unsigned getDynamicVGPRBlockSize(const Function &F)
SmallVector< unsigned > getMaxNumWorkGroups(const Function &F)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
CallingConv Namespace - This namespace contains an enum with a value for the well-known calling conve...
Definition CallingConv.h:21
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SPIR_KERNEL
Used for SPIR kernel functions.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1765
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:42
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
MachineFunctionInfo - This class can be derived from and used by targets to hold private target-speci...
A serializaable representation of a reference to a stack object or fixed stack object.
This class should be specialized by any type that needs to be converted to/from a YAML mapping.
Definition YAMLTraits.h:63
std::optional< SIArgument > PrivateSegmentWaveByteOffset
std::optional< SIArgument > WorkGroupIDY
std::optional< SIArgument > FlatScratchInit
std::optional< SIArgument > DispatchPtr
std::optional< SIArgument > DispatchID
std::optional< SIArgument > WorkItemIDY
std::optional< SIArgument > WorkGroupIDX
std::optional< SIArgument > ImplicitArgPtr
std::optional< SIArgument > QueuePtr
std::optional< SIArgument > WorkGroupInfo
std::optional< SIArgument > LDSKernelId
std::optional< SIArgument > ImplicitBufferPtr
std::optional< SIArgument > WorkItemIDX
std::optional< SIArgument > KernargSegmentPtr
std::optional< SIArgument > WorkItemIDZ
std::optional< SIArgument > PrivateSegmentSize
std::optional< SIArgument > PrivateSegmentBuffer
std::optional< SIArgument > FirstKernArgPreloadReg
std::optional< SIArgument > WorkGroupIDZ
std::optional< unsigned > Mask
static SIArgument createArgument(bool IsReg)
SmallVector< StringValue > WWMReservedRegs
void mappingImpl(yaml::IO &YamlIO) override
std::optional< SIArgumentInfo > ArgInfo
std::optional< unsigned > DynamicVGPRBlockSize
SmallVector< StringValue, 2 > SpillPhysVGPRS
std::optional< FrameIndex > ScavengeFI
A wrapper around std::string which contains a source range that's being set during parsing.