LLVM 20.0.0git
AMDGPUMarkLastScratchLoad.cpp
Go to the documentation of this file.
1//===-- AMDGPUMarkLastScratchLoad.cpp -------------------------------------===//
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// Mark scratch load/spill instructions which are guaranteed to be the last time
10// this scratch slot is used so it can be evicted from caches.
11//
12// TODO: Handle general stack accesses not just spilling.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AMDGPU.h"
17#include "GCNSubtarget.h"
21
22using namespace llvm;
23
24#define DEBUG_TYPE "amdgpu-mark-last-scratch-load"
25
26namespace {
27
28class AMDGPUMarkLastScratchLoad : public MachineFunctionPass {
29private:
30 LiveStacks *LS = nullptr;
31 LiveIntervals *LIS = nullptr;
32 SlotIndexes *SI = nullptr;
33 const SIInstrInfo *SII = nullptr;
34
35public:
36 static char ID;
37
38 AMDGPUMarkLastScratchLoad() : MachineFunctionPass(ID) {
40 }
41
42 bool runOnMachineFunction(MachineFunction &MF) override;
43
44 void getAnalysisUsage(AnalysisUsage &AU) const override {
48 AU.setPreservesAll();
50 }
51
52 StringRef getPassName() const override {
53 return "AMDGPU Mark Last Scratch Load";
54 }
55};
56
57} // end anonymous namespace
58
59bool AMDGPUMarkLastScratchLoad::runOnMachineFunction(MachineFunction &MF) {
60 if (skipFunction(MF.getFunction()))
61 return false;
62
64 if (ST.getGeneration() < AMDGPUSubtarget::GFX12)
65 return false;
66
67 LS = &getAnalysis<LiveStacksWrapperLegacy>().getLS();
68 LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
69 SI = &getAnalysis<SlotIndexesWrapperPass>().getSI();
70 SII = ST.getInstrInfo();
71 SlotIndexes &Slots = *LIS->getSlotIndexes();
72
73 const unsigned NumSlots = LS->getNumIntervals();
74 if (NumSlots == 0) {
75 LLVM_DEBUG(dbgs() << "No live slots, skipping\n");
76 return false;
77 }
78
79 LLVM_DEBUG(dbgs() << LS->getNumIntervals() << " intervals\n");
80
81 bool Changed = false;
82
83 for (auto &[SS, LI] : *LS) {
84 for (const LiveRange::Segment &Segment : LI.segments) {
85
86 // Ignore segments that run to the end of basic block because in this case
87 // slot is still live at the end of it.
88 if (Segment.end.isBlock())
89 continue;
90
91 const int FrameIndex = Register::stackSlot2Index(LI.reg());
92 MachineInstr *LastLoad = nullptr;
93
94 MachineInstr *MISegmentEnd = SI->getInstructionFromIndex(Segment.end);
95
96 // If there is no instruction at this slot because it was deleted take the
97 // instruction from the next slot.
98 if (!MISegmentEnd) {
99 SlotIndex NextSlot = Slots.getNextNonNullIndex(Segment.end);
100 MISegmentEnd = SI->getInstructionFromIndex(NextSlot);
101 }
102
103 MachineInstr *MISegmentStart = SI->getInstructionFromIndex(Segment.start);
104 MachineBasicBlock *BB = MISegmentEnd->getParent();
105
106 // Start iteration backwards from segment end until the start of basic
107 // block or start of segment if it is in the same basic block.
108 auto End = BB->rend();
109 if (MISegmentStart && MISegmentStart->getParent() == BB)
110 End = MISegmentStart->getReverseIterator();
111
112 for (auto MI = MISegmentEnd->getReverseIterator(); MI != End; ++MI) {
113 int LoadFI = 0;
114
115 if (SII->isLoadFromStackSlot(*MI, LoadFI) && LoadFI == FrameIndex) {
116 LastLoad = &*MI;
117 break;
118 }
119 }
120
121 if (LastLoad && !LastLoad->memoperands_empty()) {
122 MachineMemOperand *MMO = *LastLoad->memoperands_begin();
123 MMO->setFlags(MOLastUse);
124 Changed = true;
125 LLVM_DEBUG(dbgs() << " Found last load: " << *LastLoad);
126 }
127 }
128 }
129
130 return Changed;
131}
132
133char AMDGPUMarkLastScratchLoad::ID = 0;
134
135char &llvm::AMDGPUMarkLastScratchLoadID = AMDGPUMarkLastScratchLoad::ID;
136
137INITIALIZE_PASS_BEGIN(AMDGPUMarkLastScratchLoad, DEBUG_TYPE,
138 "AMDGPU Mark last scratch load", false, false)
141INITIALIZE_PASS_END(AMDGPUMarkLastScratchLoad, DEBUG_TYPE,
142 "AMDGPU Mark last scratch load", false, false)
AMDGPU Mark last scratch load
#define DEBUG_TYPE
#define LLVM_DEBUG(...)
Definition: Debug.h:106
bool End
Definition: ELF_riscv.cpp:480
AMD GCN specific subclass of TargetSubtarget.
IRTranslator LLVM IR MI
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
reverse_iterator rend()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:347
bool memoperands_empty() const
Return true if we don't have any memory operands which described the memory access done by this instr...
Definition: MachineInstr.h:818
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:806
A description of a memory reference used in the backend.
void setFlags(Flags f)
Bitwise OR the current flags with the given flags.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
static int stackSlot2Index(Register Reg)
Compute the frame index from a register value representing a stack slot.
Definition: Register.h:52
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:65
bool isBlock() const
isBlock - Returns true if this is a block boundary slot.
Definition: SlotIndexes.h:209
SlotIndexes pass.
Definition: SlotIndexes.h:297
SlotIndex getNextNonNullIndex(SlotIndex Index)
Returns the next non-null index, if one exists.
Definition: SlotIndexes.h:403
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
reverse_self_iterator getReverseIterator()
Definition: ilist_node.h:135
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ FrameIndex
Definition: ISDOpcodes.h:80
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void initializeAMDGPUMarkLastScratchLoadPass(PassRegistry &)
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition: SIInstrInfo.h:47
char & AMDGPUMarkLastScratchLoadID
This represents a simple continuous liveness interval for a value.
Definition: LiveInterval.h:162