Skip to content

Commit 084cd0f

Browse files
pxl-thjmmartinez
andauthored
[AMDGPU][Backend] Fix user-after-free in AMDGPUReleaseVGPRs::isLastVGPRUseVMEMStore (llvm#21)
Reviewed By: jpages, arsenm Differential Revision: https://reviews.llvm.org/D134641 (cherry picked from commit bb24b2c) Co-authored-by: Juan Manuel MARTINEZ CAAMAÑO <[email protected]>
1 parent e010657 commit 084cd0f

File tree

1 file changed

+60
-46
lines changed

1 file changed

+60
-46
lines changed

llvm/lib/Target/AMDGPU/AMDGPUReleaseVGPRs.cpp

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "GCNSubtarget.h"
1717
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
1818
#include "SIDefines.h"
19-
#include "llvm/ADT/STLExtras.h"
19+
#include "llvm/ADT/DepthFirstIterator.h"
2020
#include "llvm/CodeGen/MachineBasicBlock.h"
2121
#include "llvm/CodeGen/MachineOperand.h"
2222
using namespace llvm;
@@ -29,60 +29,76 @@ class AMDGPUReleaseVGPRs : public MachineFunctionPass {
2929
public:
3030
static char ID;
3131

32-
const SIInstrInfo *SII;
33-
const SIRegisterInfo *TRI;
34-
3532
AMDGPUReleaseVGPRs() : MachineFunctionPass(ID) {}
3633

3734
void getAnalysisUsage(AnalysisUsage &AU) const override {
3835
AU.setPreservesAll();
3936
MachineFunctionPass::getAnalysisUsage(AU);
4037
}
4138

42-
// Used to cache the result of isLastInstructionVMEMStore for each block
43-
using BlockVMEMStoreType = DenseMap<MachineBasicBlock *, bool>;
44-
BlockVMEMStoreType BlockVMEMStore;
45-
46-
// Return true if the last instruction referencing a vgpr in this MBB
47-
// is a VMEM store, otherwise return false.
48-
// Visit previous basic blocks to find this last instruction if needed.
49-
// Because this pass is late in the pipeline, it is expected that the
39+
// Track if the last instruction referencing a vgpr in a MBB is a VMEM
40+
// store. Because this pass is late in the pipeline, it is expected that the
5041
// last vgpr use will likely be one of vmem store, ds, exp.
5142
// Loads and others vgpr operations would have been
5243
// deleted by this point, except for complex control flow involving loops.
5344
// This is why we are just testing the type of instructions rather
5445
// than the operands.
55-
bool isLastVGPRUseVMEMStore(MachineBasicBlock &MBB) {
56-
// Use the cache to break infinite loop and save some time. Initialize to
57-
// false in case we have a cycle.
58-
BlockVMEMStoreType::iterator It;
59-
bool Inserted;
60-
std::tie(It, Inserted) = BlockVMEMStore.insert({&MBB, false});
61-
bool &CacheEntry = It->second;
62-
if (!Inserted)
63-
return CacheEntry;
64-
65-
for (auto &MI : reverse(MBB.instrs())) {
66-
// If it's a VMEM store, a vgpr will be used, return true.
67-
if ((SIInstrInfo::isVMEM(MI) || SIInstrInfo::isFLAT(MI)) && MI.mayStore())
68-
return CacheEntry = true;
69-
70-
// If it's referencing a VGPR but is not a VMEM store, return false.
71-
if (SIInstrInfo::isDS(MI) || SIInstrInfo::isEXP(MI) ||
72-
SIInstrInfo::isVMEM(MI) || SIInstrInfo::isFLAT(MI) ||
73-
SIInstrInfo::isVALU(MI))
74-
return CacheEntry = false;
46+
class LastVGPRUseIsVMEMStore {
47+
BitVector BlockVMEMStore;
48+
49+
static Optional<bool> lastVGPRUseIsStore(const MachineBasicBlock &MBB) {
50+
for (auto &MI : reverse(MBB.instrs())) {
51+
// If it's a VMEM store, a VGPR will be used, return true.
52+
if ((SIInstrInfo::isVMEM(MI) || SIInstrInfo::isFLAT(MI)) &&
53+
MI.mayStore())
54+
return true;
55+
56+
// If it's referencing a VGPR but is not a VMEM store, return false.
57+
if (SIInstrInfo::isDS(MI) || SIInstrInfo::isEXP(MI) ||
58+
SIInstrInfo::isVMEM(MI) || SIInstrInfo::isFLAT(MI) ||
59+
SIInstrInfo::isVALU(MI))
60+
return false;
61+
}
62+
// Wait until the values are propagated from the predecessors
63+
return None;
7564
}
7665

77-
// Recursive call into parent blocks. Look into predecessors if there is no
78-
// vgpr used in this block.
79-
return CacheEntry = llvm::any_of(MBB.predecessors(),
80-
[this](MachineBasicBlock *Parent) {
81-
return isLastVGPRUseVMEMStore(*Parent);
82-
});
83-
}
66+
public:
67+
LastVGPRUseIsVMEMStore(const MachineFunction &MF)
68+
: BlockVMEMStore(MF.getNumBlockIDs()) {
69+
70+
df_iterator_default_set<const MachineBasicBlock *> Visited;
71+
SmallVector<const MachineBasicBlock *> EndWithVMEMStoreBlocks;
72+
73+
for (const auto &MBB : MF) {
74+
auto LastUseIsStore = lastVGPRUseIsStore(MBB);
75+
if (!LastUseIsStore.has_value())
76+
continue;
77+
78+
if (*LastUseIsStore) {
79+
EndWithVMEMStoreBlocks.push_back(&MBB);
80+
} else {
81+
Visited.insert(&MBB);
82+
}
83+
}
84+
85+
for (const auto *MBB : EndWithVMEMStoreBlocks) {
86+
for (const auto *Succ : depth_first_ext(MBB, Visited)) {
87+
BlockVMEMStore[Succ->getNumber()] = true;
88+
}
89+
}
90+
}
91+
92+
// Return true if the last instruction referencing a vgpr in this MBB
93+
// is a VMEM store, otherwise return false.
94+
bool isLastVGPRUseVMEMStore(const MachineBasicBlock &MBB) const {
95+
return BlockVMEMStore[MBB.getNumber()];
96+
}
97+
};
8498

85-
bool runOnMachineBasicBlock(MachineBasicBlock &MBB) {
99+
static bool
100+
runOnMachineBasicBlock(MachineBasicBlock &MBB, const SIInstrInfo *SII,
101+
const LastVGPRUseIsVMEMStore &BlockVMEMStore) {
86102

87103
bool Changed = false;
88104

@@ -93,7 +109,7 @@ class AMDGPUReleaseVGPRs : public MachineFunctionPass {
93109
// If the last instruction using a VGPR in the block is a VMEM store,
94110
// release VGPRs. The VGPRs release will be placed just before ending
95111
// the program
96-
if (isLastVGPRUseVMEMStore(MBB)) {
112+
if (BlockVMEMStore.isLastVGPRUseVMEMStore(MBB)) {
97113
BuildMI(MBB, MI, DebugLoc(), SII->get(AMDGPU::S_SENDMSG))
98114
.addImm(AMDGPU::SendMsg::ID_DEALLOC_VGPRS_GFX11Plus);
99115
Changed = true;
@@ -117,16 +133,14 @@ class AMDGPUReleaseVGPRs : public MachineFunctionPass {
117133
LLVM_DEBUG(dbgs() << "AMDGPUReleaseVGPRs running on " << MF.getName()
118134
<< "\n");
119135

120-
SII = ST.getInstrInfo();
121-
TRI = ST.getRegisterInfo();
136+
const SIInstrInfo *SII = ST.getInstrInfo();
137+
LastVGPRUseIsVMEMStore BlockVMEMStore(MF);
122138

123139
bool Changed = false;
124140
for (auto &MBB : MF) {
125-
Changed |= runOnMachineBasicBlock(MBB);
141+
Changed |= runOnMachineBasicBlock(MBB, SII, BlockVMEMStore);
126142
}
127143

128-
BlockVMEMStore.clear();
129-
130144
return Changed;
131145
}
132146
};

0 commit comments

Comments
 (0)