[llvm] [CodeGen] Use SmallSetVector for getRegAllocationHints (PR #224472)

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 17:00:20 PDT 2026


https://github.com/nickdesaulniers updated https://github.com/llvm/llvm-project/pull/224472

>From 58df225acc35c256448fcfc8b183305363f99611 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 17 Sep 2026 14:53:57 -0700
Subject: [PATCH] [CodeGen] Use SmallSetVector for getRegAllocationHints

Change TargetRegisterInfo::getRegAllocationHints and all target overrides
to accept SmallSetVector<MCPhysReg, 16> &Hints instead of SmallVectorImpl,
structurally preventing duplicate register allocation hints while preserving
insertion order.

Assisted-by: Gemini
Link: #190139
Link: #193011
Link: #219007
Link: #224448
Link: #224451
Link: #224742
---
 .../include/llvm/CodeGen/TargetRegisterInfo.h |  3 +-
 llvm/lib/CodeGen/AllocationOrder.cpp          | 10 ++--
 llvm/lib/CodeGen/TargetRegisterInfo.cpp       | 10 +---
 .../Target/AArch64/AArch64RegisterInfo.cpp    | 27 ++++++-----
 llvm/lib/Target/AArch64/AArch64RegisterInfo.h |  2 +-
 llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp     |  8 ++--
 llvm/lib/Target/AMDGPU/SIRegisterInfo.h       |  2 +-
 llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp   |  8 ++--
 llvm/lib/Target/ARM/ARMBaseRegisterInfo.h     |  2 +-
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp   | 16 +++----
 llvm/lib/Target/PowerPC/PPCRegisterInfo.h     |  2 +-
 llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp   | 10 ++--
 llvm/lib/Target/RISCV/RISCVRegisterInfo.h     |  2 +-
 .../Target/SystemZ/SystemZRegisterInfo.cpp    | 12 ++---
 llvm/lib/Target/SystemZ/SystemZRegisterInfo.h |  2 +-
 llvm/lib/Target/X86/X86RegisterInfo.cpp       | 22 ++++-----
 llvm/lib/Target/X86/X86RegisterInfo.h         |  2 +-
 .../AArch64/AArch64RegisterInfoTest.cpp       | 46 +++++++++++++++++++
 18 files changed, 111 insertions(+), 75 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 4678773607377..b18aaa7b05a6b 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -16,6 +16,7 @@
 #define LLVM_CODEGEN_TARGETREGISTERINFO_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
@@ -837,7 +838,7 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
   /// expect to see generic copy hints added.
   virtual bool
   getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                        SmallVectorImpl<MCPhysReg> &Hints,
+                        SmallSetVector<MCPhysReg, 16> &Hints,
                         const MachineFunction &MF,
                         const VirtRegMap *VRM = nullptr,
                         const LiveRegMatrix *Matrix = nullptr) const;
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 6294b86b27c44..4f04a25809430 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -53,14 +53,14 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
   const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
   const MachineRegisterInfo &MRI = MF.getRegInfo();
   auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
+  // Get Hints.
+  SmallSetVector<MCPhysReg, 16> Hints;
+  bool HardHints =
+      TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix);
 
   // HintsAndCustomOrder holds Hints first followed by the custom order if the
   // anti-hints reorders it.
-  SmallVector<MCPhysReg, 16> HintsAndCustomOrder;
-
-  // Get Hints.
-  bool HardHints = TRI->getRegAllocationHints(
-      VirtReg, Order, HintsAndCustomOrder, MF, &VRM, Matrix);
+  SmallVector<MCPhysReg, 16> HintsAndCustomOrder = Hints.takeVector();
   const int NumHints = static_cast<int>(HintsAndCustomOrder.size());
 
   // HintsAndCustomOrder only holds Hints (custom order is not added yet).
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 79b01d27d91a5..fb86ca377e89e 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -14,7 +14,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/LiveInterval.h"
@@ -399,7 +398,7 @@ float TargetRegisterInfo::getSpillWeightScaleFactor(
 // Compute target-independent register allocator hints to help eliminate copies.
 bool TargetRegisterInfo::getRegAllocationHints(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo &MRI = MF.getRegInfo();
   const std::pair<unsigned, SmallVector<Register, 4>> *Hints_MRI =
@@ -408,7 +407,6 @@ bool TargetRegisterInfo::getRegAllocationHints(
   if (!Hints_MRI)
     return false;
 
-  SmallSet<Register, 32> HintedRegs;
   // First hint may be a target hint.
   bool Skip = (Hints_MRI->first != 0);
   for (auto Reg : Hints_MRI->second) {
@@ -422,10 +420,6 @@ bool TargetRegisterInfo::getRegAllocationHints(
     if (VRM && Phys.isVirtual())
       Phys = VRM->getPhys(Phys);
 
-    // Don't add the same reg twice (Hints_MRI may contain multiple virtual
-    // registers allocated to the same physreg).
-    if (!HintedRegs.insert(Phys).second)
-      continue;
     // Check that Phys is a valid hint in VirtReg's register class.
     if (!Phys.isPhysical())
       continue;
@@ -438,7 +432,7 @@ bool TargetRegisterInfo::getRegAllocationHints(
       continue;
 
     // All clear, tell the register allocator to prefer this register.
-    Hints.push_back(Phys.id());
+    Hints.insert(Phys);
   }
   return false;
 }
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 7f22038c206b7..672441c51286c 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -1111,7 +1111,7 @@ unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
 
 static bool HandleDestructivePredicateHint(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const VirtRegMap *VRM,
+    SmallSetVector<MCPhysReg, 16> &Hints, const VirtRegMap *VRM,
     const MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
     const AArch64Subtarget &ST, const LiveRegMatrix *Matrix) {
   const TargetRegisterClass *RegRC = MRI.getRegClass(VirtReg);
@@ -1150,15 +1150,17 @@ static bool HandleDestructivePredicateHint(
       CSRs.insert(R);
   }
 
-  Hints.append(Order.begin(), Order.end());
+  Hints.insert_range(Order);
   auto CanUseReg = [&](Register R) {
     return !CSRs.contains(R) || !MRI.def_empty(R) || Matrix->isPhysRegUsed(R);
   };
-  llvm::stable_sort(Hints, [&](Register A, Register B) {
+  SmallVector<MCPhysReg, 16> SortedHints = Hints.takeVector();
+  llvm::stable_sort(SortedHints, [&](Register A, Register B) {
     bool PrefA = (A != Op1Reg) && CanUseReg(A);
     bool PrefB = (B != Op1Reg) && CanUseReg(B);
     return PrefA && !PrefB;
   });
+  Hints.insert_range(SortedHints);
   return true;
 }
 
@@ -1184,7 +1186,7 @@ static bool HandleDestructivePredicateHint(
 //   begins with $z24 (i.e. $z24_z25_z26_z27).
 bool AArch64RegisterInfo::getRegAllocationHints(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   auto &ST = MF.getSubtarget<AArch64Subtarget>();
   const AArch64InstrInfo *TII =
@@ -1219,7 +1221,7 @@ bool AArch64RegisterInfo::getRegAllocationHints(
             PhysReg = getSubReg(PhysReg, MO.getSubReg());
           if (PhysReg != R)
             return false;
-          Hints.push_back(R);
+          Hints.insert(R);
           return true;
         };
 
@@ -1260,8 +1262,7 @@ bool AArch64RegisterInfo::getRegAllocationHints(
     return ConsiderOnlyHints;
 
   if (!ST.hasSME() || !ST.isStreaming())
-    return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
-                                                     VRM);
+    return ConsiderOnlyHints;
 
   // The SVE calling convention preserves registers Z8-Z23. As a result, there
   // are no ZPR2Strided or ZPR4Strided registers that do not overlap with the
@@ -1380,7 +1381,7 @@ bool AArch64RegisterInfo::getRegAllocationHints(
                    !Matrix->isPhysRegUsed(R);
           };
           if (all_of(seq(0U, TupleSize), IsFreeConsecutiveReg))
-            Hints.push_back(Reg);
+            Hints.insert(Reg);
         }
       } else {
         // At least copy already has a physical register assigned to its source.
@@ -1399,12 +1400,11 @@ bool AArch64RegisterInfo::getRegAllocationHints(
 
         for (unsigned I = 0; I < StridedOrder.size(); ++I)
           if (getSubReg(StridedOrder[I], AArch64::zsub0) == TargetStartReg)
-            Hints.push_back(StridedOrder[I]);
+            Hints.insert(StridedOrder[I]);
       }
 
       if (!Hints.empty())
-        return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints,
-                                                         MF, VRM);
+        return ConsiderOnlyHints;
     }
   }
 
@@ -1431,12 +1431,11 @@ bool AArch64RegisterInfo::getRegAllocationHints(
     // Try to pick a tuple register for Dst with Src as a member.
     for (MCPhysReg R : Order) {
       if (getSubReg(R, Dst.getSubReg()) == SrcZPR)
-        Hints.push_back(R);
+        Hints.insert(R);
     }
   }
 
-  return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
-                                                   VRM);
+  return ConsiderOnlyHints;
 }
 
 unsigned AArch64RegisterInfo::getLocalAddressRegister(
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index 5f6b0a2472b1a..4b577e7206f2f 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -138,7 +138,7 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
                                MachineFunction &MF) const override;
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 1aa423e1da647..8e620613aca9d 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4239,7 +4239,7 @@ const int *SIRegisterInfo::getRegUnitPressureSets(MCRegUnit RegUnit) const {
 
 bool SIRegisterInfo::getRegAllocationHints(Register VirtReg,
                                            ArrayRef<MCPhysReg> Order,
-                                           SmallVectorImpl<MCPhysReg> &Hints,
+                                           SmallSetVector<MCPhysReg, 16> &Hints,
                                            const MachineFunction &MF,
                                            const VirtRegMap *VRM,
                                            const LiveRegMatrix *Matrix) const {
@@ -4266,7 +4266,7 @@ bool SIRegisterInfo::getRegAllocationHints(Register VirtReg,
     if (PairedPhys)
       // isLo(Paired) is implicitly true here from the API of
       // getMatchingSuperReg.
-      Hints.push_back(PairedPhys);
+      Hints.insert(PairedPhys);
     return false;
   }
   case AMDGPURI::Size16: {
@@ -4281,7 +4281,7 @@ bool SIRegisterInfo::getRegAllocationHints(Register VirtReg,
 
     // First prefer the paired physreg.
     if (PairedPhys)
-      Hints.push_back(PairedPhys);
+      Hints.insert(PairedPhys);
     else {
       // Add all the lo16 physregs.
       // When the Paired operand has not yet been assigned a physreg it is
@@ -4293,7 +4293,7 @@ bool SIRegisterInfo::getRegAllocationHints(Register VirtReg,
           continue;
         if (AMDGPU::VGPR_16RegClass.contains(PhysReg) &&
             !MRI.isReserved(PhysReg))
-          Hints.push_back(PhysReg);
+          Hints.insert(PhysReg);
       }
     }
     return false;
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index c5a4162fbb01c..72ffc3eaaa5d6 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -375,7 +375,7 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
                                   unsigned Idx) const override;
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 5496729bcb2b3..b21e77be60f9a 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -358,7 +358,7 @@ static MCRegister getPairedGPR(MCRegister Reg, bool Odd,
 // Resolve the RegPairEven / RegPairOdd register allocator hints.
 bool ARMBaseRegisterInfo::getRegAllocationHints(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo &MRI = MF.getRegInfo();
   std::pair<unsigned, Register> Hint = MRI.getRegAllocationHint(VirtReg);
@@ -374,7 +374,7 @@ bool ARMBaseRegisterInfo::getRegAllocationHints(
   case ARMRI::RegLR:
     TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM);
     if (MRI.getRegClass(VirtReg)->contains(ARM::LR))
-      Hints.push_back(ARM::LR);
+      Hints.insert(ARM::LR);
     return false;
   default:
     return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM);
@@ -396,7 +396,7 @@ bool ARMBaseRegisterInfo::getRegAllocationHints(
 
   // First prefer the paired physreg.
   if (PairedPhys && is_contained(Order, PairedPhys))
-    Hints.push_back(PairedPhys);
+    Hints.insert(PairedPhys);
 
   // Then prefer even or odd registers.
   for (MCPhysReg Reg : Order) {
@@ -406,7 +406,7 @@ bool ARMBaseRegisterInfo::getRegAllocationHints(
     MCRegister Paired = getPairedGPR(Reg, !Odd, this);
     if (!Paired || MRI.isReserved(Paired))
       continue;
-    Hints.push_back(Reg);
+    Hints.insert(Reg);
   }
   return false;
 }
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
index 7a73680e637bc..cea598e302707 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
@@ -101,7 +101,7 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
                                MachineFunction &MF) const override;
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 80f678200f79a..c2908551402c7 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -534,12 +534,10 @@ bool PPCRegisterInfo::isCallerPreservedPhysReg(MCRegister PhysReg,
   return false;
 }
 
-bool PPCRegisterInfo::getRegAllocationHints(Register VirtReg,
-                                            ArrayRef<MCPhysReg> Order,
-                                            SmallVectorImpl<MCPhysReg> &Hints,
-                                            const MachineFunction &MF,
-                                            const VirtRegMap *VRM,
-                                            const LiveRegMatrix *Matrix) const {
+bool PPCRegisterInfo::getRegAllocationHints(
+    Register VirtReg, ArrayRef<MCPhysReg> Order,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
+    const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo *MRI = &MF.getRegInfo();
 
   // Call the base implementation first to set any hints based on the usual
@@ -580,11 +578,11 @@ bool PPCRegisterInfo::getRegAllocationHints(Register VirtReg,
           HintReg = getSubReg(UACCPhys, ResultOp->getSubReg());
           // Ensure that the hint is a VSRp register.
           if (HintReg >= PPC::VSRp0 && HintReg <= PPC::VSRp31)
-            Hints.push_back(HintReg);
+            Hints.insert(HintReg);
         } else if (RegClass->contains(PPC::ACC0)) {
           HintReg = PPC::ACC0 + (UACCPhys - PPC::UACC0);
           if (HintReg >= PPC::ACC0 && HintReg <= PPC::ACC7)
-            Hints.push_back(HintReg);
+            Hints.insert(HintReg);
         }
       }
       break;
@@ -598,7 +596,7 @@ bool PPCRegisterInfo::getRegAllocationHints(Register VirtReg,
         assert((ACCPhys >= PPC::ACC0 && ACCPhys <= PPC::ACC7) &&
                "Expecting an ACC register for BUILD_UACC.");
         Register HintReg = PPC::UACC0 + (ACCPhys - PPC::ACC0);
-        Hints.push_back(HintReg);
+        Hints.insert(HintReg);
       }
       break;
     }
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index 0c5b9d8b94233..ca0a700ac541e 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -106,7 +106,7 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
   // Similarly if UACC5 is assigned, we want to assign VSRp10, VSRp11
   // to its inputs.
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index adc6eadee2e35..33738a9661571 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -999,7 +999,7 @@ float RISCVRegisterInfo::getSpillWeightScaleFactor(
 // instruction.
 bool RISCVRegisterInfo::getRegAllocationHints(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo *MRI = &MF.getRegInfo();
   auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
@@ -1023,7 +1023,7 @@ bool RISCVRegisterInfo::getRegAllocationHints(
       // Verify it's valid and available
       if (RISCV::GPRRegClass.contains(TargetReg) &&
           is_contained(Order, TargetReg))
-        Hints.push_back(TargetReg.id());
+        Hints.insert(TargetReg.id());
     }
 
     // Second priority: Try to find consecutive register pairs in the allocation
@@ -1040,7 +1040,7 @@ bool RISCVRegisterInfo::getRegAllocationHints(
       // Don't provide hints that are paired to a reserved register.
       MCRegister Paired = PhysReg + (IsOdd ? -1 : 1);
       if (WantOdd == IsOdd && !MRI->isReserved(Paired))
-        Hints.push_back(PhysReg);
+        Hints.insert(PhysReg);
     }
   }
 
@@ -1062,7 +1062,7 @@ bool RISCVRegisterInfo::getRegAllocationHints(
     // physical register is even (or vice versa), we should not add the hint.
     if (PhysReg && (!NeedGPRC || RISCV::GPRCRegClass.contains(PhysReg)) &&
         !MO.getSubReg() && !VRRegMO.getSubReg()) {
-      if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
+      if (!MRI->isReserved(PhysReg) && !Hints.contains(PhysReg))
         TwoAddrHints.insert(PhysReg);
     }
   };
@@ -1190,7 +1190,7 @@ bool RISCVRegisterInfo::getRegAllocationHints(
 
   for (MCPhysReg OrderReg : Order)
     if (TwoAddrHints.count(OrderReg))
-      Hints.push_back(OrderReg);
+      Hints.insert(OrderReg);
 
   return BaseImplRetVal;
 }
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
index e94f5f0b4b364..a0610f4446a29 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -151,7 +151,7 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
   float getSpillWeightScaleFactor(const TargetRegisterClass *RC) const override;
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 177f2c50e4f01..4cc20bbad6ee5 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -55,7 +55,7 @@ static const TargetRegisterClass *getRC32(MachineOperand &MO,
 // registers are copy hints (and therefore already in Hints), hint them
 // first.
 static void addHints(ArrayRef<MCPhysReg> Order,
-                     SmallVectorImpl<MCPhysReg> &Hints,
+                     SmallSetVector<MCPhysReg, 16> &Hints,
                      const TargetRegisterClass *RC,
                      const MachineRegisterInfo *MRI) {
   SmallSet<unsigned, 4> CopyHints(llvm::from_range, Hints);
@@ -63,16 +63,16 @@ static void addHints(ArrayRef<MCPhysReg> Order,
   for (MCPhysReg Reg : Order)
     if (CopyHints.count(Reg) &&
         RC->contains(Reg) && !MRI->isReserved(Reg))
-      Hints.push_back(Reg);
+      Hints.insert(Reg);
   for (MCPhysReg Reg : Order)
     if (!CopyHints.count(Reg) &&
         RC->contains(Reg) && !MRI->isReserved(Reg))
-      Hints.push_back(Reg);
+      Hints.insert(Reg);
 }
 
 bool SystemZRegisterInfo::getRegAllocationHints(
     Register VirtReg, ArrayRef<MCPhysReg> Order,
-    SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
     const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo *MRI = &MF.getRegInfo();
   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
@@ -114,7 +114,7 @@ bool SystemZRegisterInfo::getRegAllocationHints(
             if (VRRegMO->getSubReg())
               PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),
                                             MRI->getRegClass(VirtReg));
-            if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
+            if (!MRI->isReserved(PhysReg) && !Hints.contains(PhysReg))
               TwoAddrHints.insert(PhysReg);
           }
         };
@@ -124,7 +124,7 @@ bool SystemZRegisterInfo::getRegAllocationHints(
       }
     for (MCPhysReg OrderReg : Order)
       if (TwoAddrHints.count(OrderReg))
-        Hints.push_back(OrderReg);
+        Hints.insert(OrderReg);
   }
 
   if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
index 7247736ff44e9..1182c408ac1e8 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -138,7 +138,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
   getCrossCopyRegClass(const TargetRegisterClass *RC) const override;
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 7e1003c9b470b..864e93fd0c1bb 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -1163,12 +1163,10 @@ static ShapeT getTileShape(Register VirtReg, VirtRegMap *VRM,
   }
 }
 
-bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
-                                            ArrayRef<MCPhysReg> Order,
-                                            SmallVectorImpl<MCPhysReg> &Hints,
-                                            const MachineFunction &MF,
-                                            const VirtRegMap *VRM,
-                                            const LiveRegMatrix *Matrix) const {
+bool X86RegisterInfo::getRegAllocationHints(
+    Register VirtReg, ArrayRef<MCPhysReg> Order,
+    SmallSetVector<MCPhysReg, 16> &Hints, const MachineFunction &MF,
+    const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
   const MachineRegisterInfo *MRI = &MF.getRegInfo();
   const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
   bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(
@@ -1192,7 +1190,7 @@ bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
     auto TryAddNDDHint = [&](const MachineOperand &MO) {
       Register Reg = MO.getReg();
       Register PhysReg = Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg));
-      if (PhysReg && !MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))
+      if (PhysReg && !MRI->isReserved(PhysReg) && !Hints.contains(PhysReg))
         TwoAddrHints.insert(PhysReg);
     };
 
@@ -1219,7 +1217,7 @@ bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
 
     for (MCPhysReg OrderReg : Order)
       if (TwoAddrHints.count(OrderReg))
-        Hints.push_back(OrderReg);
+        Hints.insert(OrderReg);
 
     return BaseImplRetVal;
   }
@@ -1228,22 +1226,22 @@ bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
   auto AddHint = [&](MCPhysReg PhysReg) {
     Register VReg = Matrix->getOneVReg(PhysReg);
     if (VReg == MCRegister::NoRegister) { // Not allocated yet
-      Hints.push_back(PhysReg);
+      Hints.insert(PhysReg);
       return;
     }
     ShapeT PhysShape = getTileShape(VReg, const_cast<VirtRegMap *>(VRM), MRI);
     if (PhysShape == VirtShape)
-      Hints.push_back(PhysReg);
+      Hints.insert(PhysReg);
   };
 
-  SmallSet<MCPhysReg, 4> CopyHints(llvm::from_range, Hints);
+  SmallSetVector<MCPhysReg, 16> CopyHints(Hints);
   Hints.clear();
   for (auto Hint : CopyHints) {
     if (RC.contains(Hint) && !MRI->isReserved(Hint))
       AddHint(Hint);
   }
   for (MCPhysReg PhysReg : Order) {
-    if (!CopyHints.count(PhysReg) && RC.contains(PhysReg) &&
+    if (!CopyHints.contains(PhysReg) && RC.contains(PhysReg) &&
         !MRI->isReserved(PhysReg))
       AddHint(PhysReg);
   }
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h
index 399c6ab863705..5818675cc6829 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.h
+++ b/llvm/lib/Target/X86/X86RegisterInfo.h
@@ -165,7 +165,7 @@ class X86RegisterInfo final : public X86GenRegisterInfo {
   unsigned getSlotSize() const { return SlotSize; }
 
   bool getRegAllocationHints(Register VirtReg, ArrayRef<MCPhysReg> Order,
-                             SmallVectorImpl<MCPhysReg> &Hints,
+                             SmallSetVector<MCPhysReg, 16> &Hints,
                              const MachineFunction &MF, const VirtRegMap *VRM,
                              const LiveRegMatrix *Matrix) const override;
 
diff --git a/llvm/unittests/Target/AArch64/AArch64RegisterInfoTest.cpp b/llvm/unittests/Target/AArch64/AArch64RegisterInfoTest.cpp
index 0f2cc69be42e5..0ec1554096587 100644
--- a/llvm/unittests/Target/AArch64/AArch64RegisterInfoTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64RegisterInfoTest.cpp
@@ -4,6 +4,7 @@
 #include "AArch64TargetMachine.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -187,4 +188,49 @@ TEST(AArch64ReservedRegs, ArtificialHIRegistersAreReserved) {
   EXPECT_TRUE(Reserved.test(AArch64::Q31_HI));
 }
 
+TEST(AArch64RegAllocationHints, NoDuplicates) {
+  std::unique_ptr<TargetMachine> TM = createTargetMachine("");
+  ASSERT_TRUE(TM);
+
+  std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
+  ASSERT_TRUE(II);
+
+  const AArch64RegisterInfo &TRI = II->getRegisterInfo();
+
+  LLVMContext Context;
+  Module M("", Context);
+  M.setDataLayout(TM->getTargetTriple().computeDataLayout());
+  Function *F = Function::Create(
+      FunctionType::get(Type::getVoidTy(Context), /*isVarArg=*/false),
+      GlobalValue::ExternalLinkage, "f", &M);
+
+  MachineModuleInfo MMI(TM.get());
+  const TargetSubtargetInfo *STI = TM->getSubtargetImpl(*F);
+  MachineFunction MF(*F, *TM, *STI, MMI.getContext(), /*FunctionNum=*/0);
+  MF.initTargetMachineFunctionInfo(*STI);
+
+  MachineRegisterInfo &MRI = MF.getRegInfo();
+  MRI.freezeReservedRegs();
+
+  Register VirtReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
+  MRI.addRegAllocationHint(VirtReg, AArch64::X0);
+
+  ArrayRef<MCPhysReg> Order = AArch64::GPR64RegClass.getRegisters();
+  SmallSetVector<MCPhysReg, 16> Hints;
+
+  // Calling getRegAllocationHints once should not produce duplicate hints
+  // from fallthrough to TargetRegisterInfo::getRegAllocationHints.
+  TRI.getRegAllocationHints(VirtReg, Order, Hints, MF, /*VRM=*/nullptr,
+                            /*Matrix=*/nullptr);
+  EXPECT_EQ(Hints.size(), 1u);
+  EXPECT_EQ(Hints[0], MCPhysReg(AArch64::X0));
+
+  // Calling getRegAllocationHints a second time with Hints already populated
+  // should not append duplicate hints.
+  TRI.getRegAllocationHints(VirtReg, Order, Hints, MF, /*VRM=*/nullptr,
+                            /*Matrix=*/nullptr);
+  EXPECT_EQ(Hints.size(), 1u);
+  EXPECT_EQ(Hints[0], MCPhysReg(AArch64::X0));
+}
+
 } // namespace



More information about the llvm-commits mailing list