[llvm] [CodeGen] Stop scanning RegMasks when all masks are identical (PR #217552)

Liu Ke via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 01:18:44 PDT 2026


https://github.com/Sockke created https://github.com/llvm/llvm-project/pull/217552

checkRegMaskInterference may repeatedly intersect the same RegMask when calls share a mask pointer.

Track whether a MachineFunction uses a single RegMask pointer and stop after the first overlapping mask. Multiple-mask functions retain the existing scan.

This reduces optimized [CTMark instructions](https://llvm-compile-time-tracker.com/compare.php?from=bc0c028fa5a3e8a76bc432f5b22d1ee4883acaca&to=0f6890573f63cdc4a5cf0ffa684d0d81fe258eac&stat=instructions:u) by 0.05-0.08% and Clang build instructions by 0.03%. Greedy RA time decreases by 7.59% on an ASan-instrumented protobuf workload, with identical object output.

>From 0f6890573f63cdc4a5cf0ffa684d0d81fe258eac Mon Sep 17 00:00:00 2001
From: Sockke <liuke.gehry at bytedance.com>
Date: Thu, 20 Aug 2026 15:06:51 +0800
Subject: [PATCH] [CodeGen] Stop scanning RegMasks when all masks are identical

checkRegMaskInterference intersects every RegMask covered by a live
interval. Calls in a MachineFunction commonly share one RegMask pointer,
and applying the same mask repeatedly cannot further change the usable
register set.

Record whether all RegMaskBits entries share one pointer while computing
the masks. In that case, stop after the first overlapping mask. Functions
with multiple mask pointers retain the existing full scan.

This reduces CTMark instructions:u by 0.05-0.08% in optimized
configurations and by 0.03% for the Clang build. On an ASan-instrumented
protobuf workload, Greedy RA time decreases by 7.59% with identical
object output.
---
 llvm/include/llvm/CodeGen/LiveIntervals.h |  4 ++++
 llvm/lib/CodeGen/LiveIntervals.cpp        | 22 +++++++++++++++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/LiveIntervals.h b/llvm/include/llvm/CodeGen/LiveIntervals.h
index e343819097f8f..c70cdb49cb31e 100644
--- a/llvm/include/llvm/CodeGen/LiveIntervals.h
+++ b/llvm/include/llvm/CodeGen/LiveIntervals.h
@@ -94,6 +94,10 @@ class LiveIntervals {
   /// block.
   SmallVector<std::pair<unsigned, unsigned>, 8> RegMaskBlocks;
 
+  /// The register mask pointer shared by every RegMaskBits entry, or nullptr
+  /// when the function uses more than one mask pointer.
+  const uint32_t *SingleRegMask = nullptr;
+
   /// Keeps a live range set for each register unit to track fixed physreg
   /// interference.
   SmallVector<LiveRange *, 0> RegUnitRanges;
diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp
index 26db1afda20aa..c887f62c53a04 100644
--- a/llvm/lib/CodeGen/LiveIntervals.cpp
+++ b/llvm/lib/CodeGen/LiveIntervals.cpp
@@ -147,6 +147,7 @@ void LiveIntervals::clear() {
   RegMaskSlots.clear();
   RegMaskBits.clear();
   RegMaskBlocks.clear();
+  SingleRegMask = nullptr;
 
   for (LiveRange *LR : RegUnitRanges)
     delete LR;
@@ -292,6 +293,16 @@ void LiveIntervals::computeRegMasks() {
     // Compute the number of register mask instructions in this block.
     RMB.second = RegMaskSlots.size() - RMB.first;
   }
+
+  if (!RegMaskBits.empty()) {
+    SingleRegMask = RegMaskBits.front();
+    for (const uint32_t *Mask : RegMaskBits) {
+      if (Mask != SingleRegMask) {
+        SingleRegMask = nullptr;
+        break;
+      }
+    }
+  }
 }
 
 void LiveIntervals::reassignRegMaskSlots(MachineBasicBlock &Orig,
@@ -1031,21 +1042,26 @@ bool LiveIntervals::checkRegMaskInterference(const LiveInterval &LI,
       }
       // Remove usable registers clobbered by this mask.
       UsableRegs.clearBitsNotInMask(Bits[Idx]);
+      // Reapplying the same mask cannot change UsableRegs.
+      return SingleRegMask != nullptr;
   };
   while (true) {
     assert(*SlotI >= LiveI->start);
     // Loop over all slots overlapping this segment.
     while (*SlotI < LiveI->end) {
       // *SlotI overlaps LI. Collect mask bits.
-      unionBitMask(SlotI - Slots.begin());
+      if (unionBitMask(SlotI - Slots.begin()))
+        return true;
       if (++SlotI == SlotE)
         return Found;
     }
     // If segment ends with live-through use we need to collect its regmask.
-    if (*SlotI == LiveI->end)
+    if (*SlotI == LiveI->end) {
       if (MachineInstr *MI = getInstructionFromIndex(*SlotI))
         if (hasLiveThroughUse(MI, LI.reg()))
-          unionBitMask(SlotI++ - Slots.begin());
+          if (unionBitMask(SlotI++ - Slots.begin()))
+            return true;
+    }
     // *SlotI is beyond the current LI segment.
     // Special advance implementation to not miss next LiveI->end.
     if (++LiveI == LiveE || SlotI == SlotE || *SlotI > LI.endIndex())



More information about the llvm-commits mailing list