Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions llvm/include/llvm/CodeGen/LiveRegMatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ class LiveRegMatrix {
}

Register getOneVReg(unsigned PhysReg) const;

/// Verify that all LiveInterval pointers in the matrix are valid.
/// This checks that each LiveInterval referenced in LiveIntervalUnion
/// actually exists in LiveIntervals and is not a dangling pointer.
/// Returns true if the matrix is valid, false if dangling pointers are found.
/// This is primarily useful for debugging heap-use-after-free issues.
/// This method uses a lazy approach - it builds a set of valid LiveInterval
/// pointers on-demand and has zero runtime/memory overhead during normal
/// register allocation.
bool isValid() const;
};

class LiveRegMatrixWrapperLegacy : public MachineFunctionPass {
Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/CodeGen/LiveRegMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@

#include "llvm/CodeGen/LiveRegMatrix.h"
#include "RegisterCoalescer.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
Expand Down Expand Up @@ -290,6 +292,33 @@ Register LiveRegMatrix::getOneVReg(unsigned PhysReg) const {
return MCRegister::NoRegister;
}

bool LiveRegMatrix::isValid() const {
// Build set of all valid LiveInterval pointers from LiveIntervals.
DenseSet<LiveInterval *> ValidIntervals;
for (unsigned RegIdx = 0, NumRegs = VRM->getRegInfo().getNumVirtRegs();
RegIdx < NumRegs; ++RegIdx) {
Register VReg = Register::index2VirtReg(RegIdx);
// Only track assigned registers since unassigned ones won't be in Matrix
if (VRM->hasPhys(VReg) && LIS->hasInterval(VReg))
ValidIntervals.insert(&LIS->getInterval(VReg));
}

// Now scan all LiveIntervalUnions in the matrix and verify each pointer
unsigned NumDanglingPointers = 0;
for (unsigned I = 0, Size = Matrix.size(); I != Size; ++I) {
MCRegUnit Unit = static_cast<MCRegUnit>(I);
for (const LiveInterval *LI : Matrix[Unit]) {
if (!ValidIntervals.contains(LI)) {
++NumDanglingPointers;
dbgs() << "ERROR: LiveInterval pointer is not found in LiveIntervals:\n"
<< " Register Unit: " << printRegUnit(Unit, TRI) << '\n'
<< " LiveInterval pointer: " << LI << '\n';
}
}
}
return NumDanglingPointers == 0;
}

AnalysisKey LiveRegMatrixAnalysis::Key;

LiveRegMatrix LiveRegMatrixAnalysis::run(MachineFunction &MF,
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/CodeGen/RegAllocBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ void RegAllocBase::allocatePhysRegs() {

void RegAllocBase::postOptimization() {
spiller().postOptimization();

// Verify LiveRegMatrix after spilling (no dangling pointers).
assert(Matrix->isValid() && "LiveRegMatrix validation failed");

for (auto *DeadInst : DeadRemats) {
LIS->RemoveMachineInstrFromMaps(*DeadInst);
DeadInst->eraseFromParent();
Expand Down
Loading