aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/RegAllocBase.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2025-02-26 15:34:47 +0700
committerGitHub <noreply@github.com>2025-02-26 15:34:47 +0700
commit1a114fa302b48fc761a58a8d3be5962d92fa581b (patch)
tree7ffaae3824a09adaa0a998200886274b55113e5a /llvm/lib/CodeGen/RegAllocBase.cpp
parente160c35c9ec69c099daeffdbca3cf4c94d3e05b9 (diff)
downloadllvm-1a114fa302b48fc761a58a8d3be5962d92fa581b.zip
llvm-1a114fa302b48fc761a58a8d3be5962d92fa581b.tar.gz
llvm-1a114fa302b48fc761a58a8d3be5962d92fa581b.tar.bz2
RegAlloc: Use new approach to handling failed allocations (#128469)
This fixes an assert after allocation failure. Rather than collecting failed virtual registers and hacking on the uses after the fact, directly hack on the uses and rewrite the registers to the dummy assignment immediately. Previously we were bypassing LiveRegMatrix and directly assigning in the VirtRegMap. This resulted in inconsistencies where illegal overlapping assignments were missing. Rather than try to hack in some system to manage these in LiveRegMatrix (i.e. hacking around cases with invalid iterators), avoid this by directly using the physreg. This should also allow removal of special casing in virtregrewriter for failed allocations.
Diffstat (limited to 'llvm/lib/CodeGen/RegAllocBase.cpp')
-rw-r--r--llvm/lib/CodeGen/RegAllocBase.cpp66
1 files changed, 21 insertions, 45 deletions
diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp
index d66d396..b9599e7 100644
--- a/llvm/lib/CodeGen/RegAllocBase.cpp
+++ b/llvm/lib/CodeGen/RegAllocBase.cpp
@@ -128,8 +128,7 @@ void RegAllocBase::allocatePhysRegs() {
AvailablePhysReg = getErrorAssignment(*RC, MI);
// Keep going after reporting the error.
- VRM->assignVirt2Phys(VirtReg->reg(), AvailablePhysReg);
- FailedVRegs.insert(VirtReg->reg());
+ cleanupFailedVReg(VirtReg->reg(), AvailablePhysReg, SplitVRegs);
} else if (AvailablePhysReg)
Matrix->assign(*VirtReg, AvailablePhysReg);
@@ -163,58 +162,35 @@ void RegAllocBase::postOptimization() {
DeadRemats.clear();
}
-void RegAllocBase::cleanupFailedVRegs() {
- SmallSet<Register, 8> JunkRegs;
-
- for (Register FailedReg : FailedVRegs) {
- JunkRegs.insert(FailedReg);
-
- MCRegister PhysReg = VRM->getPhys(FailedReg);
- LiveInterval &FailedInterval = LIS->getInterval(FailedReg);
-
- // The liveness information for the failed register and anything interfering
- // with the physical register we arbitrarily chose is junk and needs to be
- // deleted.
- for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
- LiveIntervalUnion::Query &Q = Matrix->query(FailedInterval, *Units);
- for (const LiveInterval *InterferingReg : Q.interferingVRegs())
- JunkRegs.insert(InterferingReg->reg());
- LIS->removeRegUnit(*Units);
- }
+void RegAllocBase::cleanupFailedVReg(Register FailedReg, MCRegister PhysReg,
+ SmallVectorImpl<Register> &SplitRegs) {
+ // We still should produce valid IR. Kill all the uses and reduce the live
+ // ranges so that we don't think it's possible to introduce kill flags later
+ // which will fail the verifier.
+ for (MachineOperand &MO : MRI->reg_operands(FailedReg)) {
+ if (MO.readsReg())
+ MO.setIsUndef(true);
}
- for (Register JunkReg : JunkRegs) {
- MCRegister PhysReg = VRM->getPhys(JunkReg);
- // We still should produce valid IR. Kill all the uses and reduce the live
- // ranges so that we don't think it's possible to introduce kill flags
- // later which will fail the verifier.
- for (MachineOperand &MO : MRI->reg_operands(JunkReg)) {
- if (MO.readsReg())
- MO.setIsUndef(true);
- }
-
- // The liveness of the assigned physical register is also now unreliable.
+ if (!MRI->isReserved(PhysReg)) {
+ // Physical liveness for any aliasing registers is now unreliable, so delete
+ // the uses.
for (MCRegAliasIterator Aliases(PhysReg, TRI, true); Aliases.isValid();
++Aliases) {
for (MachineOperand &MO : MRI->reg_operands(*Aliases)) {
- if (MO.readsReg())
+ if (MO.readsReg()) {
MO.setIsUndef(true);
- }
- }
-
- LiveInterval &JunkLI = LIS->getInterval(JunkReg);
- if (LIS->shrinkToUses(&JunkLI)) {
- SmallVector<LiveInterval *, 8> SplitLIs;
- LIS->splitSeparateComponents(JunkLI, SplitLIs);
-
- VRM->grow();
- Register Original = VRM->getOriginal(JunkReg);
- for (LiveInterval *SplitLI : SplitLIs) {
- VRM->setIsSplitFromReg(SplitLI->reg(), Original);
- VRM->assignVirt2Phys(SplitLI->reg(), PhysReg);
+ LIS->removeAllRegUnitsForPhysReg(MO.getReg());
+ }
}
}
}
+
+ // Directly perform the rewrite, and do not leave it to VirtRegRewriter as
+ // usual. This avoids trying to manage illegal overlapping assignments in
+ // LiveRegMatrix.
+ MRI->replaceRegWith(FailedReg, PhysReg);
+ LIS->removeInterval(FailedReg);
}
void RegAllocBase::enqueue(const LiveInterval *LI) {