Skip to content

Conversation

@s-barannikov
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-llvm-mc

@llvm/pr-subscribers-llvm-regalloc

Author: Sergei Barannikov (s-barannikov)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/167901.diff

8 Files Affected:

  • (modified) llvm/include/llvm/MC/MCRegisterInfo.h (+8)
  • (modified) llvm/lib/CodeGen/LiveIntervals.cpp (+4-3)
  • (modified) llvm/lib/CodeGen/LiveRegMatrix.cpp (+3-2)
  • (modified) llvm/lib/CodeGen/LiveRegUnits.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/MachineVerifier.cpp (+3-3)
  • (modified) llvm/lib/CodeGen/RDFRegisters.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/ReachingDefAnalysis.cpp (+4-4)
  • (modified) llvm/lib/CodeGen/RegAllocFast.cpp (+1-2)
diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h
index e6dbb38dfee67..f1caa077a6d7b 100644
--- a/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -16,6 +16,7 @@
 #define LLVM_MC_MCREGISTERINFO_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/MC/LaneBitmask.h"
@@ -259,6 +260,9 @@ class LLVM_ABI MCRegisterInfo {
                        iterator_range<MCSuperRegIterator>>
   sub_and_superregs_inclusive(MCRegister Reg) const;
 
+  /// Returns an iterator range over all regunits.
+  iota_range<MCRegUnit> regunits() const;
+
   /// Returns an iterator range over all regunits for \p Reg.
   iterator_range<MCRegUnitIterator> regunits(MCRegister Reg) const;
 
@@ -798,6 +802,10 @@ MCRegisterInfo::sub_and_superregs_inclusive(MCRegister Reg) const {
   return concat<const MCPhysReg>(subregs_inclusive(Reg), superregs(Reg));
 }
 
+inline iota_range<MCRegUnit> MCRegisterInfo::regunits() const {
+  return seq(getNumRegUnits());
+}
+
 inline iterator_range<MCRegUnitIterator>
 MCRegisterInfo::regunits(MCRegister Reg) const {
   return make_range({Reg, this}, MCRegUnitIterator());
diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp
index 27c5addffa4ab..9af1f53e5ced0 100644
--- a/llvm/lib/CodeGen/LiveIntervals.cpp
+++ b/llvm/lib/CodeGen/LiveIntervals.cpp
@@ -173,8 +173,8 @@ void LiveIntervals::analyze(MachineFunction &fn) {
   if (EnablePrecomputePhysRegs) {
     // For stress testing, precompute live ranges of all physical register
     // units, including reserved registers.
-    for (unsigned i = 0, e = TRI->getNumRegUnits(); i != e; ++i)
-      getRegUnit(i);
+    for (MCRegUnit Unit : TRI->regunits())
+      getRegUnit(Unit);
   }
 }
 
@@ -182,7 +182,8 @@ void LiveIntervals::print(raw_ostream &OS) const {
   OS << "********** INTERVALS **********\n";
 
   // Dump the regunits.
-  for (unsigned Unit = 0, UnitE = RegUnitRanges.size(); Unit != UnitE; ++Unit)
+  assert(RegUnitRanges.size() == TRI->getNumRegUnits());
+  for (MCRegUnit Unit : TRI->regunits())
     if (LiveRange *LR = RegUnitRanges[Unit])
       OS << printRegUnit(Unit, TRI) << ' ' << *LR << '\n';
 
diff --git a/llvm/lib/CodeGen/LiveRegMatrix.cpp b/llvm/lib/CodeGen/LiveRegMatrix.cpp
index e3ee8dc325933..38d4810c38061 100644
--- a/llvm/lib/CodeGen/LiveRegMatrix.cpp
+++ b/llvm/lib/CodeGen/LiveRegMatrix.cpp
@@ -75,8 +75,9 @@ void LiveRegMatrix::init(MachineFunction &MF, LiveIntervals &pLIS,
 void LiveRegMatrixWrapperLegacy::releaseMemory() { LRM.releaseMemory(); }
 
 void LiveRegMatrix::releaseMemory() {
-  for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
-    Matrix[i].clear();
+  assert(Matrix.size() == TRI->getNumRegUnits());
+  for (MCRegUnit Unit : TRI->regunits()) {
+    Matrix[Unit].clear();
     // No need to clear Queries here, since LiveIntervalUnion::Query doesn't
     // have anything important to clear and LiveRegMatrix's runOnFunction()
     // does a std::unique_ptr::reset anyways.
diff --git a/llvm/lib/CodeGen/LiveRegUnits.cpp b/llvm/lib/CodeGen/LiveRegUnits.cpp
index 0d87062169585..3e7052a9b6245 100644
--- a/llvm/lib/CodeGen/LiveRegUnits.cpp
+++ b/llvm/lib/CodeGen/LiveRegUnits.cpp
@@ -20,7 +20,7 @@
 using namespace llvm;
 
 void LiveRegUnits::removeRegsNotPreserved(const uint32_t *RegMask) {
-  for (unsigned U = 0, E = TRI->getNumRegUnits(); U != E; ++U) {
+  for (MCRegUnit U : TRI->regunits()) {
     for (MCRegUnitRootIterator RootReg(U, TRI); RootReg.isValid(); ++RootReg) {
       if (MachineOperand::clobbersPhysReg(RegMask, *RootReg)) {
         Units.reset(U);
@@ -31,7 +31,7 @@ void LiveRegUnits::removeRegsNotPreserved(const uint32_t *RegMask) {
 }
 
 void LiveRegUnits::addRegsInMask(const uint32_t *RegMask) {
-  for (unsigned U = 0, E = TRI->getNumRegUnits(); U != E; ++U) {
+  for (MCRegUnit U : TRI->regunits()) {
     for (MCRegUnitRootIterator RootReg(U, TRI); RootReg.isValid(); ++RootReg) {
       if (MachineOperand::clobbersPhysReg(RegMask, *RootReg)) {
         Units.set(U);
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 013f52938b65c..a2a66d6128348 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -3564,9 +3564,9 @@ void MachineVerifier::verifyLiveIntervals() {
   }
 
   // Verify all the cached regunit intervals.
-  for (unsigned i = 0, e = TRI->getNumRegUnits(); i != e; ++i)
-    if (const LiveRange *LR = LiveInts->getCachedRegUnit(i))
-      verifyLiveRange(*LR, VirtRegOrUnit(i));
+  for (MCRegUnit Unit : TRI->regunits())
+    if (const LiveRange *LR = LiveInts->getCachedRegUnit(Unit))
+      verifyLiveRange(*LR, VirtRegOrUnit(Unit));
 }
 
 void MachineVerifier::verifyLiveRangeValue(const LiveRange &LR,
diff --git a/llvm/lib/CodeGen/RDFRegisters.cpp b/llvm/lib/CodeGen/RDFRegisters.cpp
index 1400699a607ff..e4b63a3a40805 100644
--- a/llvm/lib/CodeGen/RDFRegisters.cpp
+++ b/llvm/lib/CodeGen/RDFRegisters.cpp
@@ -46,7 +46,7 @@ PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri,
 
   UnitInfos.resize(TRI.getNumRegUnits());
 
-  for (uint32_t U = 0, NU = TRI.getNumRegUnits(); U != NU; ++U) {
+  for (MCRegUnit U : TRI.regunits()) {
     if (UnitInfos[U].Reg != 0)
       continue;
     MCRegUnitRootIterator R(U, &TRI);
@@ -88,7 +88,7 @@ PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri,
   }
 
   AliasInfos.resize(TRI.getNumRegUnits());
-  for (uint32_t U = 0, NU = TRI.getNumRegUnits(); U != NU; ++U) {
+  for (MCRegUnit U : TRI.regunits()) {
     BitVector AS(TRI.getNumRegs());
     for (MCRegUnitRootIterator R(U, &TRI); R.isValid(); ++R)
       for (MCPhysReg S : TRI.superregs_inclusive(*R))
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index 61706e13b8e91..c0e7469a7bfd7 100644
--- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
+++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
@@ -155,12 +155,12 @@ void ReachingDefInfo::enterBasicBlock(MachineBasicBlock *MBB) {
       continue;
 
     // Find the most recent reaching definition from a predecessor.
-    for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit)
+    for (MCRegUnit Unit : TRI->regunits())
       LiveRegs[Unit] = std::max(LiveRegs[Unit], Incoming[Unit]);
   }
 
   // Insert the most recent reaching definition we found.
-  for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit)
+  for (MCRegUnit Unit : TRI->regunits())
     if (LiveRegs[Unit] != ReachingDefDefaultVal)
       MBBReachingDefs.append(MBBNumber, Unit, LiveRegs[Unit]);
 }
@@ -235,7 +235,7 @@ void ReachingDefInfo::reprocessBasicBlock(MachineBasicBlock *MBB) {
     if (Incoming.empty())
       continue;
 
-    for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit) {
+    for (MCRegUnit Unit : TRI->regunits()) {
       int Def = Incoming[Unit];
       if (Def == ReachingDefDefaultVal)
         continue;
@@ -368,7 +368,7 @@ void ReachingDefInfo::traverse() {
   // Make sure reaching defs are sorted and unique.
   for (unsigned MBBNumber = 0, NumBlockIDs = MF->getNumBlockIDs();
        MBBNumber != NumBlockIDs; ++MBBNumber) {
-    for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit) {
+    for (MCRegUnit Unit : TRI->regunits()) {
       int LastDef = ReachingDefDefaultVal;
       for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) {
         assert(Def > LastDef && "Defs must be sorted and unique");
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 9097728c84e7e..62d7d2f9eed9a 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -1291,8 +1291,7 @@ bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO,
 #ifndef NDEBUG
 
 void RegAllocFastImpl::dumpState() const {
-  for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
-       ++Unit) {
+  for (MCRegUnit Unit : TRI->regunits()) {
     switch (unsigned VirtReg = RegUnitStates[Unit]) {
     case regFree:
       break;

Copy link
Contributor

@jayfoad jayfoad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me.

#ifndef NDEBUG

void RegAllocFastImpl::dumpState() const {
for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
Copy link
Contributor Author

@s-barannikov s-barannikov Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a small bug here: regunit 0 was skipped. This is a debugging function, so the change should be non-functional.

#ifndef NDEBUG

void RegAllocFastImpl::dumpState() const {
for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to preserve the semantics of Unit = 1 somehow? Maybe with drop_begin?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eye, answered just below

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also probably just apply this in regunits(). There's probably no reason to visit the invalid case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 is a valid regunit AFAICT (unlike MCRegister)
Let me double check

Copy link
Contributor Author

@s-barannikov s-barannikov Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it is valid.
E.g. there is an entry for regunit 0 in AMDGPURegUnitRoots; it says ASYNCcnt is the root.
MCRegisterDesc entry for ASYNCcnt also has regunit 0 encoded in RegUnits field (12 lowest bits).

@s-barannikov s-barannikov enabled auto-merge (squash) November 13, 2025 16:53
@s-barannikov s-barannikov enabled auto-merge (squash) November 13, 2025 17:11
@s-barannikov s-barannikov merged commit d1cc137 into llvm:main Nov 13, 2025
9 of 10 checks passed
@s-barannikov s-barannikov deleted the perf/all-regunits-iterator branch November 13, 2025 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants