[MachineCopyPropagation][NFC] Refactor EliminateSpillageCopies (#192609)

This patch builds on the original implementation to address areas that
may impact compile time regression if enabled. The aim of the patch is
to streamline and improve the implementation for better compile time
impact. A summary of the changes is as follows:
- Cost modelling that does an initial scan of the block, any blocks with
less than 6 copies are immediately skipped.
- RegMask scan in `findLastSeenDefInCopy` removed. This now only checks
the recorded copies to ensure that RegMasks are clobbered when they are
seen if they clobber a Reg
- Streamlining of `IsSpillReloadPair` and `IsChainedCopy` to reduce the
need for a second call to isCopyInstr to get the DestSourcePair, these
are now returned from the lamdba function
- Use of TRI API to get the CommonRegClass

Assisted-by: Claude Sonnet 4.6 (Co-Pilot)
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 4d2a66f..fd14a02 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -421,20 +421,39 @@
     if (!TRI.isSubRegisterEq(Dst, Reg))
       return nullptr;
 
-    for (const MachineInstr &MI :
-         make_range(static_cast<const MachineInstr *>(DefCopy)->getIterator(),
-                    Current.getIterator()))
-      for (const MachineOperand &MO : MI.operands())
-        if (MO.isRegMask())
-          if (MO.clobbersPhysReg(Dst)) {
-            LLVM_DEBUG(dbgs() << "MCP: Removed tracking of "
-                              << printReg(Dst, &TRI) << "\n");
-            return nullptr;
-          }
-
     return DefCopy;
   }
 
+  void clobberNonPreservedRegs(const BitVector &PreservedRegUnits,
+                               const TargetRegisterInfo &TRI,
+                               const TargetInstrInfo &TII) {
+    SmallVector<MCRegUnit, 8> UnitsToClobber;
+    for (auto &[Unit, _] : Copies)
+      if (!PreservedRegUnits.test(static_cast<unsigned>(Unit)))
+        UnitsToClobber.push_back(Unit);
+
+    for (MCRegUnit Unit : UnitsToClobber) {
+      // If we clobber the RegUnit, it will mark all the DefReg Units
+      // as unavailable, which leads to issues if the Destination Reg Unit is
+      // preserved, and used later. As such, only mark them as unavailable if
+      // they are not preserved.
+      auto RegUnitInfo = Copies.find(Unit);
+      if (RegUnitInfo == Copies.end())
+        continue;
+
+      for (MCRegister DstReg : RegUnitInfo->second.DefRegs) {
+        for (MCRegUnit DstUnit : TRI.regunits(DstReg)) {
+          if (!PreservedRegUnits.test(static_cast<unsigned>(DstUnit))) {
+            if (auto CI = Copies.find(DstUnit); CI != Copies.end()) {
+              CI->second.Avail = false;
+            }
+          }
+        }
+      }
+      Copies.erase(RegUnitInfo);
+    }
+  }
+
   // Find last COPY that uses Reg.
   MachineInstr *findLastSeenUseInCopy(MCRegister Reg,
                                       const TargetRegisterInfo &TRI) {
@@ -1324,11 +1343,7 @@
             return;
 
         auto CheckCopyConstraint = [this](Register Dst, Register Src) {
-          for (const TargetRegisterClass *RC : TRI->regclasses()) {
-            if (RC->contains(Dst) && RC->contains(Src))
-              return true;
-          }
-          return false;
+          return TRI->getCommonMinimalPhysRegClass(Dst, Src);
         };
 
         auto UpdateReg = [](MachineInstr *MI, const MachineOperand *Old,
@@ -1367,44 +1382,48 @@
         }
       };
 
-  auto IsFoldableCopy = [this](const MachineInstr &MaybeCopy) {
+  auto GetFoldableCopy =
+      [this](const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
     if (MaybeCopy.getNumImplicitOperands() > 0)
-      return false;
+      return std::nullopt;
     std::optional<DestSourcePair> CopyOperands =
         isCopyInstr(MaybeCopy, *TII, UseCopyInstr);
     if (!CopyOperands)
-      return false;
+      return std::nullopt;
     auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
-    return Src && Dst && !TRI->regsOverlap(Src, Dst) &&
-           CopyOperands->Source->isRenamable() &&
-           CopyOperands->Destination->isRenamable();
+    if (Src && Dst && !TRI->regsOverlap(Src, Dst) &&
+        CopyOperands->Source->isRenamable() &&
+        CopyOperands->Destination->isRenamable())
+      return CopyOperands;
+
+    return std::nullopt;
   };
 
-  auto IsSpillReloadPair = [&, this](const MachineInstr &Spill,
-                                     const MachineInstr &Reload) {
-    if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))
+  auto IsSpillReloadPair = [&](const MachineInstr &Spill,
+                               const MachineInstr &Reload) {
+    std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
+    if (!FoldableSpillCopy)
       return false;
-    std::optional<DestSourcePair> SpillCopy =
-        isCopyInstr(Spill, *TII, UseCopyInstr);
-    std::optional<DestSourcePair> ReloadCopy =
-        isCopyInstr(Reload, *TII, UseCopyInstr);
-    if (!SpillCopy || !ReloadCopy)
+    std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
+    if (!FoldableReloadCopy)
       return false;
-    return getSrcMCReg(*SpillCopy) == getDstMCReg(*ReloadCopy) &&
-           getDstMCReg(*SpillCopy) == getSrcMCReg(*ReloadCopy);
+    return FoldableSpillCopy->Source->getReg() ==
+               FoldableReloadCopy->Destination->getReg() &&
+           FoldableSpillCopy->Destination->getReg() ==
+               FoldableReloadCopy->Source->getReg();
   };
 
-  auto IsChainedCopy = [&, this](const MachineInstr &Prev,
-                                 const MachineInstr &Current) {
-    if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))
+  auto IsChainedCopy = [&](const MachineInstr &Prev,
+                           const MachineInstr &Current) {
+    std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
+    if (!FoldablePrevCopy)
       return false;
-    std::optional<DestSourcePair> PrevCopy =
-        isCopyInstr(Prev, *TII, UseCopyInstr);
-    std::optional<DestSourcePair> CurrentCopy =
-        isCopyInstr(Current, *TII, UseCopyInstr);
-    if (!PrevCopy || !CurrentCopy)
+    std::optional<DestSourcePair> FoldableCurrentCopy =
+        GetFoldableCopy(Current);
+    if (!FoldableCurrentCopy)
       return false;
-    return getSrcMCReg(*PrevCopy) == getDstMCReg(*CurrentCopy);
+    return FoldablePrevCopy->Source->getReg() ==
+           FoldableCurrentCopy->Destination->getReg();
   };
 
   for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
@@ -1415,6 +1434,11 @@
     SmallSet<Register, 8> RegsToClobber;
     if (!CopyOperands) {
       for (const MachineOperand &MO : MI.operands()) {
+        if (MO.isRegMask()) {
+          BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *TRI);
+          Tracker.clobberNonPreservedRegs(PreservedRegUnits, *TRI, *TII);
+          continue;
+        }
         if (!MO.isReg())
           continue;
         Register Reg = MO.getReg();