[llvm] [Mips] Print ABI register names in MIR (PR #228017)

Jiaxun Yang via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 09:19:10 PDT 2026


https://github.com/FlyGoat updated https://github.com/llvm/llvm-project/pull/228017

>From b4c991e34480bf70cb6219fd4bcf0cb8ca1cc65f Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Thu, 1 Oct 2026 11:06:29 +0100
Subject: [PATCH] [Mips] Use ABI register names in MIR

MIPS MIR currently uses TableGen register names, so registers 8-15 use
O32 names even under N32 and N64. Add a TargetRegisterInfo hook for MIR
register names and use it when printing, parsing, and diagnosing physical
register operands.

Select MIPS GPR names from the subtarget ABI and retain the _64 suffix to
distinguish 64-bit registers from their 32-bit subregisters. Other register
names remain unchanged.

Migrate the affected MSA spill fixture and add O32, N32, and N64 tests for
both GPR widths. Check MIR round-trips and emitted numeric assembly operands
to verify that the ABI names preserve physical register identity.
---
 .../include/llvm/CodeGen/TargetRegisterInfo.h |   4 +
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |   4 +-
 llvm/lib/CodeGen/TargetRegisterInfo.cpp       |   2 +-
 llvm/lib/Target/Mips/MipsRegisterInfo.cpp     |  18 +++
 llvm/lib/Target/Mips/MipsRegisterInfo.h       |   5 +
 .../CodeGen/MIR/Mips/abi-register-names.mir   | 141 ++++++++++++++++++
 .../test/CodeGen/Mips/msa/emergency-spill.mir |  22 +--
 7 files changed, 182 insertions(+), 14 deletions(-)
 create mode 100644 llvm/test/CodeGen/MIR/Mips/abi-register-names.mir

diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 46787736073771b..5b531881caadd44 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -1044,6 +1044,10 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
     return StringRef(getName(Reg));
   }
 
+  /// Return the name used to serialize a physical register in MIR. Targets
+  /// with ABI-dependent register names may override this for each subtarget.
+  virtual StringRef getMIRRegName(MCRegister Reg) const { return getName(Reg); }
+
   //===--------------------------------------------------------------------===//
   /// Subtarget Hooks
 
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7b45d028efdd77c..e879982b9de85f9 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -109,7 +109,7 @@ void PerTargetMIParsingState::initNames2Regs() {
 
   for (unsigned I = 0, E = TRI->getNumRegs(); I < E; ++I) {
     bool WasInserted =
-        Names2Regs.insert(std::make_pair(StringRef(TRI->getName(I)).lower(), I))
+        Names2Regs.insert(std::make_pair(TRI->getMIRRegName(I).lower(), I))
             .second;
     (void)WasInserted;
     assert(WasInserted && "Expected registers to be unique case-insensitively");
@@ -1326,7 +1326,7 @@ static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
 static std::string getRegisterName(const TargetRegisterInfo *TRI,
                                    Register Reg) {
   assert(Reg.isPhysical() && "expected phys reg");
-  return StringRef(TRI->getName(Reg)).lower();
+  return TRI->getMIRRegName(Reg).lower();
 }
 
 /// Return true if the parsed machine operands contain a given machine operand.
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 79b01d27d91a5be..bfe31e1f2b9ad0d 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -122,7 +122,7 @@ Printable llvm::printReg(Register Reg, const TargetRegisterInfo *TRI,
       OS << '$' << "physreg" << Reg.id();
     else if (Reg < TRI->getNumRegs()) {
       OS << '$';
-      printLowerCase(TRI->getName(Reg), OS);
+      printLowerCase(TRI->getMIRRegName(Reg), OS);
     } else
       llvm_unreachable("Register kind is unsupported.");
 
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index d68ab86dd0efede..0785aa1bb7906bb 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -12,6 +12,7 @@
 
 #include "MipsRegisterInfo.h"
 #include "MCTargetDesc/MipsABIInfo.h"
+#include "MCTargetDesc/MipsInstPrinter.h"
 #include "Mips.h"
 #include "MipsMachineFunction.h"
 #include "MipsSubtarget.h"
@@ -40,6 +41,23 @@ using namespace llvm;
 MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &STI)
     : MipsGenRegisterInfo(Mips::RA), ArePtrs64bit(STI.getABI().ArePtrs64bit()) {
   MIPS_MC::initLLVMToCVRegMapping(this);
+  MIRRegNames.resize(getNumRegs());
+  const auto &GPR32 = *getRegClass(Mips::GPR32RegClassID);
+  const auto &GPR64 = *getRegClass(Mips::GPR64RegClassID);
+  for (unsigned I = 1; I < getNumRegs(); ++I) {
+    if (GPR32.contains(I) || GPR64.contains(I)) {
+      MIRRegNames[I] = MipsInstPrinter::getRegisterName(
+          I, STI.getABI().getRegAltNameIndex());
+      if (GPR64.contains(I))
+        MIRRegNames[I] += "_64";
+    }
+  }
+}
+
+StringRef MipsRegisterInfo::getMIRRegName(MCRegister Reg) const {
+  if (!MIRRegNames[Reg.id()].empty())
+    return MIRRegNames[Reg.id()];
+  return getName(Reg);
 }
 
 unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; }
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h
index 80ba23d173cbcab..0096b239dd8ff66 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.h
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h
@@ -16,6 +16,8 @@
 #include "Mips.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include <cstdint>
+#include <string>
+#include <vector>
 
 #define GET_REGINFO_HEADER
 #include "MipsGenRegisterInfo.inc"
@@ -28,10 +30,13 @@ using TargetRegisterClass = MCRegisterClass;
 class MipsRegisterInfo : public MipsGenRegisterInfo {
 private:
   const bool ArePtrs64bit;
+  std::vector<std::string> MIRRegNames;
 
 public:
   explicit MipsRegisterInfo(const MipsSubtarget &STI);
 
+  StringRef getMIRRegName(MCRegister Reg) const override;
+
   /// Get PIC indirect call register
   static unsigned getPICCallReg();
 
diff --git a/llvm/test/CodeGen/MIR/Mips/abi-register-names.mir b/llvm/test/CodeGen/MIR/Mips/abi-register-names.mir
new file mode 100644
index 000000000000000..00597f0c6ad6477
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Mips/abi-register-names.mir
@@ -0,0 +1,141 @@
+# RUN: split-file %s %t
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/o32.mir -o %t/o32.out.mir
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/o32.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,O32
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=o32 -verify-machineinstrs \
+# RUN:   -start-after=prolog-epilog %t/o32.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefix=ASM
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n32 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/nabi.mir -o %t/n32.out.mir
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n32 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/n32.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,NABI
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n32 -verify-machineinstrs \
+# RUN:   -start-after=prolog-epilog %t/n32.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefix=ASM
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n64 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/nabi.mir -o %t/n64.out.mir
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n64 -verify-machineinstrs \
+# RUN:   -run-pass=none %t/n64.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,NABI
+# RUN: llc -mtriple=mips64 -mcpu=mips64 -target-abi=n64 -verify-machineinstrs \
+# RUN:   -start-after=prolog-epilog %t/n64.out.mir -o - \
+# RUN:   | FileCheck %s --check-prefix=ASM
+
+# The same hardware registers have different MIR names under O32 and N32/N64.
+# Round-trip both GPR widths through the MIR printer and parser, then check
+# numeric assembly operands to ensure that parsing preserves register identity.
+
+# COMMON-LABEL: name: registers
+# COMMON: bb.0:
+# O32-NEXT: $t0 = ADDiu $zero, 8
+# O32-NEXT: $t1 = ADDiu $zero, 9
+# O32-NEXT: $t2 = ADDiu $zero, 10
+# O32-NEXT: $t3 = ADDiu $zero, 11
+# O32-NEXT: $t4 = ADDiu $zero, 12
+# O32-NEXT: $t5 = ADDiu $zero, 13
+# O32-NEXT: $t6 = ADDiu $zero, 14
+# O32-NEXT: $t7 = ADDiu $zero, 15
+# NABI-NEXT: $a4 = ADDiu $zero, 8
+# NABI-NEXT: $a5 = ADDiu $zero, 9
+# NABI-NEXT: $a6 = ADDiu $zero, 10
+# NABI-NEXT: $a7 = ADDiu $zero, 11
+# NABI-NEXT: $t0 = ADDiu $zero, 12
+# NABI-NEXT: $t1 = ADDiu $zero, 13
+# NABI-NEXT: $t2 = ADDiu $zero, 14
+# NABI-NEXT: $t3 = ADDiu $zero, 15
+# O32-NEXT: $t0_64 = DADDiu $zero_64, 8
+# O32-NEXT: $t1_64 = DADDiu $zero_64, 9
+# O32-NEXT: $t2_64 = DADDiu $zero_64, 10
+# O32-NEXT: $t3_64 = DADDiu $zero_64, 11
+# O32-NEXT: $t4_64 = DADDiu $zero_64, 12
+# O32-NEXT: $t5_64 = DADDiu $zero_64, 13
+# O32-NEXT: $t6_64 = DADDiu $zero_64, 14
+# O32-NEXT: $t7_64 = DADDiu $zero_64, 15
+# NABI-NEXT: $a4_64 = DADDiu $zero_64, 8
+# NABI-NEXT: $a5_64 = DADDiu $zero_64, 9
+# NABI-NEXT: $a6_64 = DADDiu $zero_64, 10
+# NABI-NEXT: $a7_64 = DADDiu $zero_64, 11
+# NABI-NEXT: $t0_64 = DADDiu $zero_64, 12
+# NABI-NEXT: $t1_64 = DADDiu $zero_64, 13
+# NABI-NEXT: $t2_64 = DADDiu $zero_64, 14
+# NABI-NEXT: $t3_64 = DADDiu $zero_64, 15
+# COMMON-NEXT: $f0 = MTC1 $zero
+# COMMON-NEXT: $d0_64 = DMTC1 $zero_64
+# COMMON-NEXT: RetRA
+
+# ASM-LABEL: registers:
+# ASM: # %bb.0:
+# ASM-NEXT: addiu $8, $zero, 8
+# ASM-NEXT: addiu $9, $zero, 9
+# ASM-NEXT: addiu $10, $zero, 10
+# ASM-NEXT: addiu $11, $zero, 11
+# ASM-NEXT: addiu $12, $zero, 12
+# ASM-NEXT: addiu $13, $zero, 13
+# ASM-NEXT: addiu $14, $zero, 14
+# ASM-NEXT: addiu $15, $zero, 15
+# ASM-NEXT: daddiu $8, $zero, 8
+# ASM-NEXT: daddiu $9, $zero, 9
+# ASM-NEXT: daddiu $10, $zero, 10
+# ASM-NEXT: daddiu $11, $zero, 11
+# ASM-NEXT: daddiu $12, $zero, 12
+# ASM-NEXT: daddiu $13, $zero, 13
+# ASM-NEXT: daddiu $14, $zero, 14
+# ASM-NEXT: daddiu $15, $zero, 15
+# ASM-NEXT: mtc1 $zero, $f0
+# ASM-NEXT: jr $ra
+# ASM-NEXT: dmtc1 $zero, $f0
+
+#--- o32.mir
+---
+name: registers
+body: |
+  bb.0:
+    $t0 = ADDiu $zero, 8
+    $t1 = ADDiu $zero, 9
+    $t2 = ADDiu $zero, 10
+    $t3 = ADDiu $zero, 11
+    $t4 = ADDiu $zero, 12
+    $t5 = ADDiu $zero, 13
+    $t6 = ADDiu $zero, 14
+    $t7 = ADDiu $zero, 15
+    $t0_64 = DADDiu $zero_64, 8
+    $t1_64 = DADDiu $zero_64, 9
+    $t2_64 = DADDiu $zero_64, 10
+    $t3_64 = DADDiu $zero_64, 11
+    $t4_64 = DADDiu $zero_64, 12
+    $t5_64 = DADDiu $zero_64, 13
+    $t6_64 = DADDiu $zero_64, 14
+    $t7_64 = DADDiu $zero_64, 15
+    $f0 = MTC1 $zero
+    $d0_64 = DMTC1 $zero_64
+    RetRA
+...
+
+#--- nabi.mir
+---
+name: registers
+body: |
+  bb.0:
+    $a4 = ADDiu $zero, 8
+    $a5 = ADDiu $zero, 9
+    $a6 = ADDiu $zero, 10
+    $a7 = ADDiu $zero, 11
+    $t0 = ADDiu $zero, 12
+    $t1 = ADDiu $zero, 13
+    $t2 = ADDiu $zero, 14
+    $t3 = ADDiu $zero, 15
+    $a4_64 = DADDiu $zero_64, 8
+    $a5_64 = DADDiu $zero_64, 9
+    $a6_64 = DADDiu $zero_64, 10
+    $a7_64 = DADDiu $zero_64, 11
+    $t0_64 = DADDiu $zero_64, 12
+    $t1_64 = DADDiu $zero_64, 13
+    $t2_64 = DADDiu $zero_64, 14
+    $t3_64 = DADDiu $zero_64, 15
+    $f0 = MTC1 $zero
+    $d0_64 = DMTC1 $zero_64
+    RetRA
+...
diff --git a/llvm/test/CodeGen/Mips/msa/emergency-spill.mir b/llvm/test/CodeGen/Mips/msa/emergency-spill.mir
index 0111758018413bd..a14e6efc0b40a4b 100644
--- a/llvm/test/CodeGen/Mips/msa/emergency-spill.mir
+++ b/llvm/test/CodeGen/Mips/msa/emergency-spill.mir
@@ -81,7 +81,7 @@ liveins:
   - { reg: '$a1_64', virtual-reg: '' }
   - { reg: '$a2_64', virtual-reg: '' }
   - { reg: '$a3_64', virtual-reg: '' }
-  - { reg: '$t0_64', virtual-reg: '' }
+  - { reg: '$a4_64', virtual-reg: '' }
 frameInfo:
   isFrameAddressTaken: false
   isReturnAddressTaken: false
@@ -131,7 +131,7 @@ stack:
 constants:
 body:             |
   bb.0.entry:
-    liveins: $a0_64, $a1_64, $a2_64, $a3_64, $t0_64
+    liveins: $a0_64, $a1_64, $a2_64, $a3_64, $a4_64
 
     SD killed $a0_64, %stack.1.a, 0 :: (store (s64) into %ir.1, align 16)
     SD killed $a1_64, %stack.1.a, 8 :: (store (s64) into %ir.2)
@@ -141,7 +141,7 @@ body:             |
     $w1 = LD_B %stack.2.b, 0 :: (dereferenceable load (s128) from %ir.b)
     ST_B killed $w0, %stack.3.a.addr, 0 :: (store (s128) into %ir.a.addr)
     ST_B killed $w1, %stack.4.b.addr, 0 :: (store (s128) into %ir.b.addr)
-    SW $t0, %stack.5.c.addr, 0, implicit killed $t0_64 :: (store (s32) into %ir.c.addr)
+    SW $a4, %stack.5.c.addr, 0, implicit killed $a4_64 :: (store (s32) into %ir.c.addr)
     $at_64 = LEA_ADDiu64 %stack.8, 0
     SD killed $at_64, %stack.6.g, 0 :: (store (s64) into %ir.g)
     $a1_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
@@ -156,14 +156,14 @@ body:             |
     $a1_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $a2_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $a3_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
+    $a4_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
+    $a5_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
+    $a6_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
+    $a7_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $t0_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $t1_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $t2_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $t3_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
-    $t4_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
-    $t5_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
-    $t6_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
-    $t7_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $s0_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $s1_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
     $s2_64 = LD %stack.6.g, 0 :: (dereferenceable load (s64) from %ir.g)
@@ -183,14 +183,14 @@ body:             |
     SD $a1_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $a2_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $a3_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
+    SD $a4_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
+    SD $a5_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
+    SD $a6_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
+    SD $a7_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $t0_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $t1_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $t2_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $t3_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
-    SD $t4_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
-    SD $t5_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
-    SD $t6_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
-    SD $t7_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $s0_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $s1_64, %stack.7.d, 0 :: (store (s64) into %ir.d)
     SD $s2_64, %stack.7.d, 0 :: (store (s64) into %ir.d)



More information about the llvm-commits mailing list