[llvm-branch-commits] [llvm] CodeGen: Replace some getPointerRegClass() uses with operand reg classes (PR #223965)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 16 03:22:26 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/223965

CodeGen: Replace some getPointerRegClass() uses with operand reg classes

Try to take the register class from the contexual instruction begin emitted
instead. This is a step towards fully replacing PointerLikeRegClass with
RegClassByHwMode.

Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>

CodeGen: Remove PointerLikeRegClass

Remove PointerLikeRegClass and the related getPointerRegClass
TargetRegisterInfo hook. This is obsoleted by RegClassByHwMode.
Previously targets would have to map ptr_rc to an assumed pointer
register class by implementing this method, but this is now auto-resolvable
per instruction using RegClassByHwMode.

Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>

Remove getRegClassByHwMode

Merge branch 'users/arsenm/codegen/replace-getPointerRegClass-uses-context-operand' into users/arsenm/codegen/remove-pointerlikeregclass

>From 94a0c832e67e741a262a39f5bce945ada9e69f41 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 15 Sep 2026 19:10:51 +0200
Subject: [PATCH 1/2] CodeGen: Replace some getPointerRegClass() uses with
 operand reg classes

Try to take the register class from the contexual instruction begin emitted
instead. This is a step towards fully replacing PointerLikeRegClass with
RegClassByHwMode.

Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp             | 5 +++--
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp              | 4 +---
 llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp | 4 ++--
 llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp  | 4 ++--
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 05d2b4815dcf0..b23134a514cf4 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2674,8 +2674,9 @@ void IRTranslatorImpl::getStackGuard(Register DstReg,
     return;
   }
 
-  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
-  MRI->setRegClass(DstReg, TRI->getPointerRegClass());
+  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
+  MRI->setRegClass(DstReg,
+                   TII.getRegClass(TII.get(TargetOpcode::LOAD_STACK_GUARD), 0));
   auto MIB =
       MIRBuilder.buildInstr(TargetOpcode::LOAD_STACK_GUARD, {DstReg}, {});
 
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index f5d5d945947d5..59ef5008dd332 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -2021,9 +2021,7 @@ Register PPCRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB,
   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
   const MCInstrDesc &MCID = TII.get(ADDriOpc);
   MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
-  const TargetRegisterClass *RC = getPointerRegClass();
-  Register BaseReg = MRI.createVirtualRegister(RC);
-  MRI.constrainRegClass(BaseReg, TII.getRegClass(MCID, 0));
+  Register BaseReg = MRI.createVirtualRegister(TII.getRegClass(MCID, 0));
 
   BuildMI(*MBB, Ins, DL, MCID, BaseReg)
     .addFrameIndex(FrameIdx).addImm(Offset);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 442d75f1884f0..7331db70fca72 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -293,7 +293,7 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
   DebugLoc DL;
 
   const TargetRegisterClass *PtrRC =
-      MRI.getTargetRegisterInfo()->getPointerRegClass();
+      TII->getRegClass(TII->get(getOpcConst(MF)), 0);
   unsigned SPReg = getSPReg(MF);
   if (StackSize)
     SPReg = MRI.createVirtualRegister(PtrRC);
@@ -371,7 +371,7 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
     SPReg = FI->getBasePointerVreg();
   } else if (StackSize) {
     const TargetRegisterClass *PtrRC =
-        MRI.getTargetRegisterInfo()->getPointerRegClass();
+        TII->getRegClass(TII->get(getOpcConst(MF)), 0);
     Register OffsetReg = MRI.createVirtualRegister(PtrRC);
     BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg)
         .addImm(StackSize);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 0472851543168..bdcdb6d153138 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -117,8 +117,8 @@ bool WebAssemblyRegisterInfo::eliminateFrameIndex(
   unsigned FIRegOperand = FrameRegister;
   if (FrameOffset) {
     // Create i32/64.add SP, offset and make it the operand.
-    const TargetRegisterClass *PtrRC =
-        MRI.getTargetRegisterInfo()->getPointerRegClass();
+    const TargetRegisterClass *PtrRC = TII->getRegClass(
+        TII->get(WebAssemblyFrameLowering::getOpcConst(MF)), 0);
     Register OffsetOp = MRI.createVirtualRegister(PtrRC);
     BuildMI(MBB, *II, II->getDebugLoc(),
             TII->get(WebAssemblyFrameLowering::getOpcConst(MF)),

>From ea24e60e5ca5e8d0505b98f9dd5b2b1c94ceb8fe Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 15 Sep 2026 18:35:59 +0200
Subject: [PATCH 2/2] CodeGen: Remove PointerLikeRegClass

Remove PointerLikeRegClass and the related getPointerRegClass
TargetRegisterInfo hook. This is obsoleted by RegClassByHwMode.
Previously targets would have to map ptr_rc to an assumed pointer
register class by implementing this method, but this is now auto-resolvable
per instruction using RegClassByHwMode.

Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>

Remove getRegClassByHwMode
---
 .../include/llvm/CodeGen/TargetRegisterInfo.h |  8 ------
 llvm/include/llvm/Target/Target.td            | 28 ++++++-------------
 .../Target/AArch64/AArch64RegisterInfo.cpp    |  5 ----
 llvm/lib/Target/AArch64/AArch64RegisterInfo.h |  2 --
 llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp     |  8 ------
 llvm/lib/Target/AMDGPU/SIRegisterInfo.h       |  3 --
 llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp   |  5 ----
 llvm/lib/Target/ARM/ARMBaseRegisterInfo.h     |  2 --
 llvm/lib/Target/ARM/ThumbRegisterInfo.cpp     |  7 -----
 llvm/lib/Target/ARM/ThumbRegisterInfo.h       |  3 --
 llvm/lib/Target/AVR/AVRRegisterInfo.cpp       |  8 ------
 llvm/lib/Target/AVR/AVRRegisterInfo.h         |  3 --
 .../Target/Hexagon/HexagonRegisterInfo.cpp    |  5 ----
 llvm/lib/Target/Hexagon/HexagonRegisterInfo.h |  3 --
 .../Target/LoongArch/LoongArchRegisterInfo.h  |  5 ----
 llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp |  5 ----
 llvm/lib/Target/MSP430/MSP430RegisterInfo.h   |  2 --
 llvm/lib/Target/Mips/MipsRegisterInfo.cpp     |  6 ----
 llvm/lib/Target/Mips/MipsRegisterInfo.h       |  1 -
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp   | 17 -----------
 llvm/lib/Target/PowerPC/PPCRegisterInfo.h     |  5 ----
 llvm/lib/Target/RISCV/RISCVRegisterInfo.h     |  5 ----
 llvm/lib/Target/Sparc/SparcRegisterInfo.cpp   |  6 ----
 llvm/lib/Target/Sparc/SparcRegisterInfo.h     |  2 --
 llvm/lib/Target/SystemZ/SystemZRegisterInfo.h |  8 ------
 llvm/lib/Target/VE/VERegisterInfo.cpp         |  5 ----
 llvm/lib/Target/VE/VERegisterInfo.h           |  2 --
 .../WebAssembly/WebAssemblyRegisterInfo.cpp   |  7 -----
 .../WebAssembly/WebAssemblyRegisterInfo.h     |  2 --
 llvm/lib/Target/X86/X86RegisterInfo.cpp       | 12 --------
 llvm/lib/Target/X86/X86RegisterInfo.h         |  5 ----
 llvm/test/TableGen/invalid_typecast_assert.td |  2 +-
 .../TableGen/target-specialized-pseudos.td    |  6 ++--
 .../TableGen/Common/CodeGenInstruction.cpp    |  3 +-
 llvm/utils/TableGen/Common/CodeGenTarget.cpp  | 13 +++++++++
 llvm/utils/TableGen/Common/CodeGenTarget.h    |  9 +++---
 llvm/utils/TableGen/InstrInfoEmitter.cpp      | 21 ++++++++------
 37 files changed, 45 insertions(+), 194 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index dacd5fb575a4d..6b0e3e1289c85 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -715,14 +715,6 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
   getCommonSubClass(const TargetRegisterClass *A,
                     const TargetRegisterClass *B) const;
 
-  /// Returns a TargetRegisterClass used for pointer values.
-  /// If a target supports multiple different pointer register classes,
-  /// kind specifies which one is indicated.
-  virtual const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const {
-    llvm_unreachable("Target didn't implement getPointerRegClass!");
-  }
-
   /// Returns a legal register class to copy a register in the specified class
   /// to or from. If it is possible to copy the register directly without using
   /// a cross register class copy, return the specified RC. Returns NULL if it
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 279de17d00da5..25a8e40d73ee5 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1001,23 +1001,6 @@ def slice;
 def encoder;
 def decoder;
 
-/// PointerLikeRegClass - Pseudoinstruction operands that are designed
-/// to have pointer width are derived from this. This should only be
-/// used by StandardPseudoInstruction instructions. No target specific
-/// instruction should use this.
-class PointerLikeRegClass<int Kind> {
-  int RegClassKind = Kind;
-}
-
-/// ptr_rc definition - Mark this operand as being a pointer value
-/// whose register class needs to be defined by the target. Targets
-/// should provide instruction definition overrides which substitute
-/// the uses of this with the backend defined RegisterClass or
-/// RegClassByHwMode to use for pointer virtual registers for a
-/// particular opcode (typically by defining a subsitute instruction
-/// with RemapPointerOperands).
-def ptr_rc : PointerLikeRegClass<0>;
-
 /// RegClassByHwMode - Operands that change the register class based
 /// on the subtarget are derived from this. TableGen
 /// treats the register class as having a symbolic kind that it
@@ -1031,6 +1014,13 @@ class RegClassByHwMode<list<HwMode> Modes,
   list<RegisterClass> Objects = RegClasses;
 }
 
+/// ptr_rc - Placeholder pointer operand for the generic
+/// StandardPseudoInstructions. It has no register classes of its own; each
+/// target must substitute a real RegClassByHwMode (or RegisterClass) via
+/// RemapPointerOperands (typically RemapAllTargetPseudoPointerOperands). An
+/// unremapped ptr_rc reaching the instruction-info emitter is an error.
+def ptr_rc : RegClassByHwMode<[], []>;
+
 /// unknown definition - Mark this operand as being of unknown type, causing
 /// it to be resolved by inference in the context it is used.
 class unknown_class;
@@ -1761,7 +1751,7 @@ defvar PseudosWithPtrOps = [
 ];
 
 
-/// Replace PointerLikeRegClass operands in OperandList with new_rc.
+/// Replace ptr_rc placeholder operands in OperandList with new_rc.
 class RemapPointerOperandList<dag OperandList, RegisterClassLike new_rc> {
   // Collect the set of names so we can query and rewrite them.
   list<string> op_names = !foreach(i, !range(!size(OperandList)),
@@ -1777,7 +1767,7 @@ class RemapPointerOperandList<dag OperandList, RegisterClassLike new_rc> {
   dag ret =
     !foldl(OperandList, op_names, acc, name,
       !cond(
-        !initialized(!getdagarg<PointerLikeRegClass>(OperandList, name))
+        !initialized(!getdagarg<RegClassByHwMode>(OperandList, name))
           : !setdagarg(acc, name, new_rc),
         !initialized(!getdagarg<unknown_class>(OperandList, name)) : acc,
         !initialized(!getdagarg<DAGOperand>(OperandList, name)) : acc
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index c8e0cb289abdf..7f22038c206b7 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -605,11 +605,6 @@ bool AArch64RegisterInfo::isAsmClobberable(const MachineFunction &MF,
   return !isReservedReg(MF, PhysReg);
 }
 
-const TargetRegisterClass *
-AArch64RegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &AArch64::GPR64spRegClass;
-}
-
 const TargetRegisterClass *
 AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
   if (RC == &AArch64::CCRRegClass)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index 681ede4584a3b..5f6b0a2472b1a 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -106,8 +106,6 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
   bool isAsmClobberable(const MachineFunction &MF,
                        MCRegister PhysReg) const override;
   const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-  const TargetRegisterClass *
   getCrossCopyRegClass(const TargetRegisterClass *RC) const override;
 
   bool requiresRegisterScavenging(const MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 720f4b5d61464..bf5c821611dd8 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -1140,14 +1140,6 @@ bool SIRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
                                 AMDGPU::FlatAddrSpace::FlatScratch);
 }
 
-const TargetRegisterClass *
-SIRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  // This is inaccurate. It depends on the instruction and address space. The
-  // only place where we should hit this is for dealing with frame indexes /
-  // private accesses, so this is correct in that case.
-  return &AMDGPU::VGPR_32RegClass;
-}
-
 const TargetRegisterClass *
 SIRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
   return RC == &AMDGPU::SCC_CLASSRegClass ? &AMDGPU::SReg_32RegClass : RC;
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 66909861271e2..1eb9a88b819ed 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -169,9 +169,6 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
   bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg,
                           int64_t Offset) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   /// Returns a legal register class to copy a register in the specified class
   /// to or from. If it is possible to copy the register directly without using
   /// a cross register class copy, return the specified RC. Returns NULL if it
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index a0bbaab3ec85e..5496729bcb2b3 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -309,11 +309,6 @@ ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
   return RC;
 }
 
-const TargetRegisterClass *
-ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &ARM::GPRRegClass;
-}
-
 const TargetRegisterClass *
 ARMBaseRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
   if (RC == &ARM::CCRRegClass)
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
index 1f0681bf2ee3e..7a73680e637bc 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
@@ -90,8 +90,6 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
   bool isInlineAsmReadOnlyReg(const MachineFunction &MF,
                               MCRegister PhysReg) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
   const TargetRegisterClass *
   getCrossCopyRegClass(const TargetRegisterClass *RC) const override;
 
diff --git a/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp b/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp
index 85e705d4c5e24..5373d13493703 100644
--- a/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp
@@ -49,13 +49,6 @@ ThumbRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
   return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF);
 }
 
-const TargetRegisterClass *
-ThumbRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  if (!IsThumb1Only)
-    return ARMBaseRegisterInfo::getPointerRegClass(Kind);
-  return &ARM::tGPRRegClass;
-}
-
 static void emitThumb1LoadConstPool(MachineBasicBlock &MBB,
                                     MachineBasicBlock::iterator &MBBI,
                                     const DebugLoc &dl, unsigned DestReg,
diff --git a/llvm/lib/Target/ARM/ThumbRegisterInfo.h b/llvm/lib/Target/ARM/ThumbRegisterInfo.h
index 1512a09cae200..11c2fa364bb35 100644
--- a/llvm/lib/Target/ARM/ThumbRegisterInfo.h
+++ b/llvm/lib/Target/ARM/ThumbRegisterInfo.h
@@ -33,9 +33,6 @@ struct ThumbRegisterInfo : public ARMBaseRegisterInfo {
   getLargestLegalSuperClass(const TargetRegisterClass *RC,
                             const MachineFunction &MF) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   /// emitLoadConstPool - Emits a load from constpool to materialize the
   /// specified immediate.
   void
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
index 880c91537ef6a..ac86ffb321a32 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -268,14 +268,6 @@ Register AVRRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   return AVR::SP;
 }
 
-const TargetRegisterClass *
-AVRRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  // FIXME: Currently we're using avr-gcc as reference, so we restrict
-  // ptrs to Y and Z regs. Though avr-gcc has buggy implementation
-  // of memory constraint, so we can fix it and bit avr-gcc here ;-)
-  return &AVR::PTRDISPREGSRegClass;
-}
-
 void AVRRegisterInfo::splitReg(Register Reg, Register &LoReg,
                                Register &HiReg) const {
   assert(AVR::DREGSRegClass.contains(Reg) && "can only split 16-bit registers");
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.h b/llvm/lib/Target/AVR/AVRRegisterInfo.h
index e69696b4d9160..7f8448091cc66 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.h
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.h
@@ -43,9 +43,6 @@ class AVRRegisterInfo : public AVRGenRegisterInfo {
 
   Register getFrameRegister(const MachineFunction &MF) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   /// Splits a 16-bit `DREGS` register into the lo/hi register pair.
   /// \param Reg A 16-bit register to split.
   void splitReg(Register Reg, Register &LoReg, Register &HiReg) const;
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index d66b8541e4942..8797a38ef0735 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -496,8 +496,3 @@ bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF)
       const {
   return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
 }
-
-const TargetRegisterClass *
-HexagonRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &Hexagon::IntRegsRegClass;
-}
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h
index bf990ad752d36..52146fbe7a6c3 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h
@@ -76,9 +76,6 @@ class HexagonRegisterInfo : public HexagonGenRegisterInfo {
   const MCPhysReg *getCallerSavedRegs(const MachineFunction *MF,
         const TargetRegisterClass *RC) const;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   /// Returns true if the given reserved physical register is live across
   /// function calls/returns.
   bool isGlobalReg(MCPhysReg Reg) const;
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h
index 53381c28898b8..74861e0f87d6f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h
@@ -32,11 +32,6 @@ struct LoongArchRegisterInfo : public LoongArchGenRegisterInfo {
 
   BitVector getReservedRegs(const MachineFunction &MF) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override {
-    return &LoongArch::GPRRegClass;
-  }
-
   bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
diff --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp b/llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp
index c1a1e8e83e0d3..7bd76ff12ba82 100644
--- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp
+++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.cpp
@@ -90,11 +90,6 @@ BitVector MSP430RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
-const TargetRegisterClass *
-MSP430RegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &MSP430::GR16RegClass;
-}
-
 bool
 MSP430RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
                                         int SPAdj, unsigned FIOperandNum,
diff --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
index fbca97361232d..d1ed52090532f 100644
--- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
+++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
@@ -28,8 +28,6 @@ class MSP430RegisterInfo : public MSP430GenRegisterInfo {
   const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
 
   BitVector getReservedRegs(const MachineFunction &MF) const override;
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
 
   bool eliminateFrameIndex(MachineBasicBlock::iterator II,
                            int SPAdj, unsigned FIOperandNum,
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index ed5f2d48902f2..76ab9da919b88 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -45,12 +45,6 @@ MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &STI)
 
 unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; }
 
-const TargetRegisterClass *
-MipsRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  assert(Kind == 0 && "this should only be used for default case");
-  return ArePtrs64bit ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
-}
-
 unsigned
 MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
                                       MachineFunction &MF) const {
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h
index 9e6ef66163bd9..80ba23d173cbc 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.h
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h
@@ -36,7 +36,6 @@ class MipsRegisterInfo : public MipsGenRegisterInfo {
   static unsigned getPICCallReg();
 
   /// Code Generation virtual methods...
-  const TargetRegisterClass *getPointerRegClass(unsigned Kind) const override;
 
   unsigned getRegPressureLimit(const TargetRegisterClass *RC,
                                MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index f5d5d945947d5..bb362e01add77 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -160,23 +160,6 @@ PPCRegisterInfo::PPCRegisterInfo(const PPCTargetMachine &TM)
   ImmToIdxMap[PPC::PSTXVP] = PPC::STXVPX;
 }
 
-/// getPointerRegClass - Return the register class to use to hold pointers.
-/// This is used for addressing modes.
-const TargetRegisterClass *
-PPCRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  // Note that PPCInstrInfo::foldImmediate also directly uses this Kind value
-  // when it checks for ZERO folding.
-  if (Kind == 1) {
-    if (TM.isPPC64())
-      return &PPC::G8RC_NOX0RegClass;
-    return &PPC::GPRC_NOR0RegClass;
-  }
-
-  if (TM.isPPC64())
-    return &PPC::G8RCRegClass;
-  return &PPC::GPRCRegClass;
-}
-
 const MCPhysReg*
 PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index 560690208f704..0c5b9d8b94233 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -76,11 +76,6 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
     return It->second;
   }
 
-  /// getPointerRegClass - Return the register class to use to hold pointers.
-  /// This is used for addressing modes.
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   const TargetRegisterClass *
   getCrossCopyRegClass(const TargetRegisterClass *RC) const override;
 
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
index de24178acca45..e94f5f0b4b364 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -139,11 +139,6 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
     return true;
   }
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override {
-    return &RISCV::GPRRegClass;
-  }
-
   const TargetRegisterClass *
   getLargestLegalSuperClass(const TargetRegisterClass *RC,
                             const MachineFunction &) const override;
diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
index 0a14746f587bb..5c2af0aa55b2c 100644
--- a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -112,12 +112,6 @@ bool SparcRegisterInfo::isReservedReg(const MachineFunction &MF,
   return getReservedRegs(MF)[Reg];
 }
 
-const TargetRegisterClass *
-SparcRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  assert(Kind == 0 && "this should only be used for default cases");
-  return Is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
-}
-
 static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,
                       MachineInstr &MI, const DebugLoc &dl,
                       unsigned FIOperandNum, int Offset, unsigned FramePtr) {
diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/llvm/lib/Target/Sparc/SparcRegisterInfo.h
index abd8baeff56a2..30f0b9f191383 100644
--- a/llvm/lib/Target/Sparc/SparcRegisterInfo.h
+++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.h
@@ -38,8 +38,6 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
   BitVector getReservedRegs(const MachineFunction &MF) const override;
   bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const;
 
-  const TargetRegisterClass *getPointerRegClass(unsigned Kind) const override;
-
   bool eliminateFrameIndex(MachineBasicBlock::iterator II,
                            int SPAdj, unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
index bea8b9f8ae74a..7247736ff44e9 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -131,14 +131,6 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
 public:
   SystemZRegisterInfo(unsigned int RA, unsigned int HwMode);
 
-  /// getPointerRegClass - Return the register class to use to hold pointers.
-  /// This is currently only used by LOAD_STACK_GUARD, which requires a non-%r0
-  /// register, hence ADDR64.
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override {
-    return &SystemZ::ADDR64BitRegClass;
-  }
-
   /// getCrossCopyRegClass - Returns a legal register class to copy a register
   /// in the specified class to or from. Returns NULL if it is possible to copy
   /// between a two registers of the specified class.
diff --git a/llvm/lib/Target/VE/VERegisterInfo.cpp b/llvm/lib/Target/VE/VERegisterInfo.cpp
index 0c1183e2ac541..d4ca1ac74c049 100644
--- a/llvm/lib/Target/VE/VERegisterInfo.cpp
+++ b/llvm/lib/Target/VE/VERegisterInfo.cpp
@@ -92,11 +92,6 @@ BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
-const TargetRegisterClass *
-VERegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &VE::I64RegClass;
-}
-
 static unsigned offsetToDisp(MachineInstr &MI) {
   // Default offset in instruction's operands (reg+reg+imm).
   unsigned OffDisp = 2;
diff --git a/llvm/lib/Target/VE/VERegisterInfo.h b/llvm/lib/Target/VE/VERegisterInfo.h
index 999dc856c9bd5..f812603dfe404 100644
--- a/llvm/lib/Target/VE/VERegisterInfo.h
+++ b/llvm/lib/Target/VE/VERegisterInfo.h
@@ -31,8 +31,6 @@ struct VERegisterInfo : public VEGenRegisterInfo {
 
   BitVector getReservedRegs(const MachineFunction &MF) const override;
 
-  const TargetRegisterClass *getPointerRegClass(unsigned Kind) const override;
-
   bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 0472851543168..ed9273688b206 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -149,13 +149,6 @@ WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];
 }
 
-const TargetRegisterClass *
-WebAssemblyRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  assert(Kind == 0 && "Only one kind of pointer on WebAssembly");
-  return TT.getArch() == Triple::wasm64 ? &WebAssembly::I64RegClass
-                                        : &WebAssembly::I32RegClass;
-}
-
 static const TargetRegisterClass &getRegClassForBank(const RegisterBank &RB) {
   switch (RB.getID()) {
   case WebAssembly::I32RegBankID:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
index 325f412bfc78a..ad525e686555e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
@@ -42,8 +42,6 @@ class WebAssemblyRegisterInfo final : public WebAssemblyGenRegisterInfo {
   // Debug information queries.
   Register getFrameRegister(const MachineFunction &MF) const override;
 
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
   // This does not apply to wasm.
   const uint32_t *getNoPreservedMask() const override { return nullptr; }
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index cc132fa1bc4db..e67e99ac10cf7 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -196,18 +196,6 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
   return RC;
 }
 
-const TargetRegisterClass *
-X86RegisterInfo::getPointerRegClass(unsigned Kind) const {
-  assert(Kind == 0 && "this should only be used for default cases");
-  if (IsTarget64BitLP64)
-    return &X86::GR64RegClass;
-  // If the target is 64bit but we have been told to use 32bit addresses,
-  // we can still use 64-bit register as long as we know the high bits
-  // are zeros.
-  // Reflect that in the returned register class.
-  return Is64Bit ? &X86::LOW32_ADDR_ACCESSRegClass : &X86::GR32RegClass;
-}
-
 const TargetRegisterClass *
 X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
   if (RC == &X86::CCRRegClass) {
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h
index e646591663aca..b292a9404ae3b 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.h
+++ b/llvm/lib/Target/X86/X86RegisterInfo.h
@@ -78,11 +78,6 @@ class X86RegisterInfo final : public X86GenRegisterInfo {
   getLargestLegalSuperClass(const TargetRegisterClass *RC,
                             const MachineFunction &MF) const override;
 
-  /// getPointerRegClass - Returns a TargetRegisterClass used for pointer
-  /// values.
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
-
   /// getCrossCopyRegClass - Returns a legal register class to copy a register
   /// in the specified class to or from. Returns NULL if it is possible to copy
   /// between a two registers of the specified class.
diff --git a/llvm/test/TableGen/invalid_typecast_assert.td b/llvm/test/TableGen/invalid_typecast_assert.td
index d0e8706ebfe5a..8ae1965b16336 100644
--- a/llvm/test/TableGen/invalid_typecast_assert.td
+++ b/llvm/test/TableGen/invalid_typecast_assert.td
@@ -41,7 +41,7 @@ def MY_LOAD : TestInstruction {
 }
 
 // CHECK: [[@LINE+2]]:1: error: {{.*}} Type cast only takes one operand!
-// CHECK: [[@LINE+1]]:1: error: {{.*}} cannot update node type from unknown operand!
+// CHECK: [[@LINE+1]]:1: error: {{.*}} was provided 2 operands but expected only 1!
 def : Pat<
   (i64 (load (iPTR:$src))),
   (MY_LOAD $val, $src)
diff --git a/llvm/test/TableGen/target-specialized-pseudos.td b/llvm/test/TableGen/target-specialized-pseudos.td
index bf55926f21983..10314ed531672 100644
--- a/llvm/test/TableGen/target-specialized-pseudos.td
+++ b/llvm/test/TableGen/target-specialized-pseudos.td
@@ -73,7 +73,7 @@ def MY_LOAD_STACK_GUARD :
   let OutOperandList = (outs XRegs:$dst);
 }
 
-// ERROR-MISSING: error: missing target override for pseudoinstruction using PointerLikeRegClass
+// ERROR-MISSING: error: missing target override for pseudoinstruction using ptr_rc
 // ERROR-MISSING note: target should define equivalent instruction with RegisterClassLike replacement; (use RemapAllTargetPseudoPointerOperands?)
 
 
@@ -98,8 +98,8 @@ def MY_LOAD_STACK_GUARD_1 : TargetSpecializedStandardPseudoInstruction<LOAD_STAC
 #ifdef ERROR_NONPSEUDO
 
 // FIXME: Double error
-// ERROR-NONPSEUDO: [[@LINE+2]]:5: error: non-pseudoinstruction user of PointerLikeRegClass
-// ERROR-NONPSEUDO: [[@LINE+1]]:5: error: non-pseudoinstruction user of PointerLikeRegClass
+// ERROR-NONPSEUDO: [[@LINE+2]]:5: error: non-pseudoinstruction user of ptr_rc
+// ERROR-NONPSEUDO: [[@LINE+1]]:5: error: non-pseudoinstruction user of ptr_rc
 def NON_PSEUDO : TestInstruction {
   let OutOperandList = (outs XRegs:$dst);
   let InOperandList = (ins ptr_rc:$src);
diff --git a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
index 62a7b54d86e7b..d5236b00910dc 100644
--- a/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp
@@ -120,8 +120,7 @@ CGIOperandList::CGIOperandList(const Record *R) : TheDef(R) {
       continue;
     } else if (Rec->isSubClassOf("RegisterClassLike")) {
       OperandType = "OPERAND_REGISTER";
-    } else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
-               !Rec->isSubClassOf("unknown_class")) {
+    } else if (!Rec->isSubClassOf("unknown_class")) {
       PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() +
                                        "' in '" + R->getName() +
                                        "' instruction!");
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.cpp b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
index 6965ee8c75b15..ba6c938d88bcd 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
@@ -91,6 +91,19 @@ CodeGenTarget::~CodeGenTarget() = default;
 
 StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
 
+ArrayRef<const Record *> CodeGenTarget::getAllRegClassByHwMode() const {
+  if (!RegClassByHwModeList) {
+    RegClassByHwModeList.emplace();
+    for (const Record *R :
+         Records.getAllDerivedDefinitions("RegClassByHwMode")) {
+      if (!R->getValueAsListOfDefs("Objects").empty())
+        RegClassByHwModeList->push_back(R);
+    }
+  }
+
+  return *RegClassByHwModeList;
+}
+
 /// getInstNamespace - Find and return the target machine's instruction
 /// namespace. The namespace is cached because it is requested multiple times.
 StringRef CodeGenTarget::getInstNamespace() const {
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.h b/llvm/utils/TableGen/Common/CodeGenTarget.h
index 482816f774df9..c04d331357b28 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.h
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.h
@@ -28,6 +28,7 @@
 #include "llvm/CodeGenTypes/MachineValueType.h"
 #include <cassert>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -62,6 +63,7 @@ class CodeGenTarget {
   mutable std::unique_ptr<CodeGenRegBank> RegBank;
   mutable ArrayRef<const Record *> RegAltNameIndices;
   mutable SmallVector<ValueTypeByHwMode, 8> LegalValueTypes;
+  mutable std::optional<std::vector<const Record *>> RegClassByHwModeList;
   CodeGenHwModes CGH;
   ArrayRef<const Record *> MacroFusions;
   mutable bool HasVariableLengthEncodings = false;
@@ -142,10 +144,9 @@ class CodeGenTarget {
   /// Convenience wrapper to avoid hardcoding the name of RegClassByHwMode
   /// everywhere. This is here instead of CodeGenRegBank to avoid the fatal
   /// error that occurs when no RegisterClasses are defined when constructing
-  /// the bank.
-  ArrayRef<const Record *> getAllRegClassByHwMode() const {
-    return Records.getAllDerivedDefinitions("RegClassByHwMode");
-  }
+  /// the bank. The empty ptr_rc placeholder is excluded: it carries no register
+  /// classes and only exists to be substituted per target.
+  ArrayRef<const Record *> getAllRegClassByHwMode() const;
 
   /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the
   /// specified physical register.
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 3b730cc33d7a9..095cb13e74a64 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -155,28 +155,33 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
       if (OpR->isSubClassOf("RegisterOperand"))
         OpR = OpR->getValueAsDef("RegClass");
 
-      if (OpR->isSubClassOf("RegClassByHwMode")) {
+      if (OpR->isSubClassOf("RegClassByHwMode") &&
+          !OpR->getValueAsListOfDefs("Objects").empty()) {
         Res += Namespace;
         Res += "::";
         Res += OpR->getName();
         Res += ", ";
-      } else if (OpR->isSubClassOf("RegisterClass"))
-        Res += getQualifiedName(OpR) + "RegClassID, ";
-      else if (OpR->isSubClassOf("PointerLikeRegClass")) {
+      } else if (OpR->isSubClassOf("RegClassByHwMode")) {
+        // An empty RegClassByHwMode is the generic ptr_rc placeholder. It must
+        // be substituted with a real class per target (via
+        // RemapAllTargetPseudoPointerOperands); reaching here means it was not.
         if (Inst.isPseudo) {
           // TODO: Verify this is a fixed pseudo
           PrintError(Inst.TheDef,
                      "missing target override for pseudoinstruction "
-                     "using PointerLikeRegClass");
+                     "using ptr_rc");
           PrintNote(OpR->getLoc(),
                     "target should define equivalent instruction "
                     "with RegisterClassLike replacement; (use "
                     "RemapAllTargetPseudoPointerOperands?)");
         } else {
-          PrintError(Inst.TheDef,
-                     "non-pseudoinstruction user of PointerLikeRegClass");
+          PrintError(Inst.TheDef, "non-pseudoinstruction user of ptr_rc");
         }
-      } else
+        // -1 means the operand does not have a fixed register class.
+        Res += "-1, ";
+      } else if (OpR->isSubClassOf("RegisterClass"))
+        Res += getQualifiedName(OpR) + "RegClassID, ";
+      else
         // -1 means the operand does not have a fixed register class.
         Res += "-1, ";
 



More information about the llvm-branch-commits mailing list