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
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/LiveIntervalUnion.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class LiveIntervalUnion {
// Remove a live virtual register's segments from this union.
void extract(const LiveInterval &VirtReg, const LiveRange &Range);

// Remove all segments referencing VirtReg. This may be used if the register
// isn't used anymore.
void clearAllSegmentsReferencing(const LiveInterval &VirtReg);

// Remove all inserted virtual registers.
void clear() { Segments.clear(); ++Tag; }

Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/CodeGen/LiveRegMatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class LiveRegMatrix {
/// the assignment and updates VirtRegMap accordingly.
void unassign(const LiveInterval &VirtReg);

/// Unassign a virtual register by register number.
/// Unlike unassign(LiveInterval&), this safely handles cases where
/// the LiveInterval may be in an inconsistent state or about to be deleted.
void unassign(Register VirtReg);

/// Returns true if the given \p PhysReg has any live intervals assigned.
bool isPhysRegUsed(MCRegister PhysReg) const;

Expand Down Expand Up @@ -170,6 +175,10 @@ class LiveRegMatrix {
}

Register getOneVReg(unsigned PhysReg) const;

/// This checks that each LiveInterval referenced in LiveIntervalUnion
/// actually exists in LiveIntervals and is not a dangling pointer.
bool isValid() const;
};

class LiveRegMatrixWrapperLegacy : public MachineFunctionPass {
Expand Down
18 changes: 15 additions & 3 deletions llvm/lib/CodeGen/InlineSpiller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class HoistSpillHelper : private LiveRangeEdit::Delegate {
const TargetInstrInfo &TII;
const TargetRegisterInfo &TRI;
const MachineBlockFrequencyInfo &MBFI;
LiveRegMatrix &Matrix;

InsertPointAnalysis IPA;

Expand Down Expand Up @@ -129,16 +130,17 @@ class HoistSpillHelper : private LiveRangeEdit::Delegate {

public:
HoistSpillHelper(const Spiller::RequiredAnalyses &Analyses,
MachineFunction &mf, VirtRegMap &vrm)
MachineFunction &mf, VirtRegMap &vrm, LiveRegMatrix &matrix)
: MF(mf), LIS(Analyses.LIS), LSS(Analyses.LSS), MDT(Analyses.MDT),
VRM(vrm), MRI(mf.getRegInfo()), TII(*mf.getSubtarget().getInstrInfo()),
TRI(*mf.getSubtarget().getRegisterInfo()), MBFI(Analyses.MBFI),
IPA(LIS, mf.getNumBlockIDs()) {}
Matrix(matrix), IPA(LIS, mf.getNumBlockIDs()) {}

void addToMergeableSpills(MachineInstr &Spill, int StackSlot,
Register Original);
bool rmFromMergeableSpills(MachineInstr &Spill, int StackSlot);
void hoistAllSpills();
bool LRE_CanEraseVirtReg(Register) override;
void LRE_DidCloneVirtReg(Register, Register) override;
};

Expand Down Expand Up @@ -191,7 +193,7 @@ class InlineSpiller : public Spiller {
: MF(MF), LIS(Analyses.LIS), LSS(Analyses.LSS), VRM(VRM),
MRI(MF.getRegInfo()), TII(*MF.getSubtarget().getInstrInfo()),
TRI(*MF.getSubtarget().getRegisterInfo()), Matrix(Matrix),
HSpiller(Analyses, MF, VRM), VRAI(VRAI) {}
HSpiller(Analyses, MF, VRM, *Matrix), VRAI(VRAI) {}

void spill(LiveRangeEdit &, AllocationOrder *Order = nullptr) override;
ArrayRef<Register> getSpilledRegs() override { return RegsToSpill; }
Expand Down Expand Up @@ -1750,6 +1752,16 @@ void HoistSpillHelper::hoistAllSpills() {
}
}

/// Called before a virtual register is erased from LiveIntervals.
/// Forcibly remove the register from LiveRegMatrix before it's deleted,
/// preventing dangling pointers.
bool HoistSpillHelper::LRE_CanEraseVirtReg(Register VirtReg) {
if (VRM.hasPhys(VirtReg)) {
Matrix.unassign(VirtReg);
}
return true; // Allow deletion to proceed
}

/// For VirtReg clone, the \p New register should have the same physreg or
/// stackslot as the \p old register.
void HoistSpillHelper::LRE_DidCloneVirtReg(Register New, Register Old) {
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/CodeGen/LiveIntervalUnion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ void LiveIntervalUnion::extract(const LiveInterval &VirtReg,
}
}

void LiveIntervalUnion::clearAllSegmentsReferencing(
const LiveInterval &VirtReg) {
++Tag;

// Remove all segments referencing VirtReg.
for (SegmentIter SegPos = Segments.begin(); SegPos.valid();) {
if (SegPos.value() == &VirtReg)
SegPos.erase();
else
++SegPos;
}
}

void
LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
if (empty()) {
Expand Down
43 changes: 43 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 @@ -142,6 +144,20 @@ void LiveRegMatrix::unassign(const LiveInterval &VirtReg) {
LLVM_DEBUG(dbgs() << '\n');
}

void LiveRegMatrix::unassign(Register VirtReg) {
Register PhysReg = VRM->getPhys(VirtReg);
LLVM_DEBUG(dbgs() << "unassigning " << printReg(VirtReg, TRI) << " from "
<< printReg(PhysReg, TRI) << '\n');
VRM->clearVirt(VirtReg);

assert(LIS->hasInterval(VirtReg));
const LiveInterval &LI = LIS->getInterval(VirtReg);
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
Matrix[Unit].clearAllSegmentsReferencing(LI);
}
++NumUnassigned;
}

bool LiveRegMatrix::isPhysRegUsed(MCRegister PhysReg) const {
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
if (!Matrix[Unit].empty())
Expand Down Expand Up @@ -290,6 +306,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
5 changes: 3 additions & 2 deletions llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,12 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();

for (unsigned Reg : RegsToRewrite) {
LIS->removeInterval(Reg);

const Register PhysReg = VRM->getPhys(Reg);
assert(PhysReg != 0);

Matrix->unassign(Reg);
LIS->removeInterval(Reg);

MFI->reserveWWMRegister(PhysReg);
}

Expand Down