[llvm] [Mips] Introduce ABI-specific register names and accessors (PR #224284)
Jiaxun Yang via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 02:03:25 PDT 2026
https://github.com/FlyGoat updated https://github.com/llvm/llvm-project/pull/224284
>From ed08d2e2959c117764a0eff0c0f794d2582e2859 Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Thu, 17 Sep 2026 13:30:19 +0100
Subject: [PATCH 1/2] [Mips] Introduce ABI-specific register names and
accessors
To accommodate the P32/P64 ABIs, we need to separate machine registers
from ABI register names and calling-convention roles. The existing
register IDs use OABI names, even when another ABI assigns a different
role to the same physical register.
As a first step, describe OABI, NABI and PABI names with RegAltNameIndices.
Extend TableGen's AsmMatcherEmitter with the opt-in
ShouldEmitMatchRegisterAltNameWithIndex flag, which generates
MatchRegisterAltName(StringRef, unsigned AltIdx). It matches only names
associated with the selected index, allowing the same spelling to identify
different registers across ABIs.
Use the indexed matcher in shared MIPS register lookup for the assembler
and named-register lowering, retaining compatibility aliases and
diagnostics for deprecated spellings.
Add ABI accessors for argument, temporary, saved and return registers,
backed by shared register lists, and use them in lowering code. Keep the
existing register IDs and assembly/MIR spellings for now, with a TODO for
ABI-independent IDs.
---
llvm/include/llvm/Target/Target.td | 5 +
.../Target/Mips/AsmParser/MipsAsmParser.cpp | 117 ++----------
.../Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 137 ++++++++++++--
.../Target/Mips/MCTargetDesc/MipsABIInfo.h | 26 +++
.../Mips/MCTargetDesc/MipsInstPrinter.h | 4 +-
.../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 71 +++++++
.../Mips/MCTargetDesc/MipsMCTargetDesc.h | 9 +
llvm/lib/Target/Mips/Mips.td | 3 +-
llvm/lib/Target/Mips/MipsFastISel.cpp | 20 +-
llvm/lib/Target/Mips/MipsISelLowering.cpp | 123 +++---------
llvm/lib/Target/Mips/MipsISelLowering.h | 6 +-
llvm/lib/Target/Mips/MipsMachineFunction.cpp | 18 +-
llvm/lib/Target/Mips/MipsOptimizePICCall.cpp | 3 +-
llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 2 +-
llvm/lib/Target/Mips/MipsRegisterInfo.td | 179 ++++++++++--------
llvm/lib/Target/Mips/MipsSEFrameLowering.cpp | 4 +-
llvm/lib/Target/Mips/MipsSEInstrInfo.cpp | 2 +-
.../CodeGen/Mips/named-register-aliases.ll | 33 ++++
.../MC/Mips/mips-register-names-invalid.s | 28 ++-
.../MC/Mips/mips64-register-names-n32-n64.s | 4 +-
.../TableGen/MatchRegisterAltNameWithIndex.td | 60 ++++++
llvm/utils/TableGen/AsmMatcherEmitter.cpp | 63 ++++--
22 files changed, 577 insertions(+), 340 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/named-register-aliases.ll
create mode 100644 llvm/test/TableGen/MatchRegisterAltNameWithIndex.td
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 279de17d00da5..0b9252aaa30e2 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1843,6 +1843,11 @@ class AsmParser {
// several registers share the same alias (i.e. not a 1:1 mapping).
bit ShouldEmitMatchRegisterAltName = false;
+ // Generate MatchRegisterAltName(StringRef Name, unsigned AltIdx), matching
+ // only explicit names for AltIdx, without fallback. Duplicate names are
+ // checked per index, subject to AllowDuplicateRegisterNames.
+ bit ShouldEmitMatchRegisterAltNameWithIndex = false;
+
// Set to true if MatchRegisterName and MatchRegisterAltName functions
// should be generated even if there are duplicate register names. The
// target is responsible for coercing aliased registers as necessary
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 0fe6b95e71148..2104e76fccc5c 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -9,6 +9,7 @@
#include "MCTargetDesc/MipsABIFlagsSection.h"
#include "MCTargetDesc/MipsABIInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsInstPrinter.h"
#include "MCTargetDesc/MipsMCAsmInfo.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "MCTargetDesc/MipsTargetStreamer.h"
@@ -6152,95 +6153,27 @@ MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
}
int MipsAsmParser::matchCPURegisterName(StringRef Name) {
- int CC;
-
- CC = StringSwitch<unsigned>(Name)
- .Case("zero", 0)
- .Cases({"at", "AT"}, 1)
- .Case("a0", 4)
- .Case("a1", 5)
- .Case("a2", 6)
- .Case("a3", 7)
- .Case("v0", 2)
- .Case("v1", 3)
- .Case("s0", 16)
- .Case("s1", 17)
- .Case("s2", 18)
- .Case("s3", 19)
- .Case("s4", 20)
- .Case("s5", 21)
- .Case("s6", 22)
- .Case("s7", 23)
- .Case("k0", 26)
- .Case("k1", 27)
- .Case("gp", 28)
- .Case("sp", 29)
- .Case("fp", 30)
- .Case("s8", 30)
- .Case("ra", 31)
- .Case("t0", 8)
- .Case("t1", 9)
- .Case("t2", 10)
- .Case("t3", 11)
- .Case("t4", 12)
- .Case("t5", 13)
- .Case("t6", 14)
- .Case("t7", 15)
- .Case("t8", 24)
- .Case("t9", 25)
- .Default(-1);
-
- if (!(isABI_N32() || isABI_N64()))
- return CC;
-
- if (12 <= CC && CC <= 15) {
- // Name is one of t4-t7
+ const MCRegisterInfo &MRI = *getContext().getRegisterInfo();
+ bool IsDeprecated;
+ int Index = MIPS_MC::getCPURegisterIndex(Name, MRI, ABI.getRegAltNameIndex(),
+ &IsDeprecated);
+ if (IsDeprecated) {
+ MCRegister Reg = MRI.getRegClass(Mips::GPR32RegClassID).getRegister(Index);
AsmToken RegTok = getLexer().peekTok();
- SMRange RegRange = RegTok.getLocRange();
-
- StringRef FixedName = StringSwitch<StringRef>(Name)
- .Case("t4", "t0")
- .Case("t5", "t1")
- .Case("t6", "t2")
- .Case("t7", "t3")
- .Default("");
- assert(FixedName != "" && "Register name is not one of t4-t7.");
-
+ StringRef FixedName =
+ MipsInstPrinter::getRegisterName(Reg, ABI.getRegAltNameIndex());
printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
- "Did you mean $" + FixedName + "?", RegRange);
+ "Did you mean $" + FixedName + "?",
+ RegTok.getLocRange());
}
-
- // Although SGI documentation just cuts out t0-t3 for n32/n64,
- // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
- // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
- if (8 <= CC && CC <= 11)
- CC += 4;
-
- if (CC == -1)
- CC = StringSwitch<unsigned>(Name)
- .Case("a4", 8)
- .Case("a5", 9)
- .Case("a6", 10)
- .Case("a7", 11)
- .Case("kt0", 26)
- .Case("kt1", 27)
- .Default(-1);
-
- return CC;
+ return Index;
}
int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
- int CC;
-
- CC = StringSwitch<unsigned>(Name)
- .Case("hwr_cpunum", 0)
- .Case("hwr_synci_step", 1)
- .Case("hwr_cc", 2)
- .Case("hwr_ccres", 3)
- .Case("hwr_ulr", 29)
- .Default(-1);
-
- return CC;
+ const MCRegisterInfo &MRI = *getContext().getRegisterInfo();
+ MCRegister Reg = MIPS_MC::matchRegisterName(Name, MRI, Mips::HWRegsRegClassID,
+ Mips::RegAliasName);
+ return Reg ? MRI.getEncodingValue(Reg) : -1;
}
int MipsAsmParser::matchFPURegisterName(StringRef Name) {
@@ -6295,20 +6228,10 @@ int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
}
int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
- int CC;
-
- CC = StringSwitch<unsigned>(Name)
- .Case("msair", 0)
- .Case("msacsr", 1)
- .Case("msaaccess", 2)
- .Case("msasave", 3)
- .Case("msamodify", 4)
- .Case("msarequest", 5)
- .Case("msamap", 6)
- .Case("msaunmap", 7)
- .Default(-1);
-
- return CC;
+ const MCRegisterInfo &MRI = *getContext().getRegisterInfo();
+ MCRegister Reg = MIPS_MC::matchRegisterName(
+ Name, MRI, Mips::MSACtrlRegClassID, Mips::RegAliasName);
+ return Reg ? MRI.getEncodingValue(Reg) : -1;
}
bool MipsAsmParser::canUseATReg() {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
index 59c8e7c72224e..f45df26ef65f7 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
@@ -26,18 +26,129 @@ cl::opt<bool>
cl::init(false));
namespace {
-static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3};
-
-static const MCPhysReg Mips64IntRegs[8] = {
+static constexpr MCPhysReg O32IntRegs[] = {Mips::A0, Mips::A1, Mips::A2,
+ Mips::A3};
+static constexpr MCPhysReg NABIIntRegs[] = {Mips::A0, Mips::A1, Mips::A2,
+ Mips::A3, Mips::T0, Mips::T1,
+ Mips::T2, Mips::T3};
+static constexpr MCPhysReg Mips64IntRegs[] = {
Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64};
+
+struct GPR {
+ MCPhysReg Reg32;
+ MCPhysReg Reg64;
+};
+
+static constexpr GPR OABITempRegs[] = {
+ {Mips::T0, Mips::T0_64}, {Mips::T1, Mips::T1_64}, {Mips::T2, Mips::T2_64},
+ {Mips::T3, Mips::T3_64}, {Mips::T4, Mips::T4_64}, {Mips::T5, Mips::T5_64},
+ {Mips::T6, Mips::T6_64}, {Mips::T7, Mips::T7_64}, {Mips::T8, Mips::T8_64},
+ {Mips::T9, Mips::T9_64},
+};
+
+static constexpr GPR NABITempRegs[] = {
+ {Mips::T4, Mips::T4_64},
+ {Mips::T5, Mips::T5_64},
+ {Mips::T6, Mips::T6_64},
+ {Mips::T7, Mips::T7_64},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::T8, Mips::T8_64},
+ {Mips::T9, Mips::T9_64},
+};
+
+static constexpr GPR PABITempRegs[] = {
+ {Mips::T4, Mips::T4_64},
+ {Mips::T5, Mips::T5_64},
+ {Mips::T6, Mips::T6_64},
+ {Mips::T7, Mips::T7_64},
+ {Mips::V0, Mips::V0_64},
+ {Mips::V1, Mips::V1_64},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::NoRegister, Mips::NoRegister},
+ {Mips::T8, Mips::T8_64},
+ {Mips::T9, Mips::T9_64},
+};
+
+static constexpr GPR SavedRegs[] = {
+ {Mips::S0, Mips::S0_64}, {Mips::S1, Mips::S1_64}, {Mips::S2, Mips::S2_64},
+ {Mips::S3, Mips::S3_64}, {Mips::S4, Mips::S4_64}, {Mips::S5, Mips::S5_64},
+ {Mips::S6, Mips::S6_64}, {Mips::S7, Mips::S7_64},
+};
+
+static constexpr GPR ReturnRegs[] = {
+ {Mips::V0, Mips::V0_64},
+ {Mips::V1, Mips::V1_64},
+};
+
+MCRegister getReg(ArrayRef<GPR> Regs, unsigned I, bool Is64Bit) {
+ assert(I < Regs.size() && "Invalid ABI register index");
+ MCRegister Reg = Is64Bit ? Regs[I].Reg64 : Regs[I].Reg32;
+ assert(Reg && "Register name is not defined by this ABI");
+ return Reg;
+}
+} // namespace
+
+ArrayRef<MCPhysReg> MipsABIInfo::getArgRegs(bool Is64Bit) const {
+ assert(IsKnown() && "Unknown ABI");
+ if (Is64Bit)
+ return ArrayRef(Mips64IntRegs).take_front(IsO32() ? 4 : 8);
+ return IsO32() ? ArrayRef(O32IntRegs) : ArrayRef(NABIIntRegs);
}
ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const {
- if (IsO32())
- return ArrayRef(O32IntRegs);
- if (IsN32() || IsN64())
- return ArrayRef(Mips64IntRegs);
+ return getArgRegs(AreGprs64bit());
+}
+
+unsigned MipsABIInfo::getRegAltNameIndex() const {
+ switch (ThisABI) {
+ case ABI::O32:
+ return Mips::OABIRegAltName;
+ case ABI::N32:
+ case ABI::N64:
+ return Mips::NABIRegAltName;
+ case ABI::Unknown:
+ llvm_unreachable("Unknown ABI");
+ }
+ llvm_unreachable("Unhandled ABI");
+}
+
+MCRegister MipsABIInfo::getArgReg(unsigned I, bool Is64Bit) const {
+ ArrayRef<MCPhysReg> Regs = getArgRegs(Is64Bit);
+ assert(I < Regs.size() && "Invalid argument register");
+ return Regs[I];
+}
+
+MCRegister MipsABIInfo::getTempReg(unsigned I, bool Is64Bit) const {
+ switch (getRegAltNameIndex()) {
+ case Mips::OABIRegAltName:
+ return getReg(OABITempRegs, I, Is64Bit);
+ case Mips::NABIRegAltName:
+ return getReg(NABITempRegs, I, Is64Bit);
+ case Mips::PABIRegAltName:
+ return getReg(PABITempRegs, I, Is64Bit);
+ default:
+ llvm_unreachable("Unknown register naming convention");
+ }
+}
+
+MCRegister MipsABIInfo::getSavedReg(unsigned I, bool Is64Bit) const {
+ assert(IsKnown() && "Unknown ABI");
+ return getReg(SavedRegs, I, Is64Bit);
+}
+
+MCRegister MipsABIInfo::getReturnReg(unsigned I, bool Is64Bit) const {
+ switch (ThisABI) {
+ case ABI::O32:
+ case ABI::N32:
+ case ABI::N64:
+ return getReg(ReturnRegs, I, Is64Bit);
+ case ABI::Unknown:
+ llvm_unreachable("Unknown ABI");
+ }
llvm_unreachable("Unhandled ABI");
}
@@ -86,7 +197,7 @@ unsigned MipsABIInfo::GetFramePtr() const {
}
unsigned MipsABIInfo::GetBasePtr() const {
- return ArePtrs64bit() ? Mips::S7_64 : Mips::S7;
+ return getSavedReg(7, ArePtrs64bit());
}
unsigned MipsABIInfo::GetGlobalPtr() const {
@@ -122,12 +233,6 @@ unsigned MipsABIInfo::GetGPRMoveOp() const {
}
unsigned MipsABIInfo::GetEhDataReg(unsigned I) const {
- static const unsigned EhDataReg[] = {
- Mips::A0, Mips::A1, Mips::A2, Mips::A3
- };
- static const unsigned EhDataReg64[] = {
- Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64
- };
-
- return IsN64() ? EhDataReg64[I] : EhDataReg[I];
+ assert(I < 4 && "Invalid EH data register");
+ return getArgReg(I, ArePtrs64bit());
}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
index d8003d2fcc164..a5a4e89e1331d 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
@@ -41,6 +41,32 @@ class MipsABIInfo {
bool IsN64() const { return ThisABI == ABI::N64; }
ABI GetEnumValue() const { return ThisABI; }
+ /// Register naming convention for this ABI.
+ unsigned getRegAltNameIndex() const;
+
+ /// Integer argument registers in calling-convention order.
+ ArrayRef<MCPhysReg> getArgRegs(bool Is64Bit) const;
+
+ /// ABI register accessors default to the ABI's GPR width.
+ MCRegister getArgReg(unsigned I, bool Is64Bit) const;
+ MCRegister getArgReg(unsigned I) const {
+ return getArgReg(I, AreGprs64bit());
+ }
+ /// I is the suffix in tI (NABI has t0-t3 and t8-t9).
+ MCRegister getTempReg(unsigned I, bool Is64Bit) const;
+ MCRegister getTempReg(unsigned I) const {
+ return getTempReg(I, AreGprs64bit());
+ }
+ MCRegister getSavedReg(unsigned I, bool Is64Bit) const;
+ MCRegister getSavedReg(unsigned I) const {
+ return getSavedReg(I, AreGprs64bit());
+ }
+ /// Integer return-value registers.
+ MCRegister getReturnReg(unsigned I, bool Is64Bit) const;
+ MCRegister getReturnReg(unsigned I) const {
+ return getReturnReg(I, AreGprs64bit());
+ }
+
/// The registers to use for byval arguments.
ArrayRef<MCPhysReg> GetByValArgRegs() const;
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
index 3924cf02e2d6b..df540ddf28051 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
@@ -12,6 +12,7 @@
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H
+#include "MipsMCTargetDesc.h"
#include "llvm/MC/MCInstPrinter.h"
namespace llvm {
@@ -83,7 +84,8 @@ class MipsInstPrinter : public MCInstPrinter {
getMnemonic(const MCInst &MI) const override;
void printInstruction(const MCInst *MI, uint64_t Address,
const MCSubtargetInfo &STI, raw_ostream &O);
- static const char *getRegisterName(MCRegister Reg);
+ static const char *getRegisterName(MCRegister Reg,
+ unsigned AltIdx = Mips::NoRegAltName);
void printRegName(raw_ostream &OS, MCRegister Reg) override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index ef73fd3288836..fb4cff6b25a1b 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -45,6 +45,77 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"
+#define GET_REGISTER_MATCHER
+#include "MipsGenAsmMatcher.inc"
+
+MCRegister MIPS_MC::matchRegisterName(StringRef Name, const MCRegisterInfo &MRI,
+ unsigned RegClassID, unsigned AltIdx) {
+ MCRegister Reg = MatchRegisterAltName(Name, AltIdx);
+ if (!Reg)
+ Reg = MatchRegisterName(Name);
+ if (!Reg)
+ return MCRegister();
+
+ const MCRegisterClass &RC = MRI.getRegClass(RegClassID);
+ // GPR32 and GPR64 share names; select the requested width.
+ if (!RC.contains(Reg)) {
+ if (RegClassID == Mips::GPR32RegClassID &&
+ MRI.getRegClass(Mips::GPR64RegClassID).contains(Reg))
+ Reg = MRI.getSubReg(Reg, Mips::sub_32);
+ else if (RegClassID == Mips::GPR64RegClassID &&
+ MRI.getRegClass(Mips::GPR32RegClassID).contains(Reg))
+ Reg = MRI.getMatchingSuperReg(Reg, Mips::sub_32, &RC);
+ }
+ return RC.contains(Reg) ? Reg : MCRegister();
+}
+
+int MIPS_MC::getCPURegisterIndex(StringRef Name, const MCRegisterInfo &MRI,
+ unsigned AltIdx, bool *IsDeprecated) {
+ if (IsDeprecated)
+ *IsDeprecated = false;
+
+ if (MCRegister Reg =
+ matchRegisterName(Name, MRI, Mips::GPR32RegClassID, AltIdx))
+ return MRI.getEncodingValue(Reg);
+
+ static const struct {
+ StringLiteral Name;
+ MCPhysReg Reg;
+ // NoRegAltName applies to all ABIs.
+ unsigned AltIdx;
+ } Aliases[] = {
+ {"AT", Mips::AT, Mips::NoRegAltName},
+ {"s8", Mips::FP, Mips::NoRegAltName},
+ {"kt0", Mips::K0, Mips::NABIRegAltName},
+ {"kt1", Mips::K1, Mips::NABIRegAltName},
+ };
+ for (const auto &Alias : Aliases)
+ if (Name == Alias.Name &&
+ (Alias.AltIdx == Mips::NoRegAltName || Alias.AltIdx == AltIdx))
+ return MRI.getEncodingValue(Alias.Reg);
+
+ // GNU also accepts t4-t7 for NABI's t0-t3.
+ if (AltIdx == Mips::NABIRegAltName) {
+ static const struct {
+ StringLiteral Name;
+ MCPhysReg Reg;
+ } Deprecated[] = {
+ {"t4", Mips::T4},
+ {"t5", Mips::T5},
+ {"t6", Mips::T6},
+ {"t7", Mips::T7},
+ };
+ for (const auto &Alias : Deprecated) {
+ if (Name == Alias.Name) {
+ if (IsDeprecated)
+ *IsDeprecated = true;
+ return MRI.getEncodingValue(Alias.Reg);
+ }
+ }
+ }
+ return -1;
+}
+
void MIPS_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {
// Mapping from CodeView to MC register id.
static const struct {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
index f3e3e6e8d1073..db9b4bf233353 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
@@ -24,6 +24,7 @@ class MCContext;
class MCInstrInfo;
class MCObjectTargetWriter;
class MCObjectWriter;
+class MCRegister;
class MCRegisterInfo;
class MCStreamer;
class MCSubtargetInfo;
@@ -60,6 +61,14 @@ namespace MIPS_MC {
void initLLVMToCVRegMapping(MCRegisterInfo *MRI);
StringRef selectMipsCPU(const Triple &TT, StringRef CPU);
+
+/// Match a symbolic name in RegClassID, or return an invalid register.
+MCRegister matchRegisterName(StringRef Name, const MCRegisterInfo &MRI,
+ unsigned RegClassID, unsigned AltIdx);
+
+/// Return a GPR name's hardware index, or -1 if unknown.
+int getCPURegisterIndex(StringRef Name, const MCRegisterInfo &MRI,
+ unsigned AltIdx, bool *IsDeprecated = nullptr);
}
} // End llvm namespace
diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td
index 3b78de8ec43ad..c6c3db7ca6dcc 100644
--- a/llvm/lib/Target/Mips/Mips.td
+++ b/llvm/lib/Target/Mips/Mips.td
@@ -313,7 +313,8 @@ def : ProcessorModel<"i6400", MipsI6400Model, [ImplI6400]>;
def : ProcessorModel<"i6500", MipsI6400Model, [ImplI6500]>;
def MipsAsmParser : AsmParser {
- let ShouldEmitMatchRegisterName = 0;
+ let ShouldEmitMatchRegisterAltNameWithIndex = 1;
+ let AllowDuplicateRegisterNames = 1;
}
def MipsAsmParserVariant : AsmParserVariant {
diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp
index e50ddb0679a23..600402152f7ec 100644
--- a/llvm/lib/Target/Mips/MipsFastISel.cpp
+++ b/llvm/lib/Target/Mips/MipsFastISel.cpp
@@ -1196,16 +1196,16 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
VA.isMemLoc()) {
switch (VA.getLocMemOffset()) {
case 0:
- VA.convertToReg(Mips::A0);
+ VA.convertToReg(getABI().getArgReg(0, false));
break;
case 4:
- VA.convertToReg(Mips::A1);
+ VA.convertToReg(getABI().getArgReg(1, false));
break;
case 8:
- VA.convertToReg(Mips::A2);
+ VA.convertToReg(getABI().getArgReg(2, false));
break;
case 12:
- VA.convertToReg(Mips::A3);
+ VA.convertToReg(getABI().getArgReg(3, false));
break;
default:
break;
@@ -1341,8 +1341,7 @@ bool MipsFastISel::fastLowerArguments() {
return false;
}
- std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2,
- Mips::A3}};
+ ArrayRef<MCPhysReg> GPR32ArgRegs = getABI().getArgRegs(false);
std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}};
std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}};
auto NextGPR32 = GPR32ArgRegs.begin();
@@ -1567,10 +1566,11 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
DestAddress = materializeExternalCallSym(Symbol);
else
DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32);
- emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress);
- MachineInstrBuilder MIB =
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Mips::JALR),
- Mips::RA).addReg(Mips::T9);
+ emitInst(TargetOpcode::COPY, getABI().getTempReg(9, false))
+ .addReg(DestAddress);
+ MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(Mips::JALR), Mips::RA)
+ .addReg(getABI().getTempReg(9, false));
// Add implicit physical register uses to the call.
for (auto Reg : CLI.OutRegs)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index a75960fd2af76..b9d9f079f1511 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -27,7 +27,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
@@ -2706,8 +2705,8 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG)
// Store stack offset in V1, store jump target in V0. Glue CopyToReg and
// EH_RETURN nodes, so that instructions are emitted back-to-back.
- unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1;
- unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0;
+ unsigned OffsetReg = ABI.getReturnReg(1, ABI.ArePtrs64bit());
+ unsigned AddrReg = ABI.getReturnReg(0, ABI.ArePtrs64bit());
Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue());
Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1));
return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain,
@@ -3054,11 +3053,11 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>(
State.getMachineFunction().getSubtarget());
- static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 };
+ ArrayRef<MCPhysReg> IntRegs = MipsABIInfo::O32().getArgRegs(false);
static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 };
- static const MCPhysReg FloatVectorIntRegs[] = { Mips::A0, Mips::A2 };
+ static const MCPhysReg FloatVectorIntRegs[] = {Mips::A0, Mips::A2};
// Do not process byval args here.
if (ArgFlags.isByVal())
@@ -4102,7 +4101,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
llvm_unreachable("sret virtual register not created in the entry block");
SDValue Val =
DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout()));
- unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0;
+ unsigned V0 = ABI.getReturnReg(0, ABI.ArePtrs64bit());
Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Glue);
Glue = Chain.getValue(1);
@@ -4260,36 +4259,29 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const {
if (!R.first)
return std::make_pair(0U, nullptr);
- if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo.
- // No numeric characters follow "hi" or "lo".
- if (R.second)
- return std::make_pair(0U, nullptr);
+ for (unsigned RegClassID : {Mips::HI32RegClassID, Mips::LO32RegClassID}) {
+ if (MCRegister NamedReg = MIPS_MC::matchRegisterName(
+ Prefix, *TRI, RegClassID, Mips::RegAliasName)) {
+ // No numeric characters follow a hi/lo register name.
+ if (R.second)
+ return std::make_pair(0U, nullptr);
+ return std::make_pair(NamedReg.id(), TRI->getRegClass(RegClassID));
+ }
+ }
- RC = TRI->getRegClass(Prefix == "hi" ?
- Mips::HI32RegClassID : Mips::LO32RegClassID);
- return std::make_pair(*(RC->begin()), RC);
- } else if (Prefix.starts_with("$msa")) {
+ if (Prefix.starts_with("$msa")) {
// Parse $msa(ir|csr|access|save|modify|request|map|unmap)
// No numeric characters follow the name.
if (R.second)
return std::make_pair(0U, nullptr);
- Reg = StringSwitch<unsigned long long>(Prefix)
- .Case("$msair", Mips::MSAIR)
- .Case("$msacsr", Mips::MSACSR)
- .Case("$msaaccess", Mips::MSAAccess)
- .Case("$msasave", Mips::MSASave)
- .Case("$msamodify", Mips::MSAModify)
- .Case("$msarequest", Mips::MSARequest)
- .Case("$msamap", Mips::MSAMap)
- .Case("$msaunmap", Mips::MSAUnmap)
- .Default(0);
-
+ RC = TRI->getRegClass(Mips::MSACtrlRegClassID);
+ Reg = MIPS_MC::matchRegisterName(
+ Prefix.drop_front(), *TRI, Mips::MSACtrlRegClassID, Mips::RegAliasName);
if (!Reg)
return std::make_pair(0U, nullptr);
- RC = TRI->getRegClass(Mips::MSACtrlRegClassID);
return std::make_pair(Reg, RC);
}
@@ -4375,9 +4367,11 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
break;
case 'c': // register suitable for indirect jump
if (VT == MVT::i32)
- return std::make_pair((unsigned)Mips::T9, &Mips::GPR32RegClass);
+ return std::make_pair(ABI.getTempReg(9, false).id(),
+ &Mips::GPR32RegClass);
if (VT == MVT::i64)
- return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass);
+ return std::make_pair(ABI.getTempReg(9, true).id(),
+ &Mips::GPR64RegClass);
// This will generate an error message
return std::make_pair(0U, nullptr);
case 'l': // use the `lo` register to store values
@@ -4969,71 +4963,6 @@ MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI,
return BB;
}
-// Copies the function MipsAsmParser::matchCPURegisterName.
-int MipsTargetLowering::getCPURegisterIndex(StringRef Name) const {
- int CC;
-
- CC = StringSwitch<unsigned>(Name)
- .Case("zero", 0)
- .Case("at", 1)
- .Case("AT", 1)
- .Case("a0", 4)
- .Case("a1", 5)
- .Case("a2", 6)
- .Case("a3", 7)
- .Case("v0", 2)
- .Case("v1", 3)
- .Case("s0", 16)
- .Case("s1", 17)
- .Case("s2", 18)
- .Case("s3", 19)
- .Case("s4", 20)
- .Case("s5", 21)
- .Case("s6", 22)
- .Case("s7", 23)
- .Case("k0", 26)
- .Case("k1", 27)
- .Case("gp", 28)
- .Case("sp", 29)
- .Case("fp", 30)
- .Case("s8", 30)
- .Case("ra", 31)
- .Case("t0", 8)
- .Case("t1", 9)
- .Case("t2", 10)
- .Case("t3", 11)
- .Case("t4", 12)
- .Case("t5", 13)
- .Case("t6", 14)
- .Case("t7", 15)
- .Case("t8", 24)
- .Case("t9", 25)
- .Default(-1);
-
- if (!(ABI.IsN32() || ABI.IsN64()))
- return CC;
-
- // Although SGI documentation just cuts out t0-t3 for n32/n64,
- // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
- // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
- if (8 <= CC && CC <= 11)
- CC += 4;
-
- if (CC == -1)
- CC = StringSwitch<unsigned>(Name)
- .Case("a4", 8)
- .Case("a5", 9)
- .Case("a6", 10)
- .Case("a7", 11)
- .Case("kt0", 26)
- .Case("kt1", 27)
- .Default(-1);
-
- return CC;
-}
-
-// FIXME? Maybe this could be a TableGen attribute on some registers and
-// this table could be generated automatically from RegInfo.
Register
MipsTargetLowering::getRegisterByName(const char *RegName, LLT VT,
const MachineFunction &MF) const {
@@ -5043,11 +4972,13 @@ MipsTargetLowering::getRegisterByName(const char *RegName, LLT VT,
unsigned RegIdx;
if (Name.getAsInteger(10, RegIdx)) {
std::string LowerName = Name.lower();
- int NamedRegIdx = getCPURegisterIndex(LowerName);
- if (NamedRegIdx < 0)
+ const MCRegisterInfo &MRI = *MF.getContext().getRegisterInfo();
+ int Index =
+ MIPS_MC::getCPURegisterIndex(LowerName, MRI, ABI.getRegAltNameIndex());
+ if (Index < 0)
report_fatal_error(
Twine("Invalid register name \"" + StringRef(RegName) + "\"."));
- RegIdx = NamedRegIdx;
+ RegIdx = Index;
}
if (RegIdx < 32) {
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 68272cb403b36..57ebd3619ed78 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -146,7 +146,7 @@ using TargetRegisterClass = MCRegisterClass;
Register
getExceptionPointerRegister(ExceptionHandling EH,
const Constant *PersonalityFn) const override {
- return ABI.IsN64() ? Mips::A0_64 : Mips::A0;
+ return ABI.getArgReg(0, ABI.ArePtrs64bit());
}
/// If a physical register, this returns the register that receives the
@@ -154,7 +154,7 @@ using TargetRegisterClass = MCRegisterClass;
Register
getExceptionSelectorRegister(ExceptionHandling EH,
const Constant *PersonalityFn) const override {
- return ABI.IsN64() ? Mips::A1_64 : Mips::A1;
+ return ABI.getArgReg(1, ABI.ArePtrs64bit());
}
bool isJumpTableRelative() const override {
@@ -508,8 +508,6 @@ using TargetRegisterClass = MCRegisterClass;
return true;
}
- int getCPURegisterIndex(StringRef Name) const;
-
ArrayRef<MCPhysReg> getRoundingControlRegisters() const override;
/// Emit a sign-extension using sll/sra, seb, or seh appropriately.
diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/llvm/lib/Target/Mips/MipsMachineFunction.cpp
index 194b467fb1d8b..83bedafd58ce5 100644
--- a/llvm/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/llvm/lib/Target/Mips/MipsMachineFunction.cpp
@@ -84,9 +84,11 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
Register V0 = RegInfo.createVirtualRegister(RC);
Register V1 = RegInfo.createVirtualRegister(RC);
+ MCRegister T9 = ABI.getTempReg(9, ABI.ArePtrs64bit());
+
if (ABI.IsN64()) {
- MF.getRegInfo().addLiveIn(Mips::T9_64);
- MBB.addLiveIn(Mips::T9_64);
+ MF.getRegInfo().addLiveIn(T9);
+ MBB.addLiveIn(T9);
// lui $v0, %hi(%neg(%gp_rel(fname)))
// daddu $v1, $v0, $t9
@@ -94,8 +96,7 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
const GlobalValue *FName = &MF.getFunction();
BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
- BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
- .addReg(Mips::T9_64);
+ BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0).addReg(T9);
BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
return;
@@ -113,8 +114,8 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
return;
}
- MF.getRegInfo().addLiveIn(Mips::T9);
- MBB.addLiveIn(Mips::T9);
+ MF.getRegInfo().addLiveIn(T9);
+ MBB.addLiveIn(T9);
if (ABI.IsN32()) {
// lui $v0, %hi(%neg(%gp_rel(fname)))
@@ -123,7 +124,7 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
const GlobalValue *FName = &MF.getFunction();
BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
- BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
+ BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(T9);
BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
return;
@@ -151,7 +152,8 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
MF.getRegInfo().addLiveIn(Mips::V0);
MBB.addLiveIn(Mips::V0);
BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
- .addReg(Mips::V0).addReg(Mips::T9);
+ .addReg(Mips::V0)
+ .addReg(T9);
}
void MipsFunctionInfo::createEhDataRegsFI(MachineFunction &MF) {
diff --git a/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp b/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
index 7ceb97642bba1..901b675e27aa8 100644
--- a/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
+++ b/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp
@@ -151,7 +151,8 @@ static void setCallTargetReg(MachineBasicBlock *MBB,
MachineFunction &MF = *MBB->getParent();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register SrcReg = I->getOperand(0).getReg();
- unsigned DstReg = getRegTy(SrcReg, MF) == MVT::i32 ? Mips::T9 : Mips::T9_64;
+ MCRegister DstReg = MF.getSubtarget<MipsSubtarget>().getABI().getTempReg(
+ 9, getRegTy(SrcReg, MF) != MVT::i32);
BuildMI(*MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg)
.addReg(SrcReg);
I->getOperand(0).setReg(DstReg);
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index ed5f2d48902f2..e45ae0e9458bb 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -316,7 +316,7 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64;
- unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64;
+ unsigned BP = Subtarget.getABI().getSavedReg(7, Subtarget.isGP64bit());
// Support dynamic stack realignment for all targets except Mips16.
if (Subtarget.inMips16Mode())
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.td b/llvm/lib/Target/Mips/MipsRegisterInfo.td
index 765179a43980d..a1c775060786d 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.td
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.td
@@ -19,6 +19,14 @@ def sub_dsp20 : SubRegIndex<1, 20>;
def sub_dsp21 : SubRegIndex<1, 21>;
def sub_dsp22 : SubRegIndex<1, 22>;
def sub_dsp23 : SubRegIndex<1, 23>;
+
+let FallbackRegAltNameIndex = NoRegAltName in {
+def OABIRegAltName : RegAltNameIndex;
+def NABIRegAltName : RegAltNameIndex;
+def PABIRegAltName : RegAltNameIndex;
+// Assembler and named-register aliases.
+def RegAliasName : RegAltNameIndex;
+}
}
class Unallocatable {
@@ -31,6 +39,11 @@ class MipsReg<bits<16> Enc, string n> : Register<n> {
let Namespace = "Mips";
}
+class MipsRegAlias<string alias> {
+ list<RegAltNameIndex> RegAltNameIndices = [RegAliasName];
+ list<string> AltNames = [alias];
+}
+
class MipsRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
: RegisterWithSubRegs<n, subregs> {
let HWEncoding = Enc;
@@ -38,12 +51,18 @@ class MipsRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
}
// Mips CPU Registers.
-class MipsGPRReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+class MipsGPRReg<bits<16> Enc, string n, string oabi,
+ string nabi = oabi, string pabi = nabi> : MipsReg<Enc, n> {
+ let RegAltNameIndices = [OABIRegAltName, NABIRegAltName, PABIRegAltName];
+ let AltNames = [oabi, nabi, pabi];
+}
// Mips 64-bit CPU Registers
-class Mips64GPRReg<bits<16> Enc, string n, list<Register> subregs>
- : MipsRegWithSubRegs<Enc, n, subregs> {
+class Mips64GPRReg<MipsGPRReg subreg>
+ : MipsRegWithSubRegs<subreg.HWEncoding, subreg.AsmName, [subreg]> {
let SubRegIndices = [sub_32];
+ let RegAltNameIndices = subreg.RegAltNameIndices;
+ let AltNames = subreg.AltNames;
}
// Mips 32-bit FPU Registers
@@ -84,74 +103,76 @@ class HWR<bits<16> Enc, string n> : MipsReg<Enc, n>;
let Namespace = "Mips" in {
// General Purpose Registers
+ // TODO: Use R0-R31/R0_64-R31_64 record names without changing MIR names.
+ // Use MipsABIInfo accessors for ABI roles.
let isConstant = true in
- def ZERO : MipsGPRReg< 0, "zero">, DwarfRegNum<[0]>;
- def AT : MipsGPRReg< 1, "1">, DwarfRegNum<[1]>;
- def V0 : MipsGPRReg< 2, "2">, DwarfRegNum<[2]>;
- def V1 : MipsGPRReg< 3, "3">, DwarfRegNum<[3]>;
- def A0 : MipsGPRReg< 4, "4">, DwarfRegNum<[4]>;
- def A1 : MipsGPRReg< 5, "5">, DwarfRegNum<[5]>;
- def A2 : MipsGPRReg< 6, "6">, DwarfRegNum<[6]>;
- def A3 : MipsGPRReg< 7, "7">, DwarfRegNum<[7]>;
- def T0 : MipsGPRReg< 8, "8">, DwarfRegNum<[8]>;
- def T1 : MipsGPRReg< 9, "9">, DwarfRegNum<[9]>;
- def T2 : MipsGPRReg< 10, "10">, DwarfRegNum<[10]>;
- def T3 : MipsGPRReg< 11, "11">, DwarfRegNum<[11]>;
- def T4 : MipsGPRReg< 12, "12">, DwarfRegNum<[12]>;
- def T5 : MipsGPRReg< 13, "13">, DwarfRegNum<[13]>;
- def T6 : MipsGPRReg< 14, "14">, DwarfRegNum<[14]>;
- def T7 : MipsGPRReg< 15, "15">, DwarfRegNum<[15]>;
- def S0 : MipsGPRReg< 16, "16">, DwarfRegNum<[16]>;
- def S1 : MipsGPRReg< 17, "17">, DwarfRegNum<[17]>;
- def S2 : MipsGPRReg< 18, "18">, DwarfRegNum<[18]>;
- def S3 : MipsGPRReg< 19, "19">, DwarfRegNum<[19]>;
- def S4 : MipsGPRReg< 20, "20">, DwarfRegNum<[20]>;
- def S5 : MipsGPRReg< 21, "21">, DwarfRegNum<[21]>;
- def S6 : MipsGPRReg< 22, "22">, DwarfRegNum<[22]>;
- def S7 : MipsGPRReg< 23, "23">, DwarfRegNum<[23]>;
- def T8 : MipsGPRReg< 24, "24">, DwarfRegNum<[24]>;
- def T9 : MipsGPRReg< 25, "25">, DwarfRegNum<[25]>;
- def K0 : MipsGPRReg< 26, "26">, DwarfRegNum<[26]>;
- def K1 : MipsGPRReg< 27, "27">, DwarfRegNum<[27]>;
- def GP : MipsGPRReg< 28, "gp">, DwarfRegNum<[28]>;
- def SP : MipsGPRReg< 29, "sp">, DwarfRegNum<[29]>;
- def FP : MipsGPRReg< 30, "fp">, DwarfRegNum<[30]>;
- def RA : MipsGPRReg< 31, "ra">, DwarfRegNum<[31]>;
+ def ZERO : MipsGPRReg< 0, "zero", "zero">, DwarfRegNum<[0]>;
+ def AT : MipsGPRReg< 1, "1", "at">, DwarfRegNum<[1]>;
+ def V0 : MipsGPRReg< 2, "2", "v0", "v0", "t4">, DwarfRegNum<[2]>;
+ def V1 : MipsGPRReg< 3, "3", "v1", "v1", "t5">, DwarfRegNum<[3]>;
+ def A0 : MipsGPRReg< 4, "4", "a0">, DwarfRegNum<[4]>;
+ def A1 : MipsGPRReg< 5, "5", "a1">, DwarfRegNum<[5]>;
+ def A2 : MipsGPRReg< 6, "6", "a2">, DwarfRegNum<[6]>;
+ def A3 : MipsGPRReg< 7, "7", "a3">, DwarfRegNum<[7]>;
+ def T0 : MipsGPRReg< 8, "8", "t0", "a4">, DwarfRegNum<[8]>;
+ def T1 : MipsGPRReg< 9, "9", "t1", "a5">, DwarfRegNum<[9]>;
+ def T2 : MipsGPRReg<10, "10", "t2", "a6">, DwarfRegNum<[10]>;
+ def T3 : MipsGPRReg<11, "11", "t3", "a7">, DwarfRegNum<[11]>;
+ def T4 : MipsGPRReg<12, "12", "t4", "t0">, DwarfRegNum<[12]>;
+ def T5 : MipsGPRReg<13, "13", "t5", "t1">, DwarfRegNum<[13]>;
+ def T6 : MipsGPRReg<14, "14", "t6", "t2">, DwarfRegNum<[14]>;
+ def T7 : MipsGPRReg<15, "15", "t7", "t3">, DwarfRegNum<[15]>;
+ def S0 : MipsGPRReg<16, "16", "s0">, DwarfRegNum<[16]>;
+ def S1 : MipsGPRReg<17, "17", "s1">, DwarfRegNum<[17]>;
+ def S2 : MipsGPRReg<18, "18", "s2">, DwarfRegNum<[18]>;
+ def S3 : MipsGPRReg<19, "19", "s3">, DwarfRegNum<[19]>;
+ def S4 : MipsGPRReg<20, "20", "s4">, DwarfRegNum<[20]>;
+ def S5 : MipsGPRReg<21, "21", "s5">, DwarfRegNum<[21]>;
+ def S6 : MipsGPRReg<22, "22", "s6">, DwarfRegNum<[22]>;
+ def S7 : MipsGPRReg<23, "23", "s7">, DwarfRegNum<[23]>;
+ def T8 : MipsGPRReg<24, "24", "t8">, DwarfRegNum<[24]>;
+ def T9 : MipsGPRReg<25, "25", "t9">, DwarfRegNum<[25]>;
+ def K0 : MipsGPRReg<26, "26", "k0">, DwarfRegNum<[26]>;
+ def K1 : MipsGPRReg<27, "27", "k1">, DwarfRegNum<[27]>;
+ def GP : MipsGPRReg<28, "gp", "gp">, DwarfRegNum<[28]>;
+ def SP : MipsGPRReg<29, "sp", "sp">, DwarfRegNum<[29]>;
+ def FP : MipsGPRReg<30, "fp", "fp">, DwarfRegNum<[30]>;
+ def RA : MipsGPRReg<31, "ra", "ra">, DwarfRegNum<[31]>;
// General Purpose 64-bit Registers
let isConstant = true in
- def ZERO_64 : Mips64GPRReg< 0, "zero", [ZERO]>, DwarfRegNum<[0]>;
- def AT_64 : Mips64GPRReg< 1, "1", [AT]>, DwarfRegNum<[1]>;
- def V0_64 : Mips64GPRReg< 2, "2", [V0]>, DwarfRegNum<[2]>;
- def V1_64 : Mips64GPRReg< 3, "3", [V1]>, DwarfRegNum<[3]>;
- def A0_64 : Mips64GPRReg< 4, "4", [A0]>, DwarfRegNum<[4]>;
- def A1_64 : Mips64GPRReg< 5, "5", [A1]>, DwarfRegNum<[5]>;
- def A2_64 : Mips64GPRReg< 6, "6", [A2]>, DwarfRegNum<[6]>;
- def A3_64 : Mips64GPRReg< 7, "7", [A3]>, DwarfRegNum<[7]>;
- def T0_64 : Mips64GPRReg< 8, "8", [T0]>, DwarfRegNum<[8]>;
- def T1_64 : Mips64GPRReg< 9, "9", [T1]>, DwarfRegNum<[9]>;
- def T2_64 : Mips64GPRReg< 10, "10", [T2]>, DwarfRegNum<[10]>;
- def T3_64 : Mips64GPRReg< 11, "11", [T3]>, DwarfRegNum<[11]>;
- def T4_64 : Mips64GPRReg< 12, "12", [T4]>, DwarfRegNum<[12]>;
- def T5_64 : Mips64GPRReg< 13, "13", [T5]>, DwarfRegNum<[13]>;
- def T6_64 : Mips64GPRReg< 14, "14", [T6]>, DwarfRegNum<[14]>;
- def T7_64 : Mips64GPRReg< 15, "15", [T7]>, DwarfRegNum<[15]>;
- def S0_64 : Mips64GPRReg< 16, "16", [S0]>, DwarfRegNum<[16]>;
- def S1_64 : Mips64GPRReg< 17, "17", [S1]>, DwarfRegNum<[17]>;
- def S2_64 : Mips64GPRReg< 18, "18", [S2]>, DwarfRegNum<[18]>;
- def S3_64 : Mips64GPRReg< 19, "19", [S3]>, DwarfRegNum<[19]>;
- def S4_64 : Mips64GPRReg< 20, "20", [S4]>, DwarfRegNum<[20]>;
- def S5_64 : Mips64GPRReg< 21, "21", [S5]>, DwarfRegNum<[21]>;
- def S6_64 : Mips64GPRReg< 22, "22", [S6]>, DwarfRegNum<[22]>;
- def S7_64 : Mips64GPRReg< 23, "23", [S7]>, DwarfRegNum<[23]>;
- def T8_64 : Mips64GPRReg< 24, "24", [T8]>, DwarfRegNum<[24]>;
- def T9_64 : Mips64GPRReg< 25, "25", [T9]>, DwarfRegNum<[25]>;
- def K0_64 : Mips64GPRReg< 26, "26", [K0]>, DwarfRegNum<[26]>;
- def K1_64 : Mips64GPRReg< 27, "27", [K1]>, DwarfRegNum<[27]>;
- def GP_64 : Mips64GPRReg< 28, "gp", [GP]>, DwarfRegNum<[28]>;
- def SP_64 : Mips64GPRReg< 29, "sp", [SP]>, DwarfRegNum<[29]>;
- def FP_64 : Mips64GPRReg< 30, "fp", [FP]>, DwarfRegNum<[30]>;
- def RA_64 : Mips64GPRReg< 31, "ra", [RA]>, DwarfRegNum<[31]>;
+ def ZERO_64 : Mips64GPRReg<ZERO>, DwarfRegNum<[0]>;
+ def AT_64 : Mips64GPRReg<AT>, DwarfRegNum<[1]>;
+ def V0_64 : Mips64GPRReg<V0>, DwarfRegNum<[2]>;
+ def V1_64 : Mips64GPRReg<V1>, DwarfRegNum<[3]>;
+ def A0_64 : Mips64GPRReg<A0>, DwarfRegNum<[4]>;
+ def A1_64 : Mips64GPRReg<A1>, DwarfRegNum<[5]>;
+ def A2_64 : Mips64GPRReg<A2>, DwarfRegNum<[6]>;
+ def A3_64 : Mips64GPRReg<A3>, DwarfRegNum<[7]>;
+ def T0_64 : Mips64GPRReg<T0>, DwarfRegNum<[8]>;
+ def T1_64 : Mips64GPRReg<T1>, DwarfRegNum<[9]>;
+ def T2_64 : Mips64GPRReg<T2>, DwarfRegNum<[10]>;
+ def T3_64 : Mips64GPRReg<T3>, DwarfRegNum<[11]>;
+ def T4_64 : Mips64GPRReg<T4>, DwarfRegNum<[12]>;
+ def T5_64 : Mips64GPRReg<T5>, DwarfRegNum<[13]>;
+ def T6_64 : Mips64GPRReg<T6>, DwarfRegNum<[14]>;
+ def T7_64 : Mips64GPRReg<T7>, DwarfRegNum<[15]>;
+ def S0_64 : Mips64GPRReg<S0>, DwarfRegNum<[16]>;
+ def S1_64 : Mips64GPRReg<S1>, DwarfRegNum<[17]>;
+ def S2_64 : Mips64GPRReg<S2>, DwarfRegNum<[18]>;
+ def S3_64 : Mips64GPRReg<S3>, DwarfRegNum<[19]>;
+ def S4_64 : Mips64GPRReg<S4>, DwarfRegNum<[20]>;
+ def S5_64 : Mips64GPRReg<S5>, DwarfRegNum<[21]>;
+ def S6_64 : Mips64GPRReg<S6>, DwarfRegNum<[22]>;
+ def S7_64 : Mips64GPRReg<S7>, DwarfRegNum<[23]>;
+ def T8_64 : Mips64GPRReg<T8>, DwarfRegNum<[24]>;
+ def T9_64 : Mips64GPRReg<T9>, DwarfRegNum<[25]>;
+ def K0_64 : Mips64GPRReg<K0>, DwarfRegNum<[26]>;
+ def K1_64 : Mips64GPRReg<K1>, DwarfRegNum<[27]>;
+ def GP_64 : Mips64GPRReg<GP>, DwarfRegNum<[28]>;
+ def SP_64 : Mips64GPRReg<SP>, DwarfRegNum<[29]>;
+ def FP_64 : Mips64GPRReg<FP>, DwarfRegNum<[30]>;
+ def RA_64 : Mips64GPRReg<RA>, DwarfRegNum<[31]>;
/// Mips Single point precision FPU Registers
foreach I = 0-31 in
@@ -180,11 +201,11 @@ let Namespace = "Mips" in {
DwarfRegNum<[!add(I, 32)]>;
// Hi/Lo registers
- def HI0 : MipsReg<0, "ac0">, DwarfRegNum<[64]>;
+ def HI0 : MipsReg<0, "ac0">, MipsRegAlias<"hi">, DwarfRegNum<[64]>;
def HI1 : MipsReg<1, "ac1">, DwarfRegNum<[176]>;
def HI2 : MipsReg<2, "ac2">, DwarfRegNum<[178]>;
def HI3 : MipsReg<3, "ac3">, DwarfRegNum<[180]>;
- def LO0 : MipsReg<0, "ac0">, DwarfRegNum<[65]>;
+ def LO0 : MipsReg<0, "ac0">, MipsRegAlias<"lo">, DwarfRegNum<[65]>;
def LO1 : MipsReg<1, "ac1">, DwarfRegNum<[177]>;
def LO2 : MipsReg<2, "ac2">, DwarfRegNum<[179]>;
def LO3 : MipsReg<3, "ac3">, DwarfRegNum<[181]>;
@@ -222,8 +243,10 @@ let Namespace = "Mips" in {
def HWR1 : MipsReg<1, "hwr_synci_step">;
def HWR2 : MipsReg<2, "hwr_cc">;
def HWR3 : MipsReg<3, "hwr_ccres">;
+ // GAS does not accept $hwr_ulr, so use the numeric name.
+ def HWR29 : MipsReg<29, "29">, MipsRegAlias<"hwr_ulr">;
- foreach I = 4-31 in
+ foreach I = {4-28, 30-31} in
def HWR#I : MipsReg<I, ""#I>;
// Accum registers
@@ -252,14 +275,14 @@ let Namespace = "Mips" in {
DSPOutFlag23]>;
// MSA-ASE control registers.
- def MSAIR : MipsReg<0, "0">;
- def MSACSR : MipsReg<1, "1">;
- def MSAAccess : MipsReg<2, "2">;
- def MSASave : MipsReg<3, "3">;
- def MSAModify : MipsReg<4, "4">;
- def MSARequest : MipsReg<5, "5">;
- def MSAMap : MipsReg<6, "6">;
- def MSAUnmap : MipsReg<7, "7">;
+ def MSAIR : MipsReg<0, "0">, MipsRegAlias<"msair">;
+ def MSACSR : MipsReg<1, "1">, MipsRegAlias<"msacsr">;
+ def MSAAccess : MipsReg<2, "2">, MipsRegAlias<"msaaccess">;
+ def MSASave : MipsReg<3, "3">, MipsRegAlias<"msasave">;
+ def MSAModify : MipsReg<4, "4">, MipsRegAlias<"msamodify">;
+ def MSARequest : MipsReg<5, "5">, MipsRegAlias<"msarequest">;
+ def MSAMap : MipsReg<6, "6">, MipsRegAlias<"msamap">;
+ def MSAUnmap : MipsReg<7, "7">, MipsRegAlias<"msaunmap">;
// MSA-ASE fake control registers.
// These registers do not exist, but instructions like `cfcmsa`
// and `ctcmsa` allows to specify them.
diff --git a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
index 937e33bd840e6..62aa19598e2f8 100644
--- a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -509,7 +509,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
if (hasBP(MF)) {
// move $s7, $sp
- unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7;
+ unsigned BP = STI.getABI().GetBasePtr();
BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP)
.addReg(SP)
.addReg(ZERO);
@@ -821,7 +821,7 @@ void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
MipsABIInfo ABI = STI.getABI();
unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA;
unsigned FP = ABI.GetFramePtr();
- unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7;
+ unsigned BP = ABI.GetBasePtr();
// Mark $ra and $fp as used if function has dedicated frame pointer.
if (hasFP(MF)) {
diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
index b16341dcec0b9..570768dde4840 100644
--- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -955,7 +955,7 @@ void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB,
unsigned ADDU = ABI.GetPtrAdduOp();
unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP;
unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA;
- unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9;
+ unsigned T9 = ABI.getTempReg(9, Subtarget.isGP64bit());
unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Register OffsetReg = I->getOperand(0).getReg();
Register TargetReg = I->getOperand(1).getReg();
diff --git a/llvm/test/CodeGen/Mips/named-register-aliases.ll b/llvm/test/CodeGen/Mips/named-register-aliases.ll
new file mode 100644
index 0000000000000..6aea464efd131
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/named-register-aliases.ll
@@ -0,0 +1,33 @@
+; RUN: llc -mtriple=mips64 -target-abi n32 -mattr=+reserve-gpr8,+reserve-gpr26,+reserve-gpr30 \
+; RUN: -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=mips64 -target-abi n64 -mattr=+reserve-gpr8,+reserve-gpr26,+reserve-gpr30 \
+; RUN: -verify-machineinstrs < %s | FileCheck %s
+
+; ABI names and aliases in named-register lowering.
+define i64 @get_a4() {
+; CHECK-LABEL: get_a4:
+; CHECK: move $2, $8
+ %value = call i64 @llvm.read_register.i64(metadata !0)
+ ret i64 %value
+}
+
+define i64 @get_kt0() {
+; CHECK-LABEL: get_kt0:
+; CHECK: move $2, $26
+ %value = call i64 @llvm.read_register.i64(metadata !1)
+ ret i64 %value
+}
+
+define i64 @get_s8() {
+; CHECK-LABEL: get_s8:
+; CHECK: move $2, $fp
+ %value = call i64 @llvm.read_register.i64(metadata !2)
+ ret i64 %value
+}
+
+declare i64 @llvm.read_register.i64(metadata)
+
+!llvm.named.register = !{!0, !1, !2}
+!0 = !{!"$a4"}
+!1 = !{!"$kt0"}
+!2 = !{!"$s8"}
diff --git a/llvm/test/MC/Mips/mips-register-names-invalid.s b/llvm/test/MC/Mips/mips-register-names-invalid.s
index 42a5a0dfb6023..9c8251256e73f 100644
--- a/llvm/test/MC/Mips/mips-register-names-invalid.s
+++ b/llvm/test/MC/Mips/mips-register-names-invalid.s
@@ -1,5 +1,9 @@
-# RUN: not llvm-mc %s -triple=mips-unknown-freebsd -show-encoding 2>%t0
-# RUN: FileCheck %s < %t0
+# RUN: not llvm-mc %s -triple=mips-unknown-freebsd -defsym O32=1 -show-encoding 2>%t0
+# RUN: FileCheck %s --check-prefixes=CHECK,O32 < %t0
+# RUN: not llvm-mc %s -triple=mips64-unknown-freebsd -target-abi n32 -show-encoding 2>%t1
+# RUN: FileCheck %s < %t1
+# RUN: not llvm-mc %s -triple=mips64-unknown-freebsd -target-abi n64 -show-encoding 2>%t2
+# RUN: FileCheck %s < %t2
# $32 used to trigger an assertion instead of the usual error message due to
# an off-by-one bug.
@@ -8,3 +12,23 @@
add $32, $0, $0
# CHECK: :[[@LINE+1]]:26: error: invalid register number
lw $8, 0x10($32)
+
+# Names from other register classes must not be accepted as GPRs.
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $hi, $0, $0
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $hwr_cc, $0, $0
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $msacsr, $0, $0
+
+# NABI-only names must not leak into O32.
+.ifdef O32
+# O32: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $a4, $0, $0
+# O32: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $a7, $0, $0
+# O32: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $kt0, $0, $0
+# O32: :[[@LINE+1]]:17: error: invalid operand for instruction
+ add $kt1, $0, $0
+.endif
diff --git a/llvm/test/MC/Mips/mips64-register-names-n32-n64.s b/llvm/test/MC/Mips/mips64-register-names-n32-n64.s
index c1eb36a8fc762..590b8c45dad0c 100644
--- a/llvm/test/MC/Mips/mips64-register-names-n32-n64.s
+++ b/llvm/test/MC/Mips/mips64-register-names-n32-n64.s
@@ -1,10 +1,10 @@
# RUN: llvm-mc %s -triple=mips64-unknown-freebsd -show-encoding 2>%t0 \
# RUN: | FileCheck %s
-# RUN: FileCheck -check-prefix=WARNING %s < %t0
+# RUN: FileCheck -check-prefix=WARNING --implicit-check-not=warning: %s < %t0
#
# RUN: llvm-mc %s -triple=mips64-unknown-freebsd -show-encoding \
# RUN: -target-abi n32 2>%t1 | FileCheck %s
-# RUN: FileCheck -check-prefix=WARNING %s < %t1
+# RUN: FileCheck -check-prefix=WARNING --implicit-check-not=warning: %s < %t1
#
# Check that the register names are mapped to their correct numbers for n32/n64
# Second byte of addiu with $zero at rt contains the number of the source
diff --git a/llvm/test/TableGen/MatchRegisterAltNameWithIndex.td b/llvm/test/TableGen/MatchRegisterAltNameWithIndex.td
new file mode 100644
index 0000000000000..9bbdb51eaf58d
--- /dev/null
+++ b/llvm/test/TableGen/MatchRegisterAltNameWithIndex.td
@@ -0,0 +1,60 @@
+// RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-asm-matcher -DDUPLICATES -I %p/../../include %s | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+def ArchInstrInfo : InstrInfo;
+def ArchAsmParser : AsmParser {
+ let ShouldEmitMatchRegisterName = false;
+ let ShouldEmitMatchRegisterAltNameWithIndex = true;
+#ifdef DUPLICATES
+ let AllowDuplicateRegisterNames = true;
+#endif
+}
+def Arch : Target {
+ let InstructionSet = ArchInstrInfo;
+ let AssemblyParsers = [ArchAsmParser];
+}
+
+let Namespace = "Arch" in {
+def ABI0 : RegAltNameIndex;
+let FallbackRegAltNameIndex = ABI0 in
+def ABI1 : RegAltNameIndex;
+
+class ArchReg<string name, list<string> names,
+ list<RegAltNameIndex> indices = [ABI0, ABI1]> : Register<name> {
+ let AltNames = names;
+ let RegAltNameIndices = indices;
+}
+
+// Shared spellings select different registers by index.
+def R0 : ArchReg<"r0", ["arg", "tmp"]>;
+def R1 : ArchReg<"r1", ["tmp", "arg"]>;
+// Ignore empty and unindexed names.
+def R2 : ArchReg<"r2", ["", "extra", "unindexed"]>;
+// Allow multiple names per index.
+def R3 : ArchReg<"r3", ["alias0", "alias1"], [ABI0, ABI0]>;
+#ifdef DUPLICATES
+def R0_64 : ArchReg<"r0", ["arg", "tmp"]>;
+#endif
+}
+
+def GPR : RegisterClass<"Arch", [i32], 32, (add R0, R1, R2, R3)>;
+
+// CHECK-LABEL: static MCRegister MatchRegisterAltName(StringRef Name, unsigned AltIdx) {
+// CHECK-NEXT: switch (AltIdx) {
+// CHECK-NEXT: default: break;
+// CHECK: case Arch::ABI0: {
+// CHECK-DAG: return Arch::R0; // "arg"
+// CHECK-DAG: return Arch::R1; // "tmp"
+// CHECK-DAG: return Arch::R3; // "alias0"
+// CHECK-DAG: return Arch::R3; // "alias1"
+// CHECK-NOT: return Arch::R2;
+// CHECK: case Arch::ABI1: {
+// CHECK-DAG: return Arch::R0; // "tmp"
+// CHECK-DAG: return Arch::R1; // "arg"
+// CHECK-DAG: return Arch::R2; // "extra"
+// CHECK-NOT: return Arch::R3;
+// CHECK-NOT: MatchRegisterAltName(Name,
+// CHECK: return Arch::NoRegister;
+// CHECK-NEXT: }
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 4a619883bfefc..8ca01a191179a 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2906,7 +2906,8 @@ static void emitMatchRegisterName(const CodeGenTarget &Target,
"::" + Reg.getName().str() + ';');
}
- OS << "static MCRegister MatchRegisterName(StringRef Name) {\n";
+ OS << "[[maybe_unused]] static MCRegister MatchRegisterName(StringRef Name) "
+ "{\n";
bool IgnoreDuplicates =
AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
@@ -2920,30 +2921,52 @@ static void emitMatchRegisterName(const CodeGenTarget &Target,
/// specific register enum.
static void emitMatchRegisterAltName(const CodeGenTarget &Target,
const Record *AsmParser, raw_ostream &OS) {
- // Construct the match list.
- std::vector<StringMatcher::StringPair> Matches;
const auto &Regs = Target.getRegBank().getRegisters();
std::string Namespace =
Regs.front().TheDef->getValueAsString("Namespace").str();
- for (const CodeGenRegister &Reg : Regs) {
- for (StringRef AltName : Reg.TheDef->getValueAsListOfStrings("AltNames")) {
- AltName = AltName.trim();
+ bool WithIndex =
+ AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltNameWithIndex");
+ bool IgnoreDuplicates =
+ AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
- // don't handle empty alternative names
- if (AltName.empty())
- continue;
+ auto EmitMatches = [&](const Record *AltIdx, unsigned Indent) {
+ std::vector<StringMatcher::StringPair> Matches;
+ for (const CodeGenRegister &Reg : Regs) {
+ auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");
+ auto AltIndices = Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
+ for (auto [I, AltName] : enumerate(AltNames)) {
+ if (AltIdx && (I >= AltIndices.size() || AltIndices[I] != AltIdx))
+ continue;
+ AltName = AltName.trim();
+ if (AltName.empty())
+ continue;
+ Matches.emplace_back(AltName.str(), "return " + Namespace + "::" +
+ Reg.getName().str() + ';');
+ }
+ }
+ StringMatcher("Name", Matches, OS).Emit(Indent, IgnoreDuplicates);
+ };
- Matches.emplace_back(AltName.str(), "return " + Namespace +
- "::" + Reg.getName().str() + ';');
+ OS << "[[maybe_unused]] static MCRegister MatchRegisterAltName(StringRef "
+ "Name";
+ if (WithIndex)
+ OS << ", unsigned AltIdx";
+ OS << ") {\n";
+
+ if (WithIndex) {
+ OS << " switch (AltIdx) {\n"
+ " default: break;\n";
+ for (const Record *AltIdx : Target.getRegAltNameIndices()) {
+ if (AltIdx->getName() == "NoRegAltName")
+ continue;
+ OS << " case " << Namespace << "::" << AltIdx->getName() << ": {\n";
+ EmitMatches(AltIdx, 1);
+ OS << " break;\n }\n";
}
+ OS << " }\n";
+ } else {
+ EmitMatches(nullptr, 0);
}
-
- OS << "static MCRegister MatchRegisterAltName(StringRef Name) {\n";
-
- bool IgnoreDuplicates =
- AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
- StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);
-
OS << " return " << Namespace << "::NoRegister;\n";
OS << "}\n\n";
}
@@ -3634,11 +3657,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
Info.SubtargetFeatures, OS);
// Emit the function to match a register name to number.
- // This should be omitted for Mips target
if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
emitMatchRegisterName(Target, AsmParser, OS);
- if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))
+ if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName") ||
+ AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltNameWithIndex"))
emitMatchRegisterAltName(Target, AsmParser, OS);
OS << "#endif // GET_REGISTER_MATCHER\n\n";
>From 40a65946c06827c46bb0b0fb13691f63d40ede99 Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Mon, 21 Sep 2026 10:03:10 +0100
Subject: [PATCH 2/2] [Mips] Add pointer-width ABI register accessors
Add RegPtr variants for argument, temporary, saved and return registers and use them at pointer-width call sites. Keep the GPR-width defaults and document the distinction for N32.
Use the current ABI to select 32-bit argument registers in O32 calling-convention lowering.
---
llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 4 ++--
llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h | 15 ++++++++++++++-
llvm/lib/Target/Mips/MipsISelLowering.cpp | 12 +++++++-----
llvm/lib/Target/Mips/MipsISelLowering.h | 4 ++--
llvm/lib/Target/Mips/MipsMachineFunction.cpp | 2 +-
5 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
index f45df26ef65f7..e0a35fcd842a3 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
@@ -197,7 +197,7 @@ unsigned MipsABIInfo::GetFramePtr() const {
}
unsigned MipsABIInfo::GetBasePtr() const {
- return getSavedReg(7, ArePtrs64bit());
+ return getSavedRegPtr(7);
}
unsigned MipsABIInfo::GetGlobalPtr() const {
@@ -234,5 +234,5 @@ unsigned MipsABIInfo::GetGPRMoveOp() const {
unsigned MipsABIInfo::GetEhDataReg(unsigned I) const {
assert(I < 4 && "Invalid EH data register");
- return getArgReg(I, ArePtrs64bit());
+ return getArgRegPtr(I);
}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
index a5a4e89e1331d..2d16b8652820b 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
@@ -47,25 +47,38 @@ class MipsABIInfo {
/// Integer argument registers in calling-convention order.
ArrayRef<MCPhysReg> getArgRegs(bool Is64Bit) const;
- /// ABI register accessors default to the ABI's GPR width.
+ /// ABI register accessors default to the ABI's GPR width. Use the *RegPtr
+ /// variants for pointer-sized values; N32 has 32-bit pointers and 64-bit GPRs.
MCRegister getArgReg(unsigned I, bool Is64Bit) const;
MCRegister getArgReg(unsigned I) const {
return getArgReg(I, AreGprs64bit());
}
+ MCRegister getArgRegPtr(unsigned I) const {
+ return getArgReg(I, ArePtrs64bit());
+ }
/// I is the suffix in tI (NABI has t0-t3 and t8-t9).
MCRegister getTempReg(unsigned I, bool Is64Bit) const;
MCRegister getTempReg(unsigned I) const {
return getTempReg(I, AreGprs64bit());
}
+ MCRegister getTempRegPtr(unsigned I) const {
+ return getTempReg(I, ArePtrs64bit());
+ }
MCRegister getSavedReg(unsigned I, bool Is64Bit) const;
MCRegister getSavedReg(unsigned I) const {
return getSavedReg(I, AreGprs64bit());
}
+ MCRegister getSavedRegPtr(unsigned I) const {
+ return getSavedReg(I, ArePtrs64bit());
+ }
/// Integer return-value registers.
MCRegister getReturnReg(unsigned I, bool Is64Bit) const;
MCRegister getReturnReg(unsigned I) const {
return getReturnReg(I, AreGprs64bit());
}
+ MCRegister getReturnRegPtr(unsigned I) const {
+ return getReturnReg(I, ArePtrs64bit());
+ }
/// The registers to use for byval arguments.
ArrayRef<MCPhysReg> GetByValArgRegs() const;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index b9d9f079f1511..c09533035f30d 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -2705,8 +2705,8 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG)
// Store stack offset in V1, store jump target in V0. Glue CopyToReg and
// EH_RETURN nodes, so that instructions are emitted back-to-back.
- unsigned OffsetReg = ABI.getReturnReg(1, ABI.ArePtrs64bit());
- unsigned AddrReg = ABI.getReturnReg(0, ABI.ArePtrs64bit());
+ unsigned OffsetReg = ABI.getReturnRegPtr(1);
+ unsigned AddrReg = ABI.getReturnRegPtr(0);
Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue());
Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1));
return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain,
@@ -3053,11 +3053,13 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>(
State.getMachineFunction().getSubtarget());
- ArrayRef<MCPhysReg> IntRegs = MipsABIInfo::O32().getArgRegs(false);
+ const MipsABIInfo &ABI = Subtarget.getABI();
+ ArrayRef<MCPhysReg> IntRegs = ABI.getArgRegs(false);
static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 };
- static const MCPhysReg FloatVectorIntRegs[] = {Mips::A0, Mips::A2};
+ const MCPhysReg FloatVectorIntRegs[] = {ABI.getArgReg(0, false),
+ ABI.getArgReg(2, false)};
// Do not process byval args here.
if (ArgFlags.isByVal())
@@ -4101,7 +4103,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
llvm_unreachable("sret virtual register not created in the entry block");
SDValue Val =
DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout()));
- unsigned V0 = ABI.getReturnReg(0, ABI.ArePtrs64bit());
+ unsigned V0 = ABI.getReturnRegPtr(0);
Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Glue);
Glue = Chain.getValue(1);
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 57ebd3619ed78..e352cf5492b3b 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -146,7 +146,7 @@ using TargetRegisterClass = MCRegisterClass;
Register
getExceptionPointerRegister(ExceptionHandling EH,
const Constant *PersonalityFn) const override {
- return ABI.getArgReg(0, ABI.ArePtrs64bit());
+ return ABI.getArgRegPtr(0);
}
/// If a physical register, this returns the register that receives the
@@ -154,7 +154,7 @@ using TargetRegisterClass = MCRegisterClass;
Register
getExceptionSelectorRegister(ExceptionHandling EH,
const Constant *PersonalityFn) const override {
- return ABI.getArgReg(1, ABI.ArePtrs64bit());
+ return ABI.getArgRegPtr(1);
}
bool isJumpTableRelative() const override {
diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/llvm/lib/Target/Mips/MipsMachineFunction.cpp
index 83bedafd58ce5..27206b4c3d19d 100644
--- a/llvm/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/llvm/lib/Target/Mips/MipsMachineFunction.cpp
@@ -84,7 +84,7 @@ void MipsFunctionInfo::initGlobalBaseReg(MachineFunction &MF) {
Register V0 = RegInfo.createVirtualRegister(RC);
Register V1 = RegInfo.createVirtualRegister(RC);
- MCRegister T9 = ABI.getTempReg(9, ABI.ArePtrs64bit());
+ MCRegister T9 = ABI.getTempRegPtr(9);
if (ABI.IsN64()) {
MF.getRegInfo().addLiveIn(T9);
More information about the llvm-commits
mailing list