[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:22:38 PDT 2026
https://github.com/FlyGoat updated https://github.com/llvm/llvm-project/pull/228017
>From 6f6bbc79d1c9529502cfbfeeefed3fddd71f8b8c 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] Decouple MIR register names from TableGen names
Preparing the MIPS backend for nanoMIPS requires separating physical
register identities from ABI roles. We want to rename the TableGen
register definitions to ABI-neutral R# names while retaining meaningful
ABI names in MIR for debugging code after register allocation.
Add a TargetRegisterInfo hook for MIR register names and use it in the
printer, parser and register operand diagnostics. Select MIPS GPR names
from the ABI-specific alternate names introduced in #224284, keeping the
_64 suffix to distinguish 64-bit registers from their 32-bit subregisters.
This allows the TableGen definitions to be renamed independently in a
follow-up.
This also fixes the existing use of O32 names in N32/N64 MIR: registers
8-11 are now a4-a7, and registers 12-15 are t0-t3. Update the affected MIR
fixture and test O32, N32 and N64 round-trips, including numeric assembly
operands to check that register identities are preserved.
See the discussion in:
https://github.com/llvm/llvm-project/pull/224284#discussion_r4144494240
---
.../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 46787736073771..5b531881caadd4 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 7b45d028efdd77..e879982b9de85f 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 79b01d27d91a5b..bfe31e1f2b9ad0 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 d68ab86dd0efed..0785aa1bb7906b 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 80ba23d173cbca..0096b239dd8ff6 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 00000000000000..00597f0c6ad647
--- /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 0111758018413b..a14e6efc0b40a4 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