[llvm] [Mips] Support "$sp" named register (PR #136821)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 00:38:52 PDT 2025


https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/136821

>From 1a3f307553f8b77b5ab0738d07b2b283cb1ece52 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Tue, 22 Apr 2025 22:29:52 -0400
Subject: [PATCH] [Mips] Support "$sp" named register

Fix #47656.
---
 llvm/lib/Target/Mips/MipsISelLowering.cpp    | 117 ++++++++++++++++---
 llvm/lib/Target/Mips/MipsISelLowering.h      |   2 +
 llvm/test/CodeGen/Mips/named-register-n32.ll |  52 ++++++++-
 llvm/test/CodeGen/Mips/named-register-n64.ll |  52 ++++++++-
 llvm/test/CodeGen/Mips/named-register-o32.ll |  52 ++++++++-
 5 files changed, 247 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index bd65431b475d0..efdd164bf6577 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -72,6 +72,8 @@
 #include <cstdint>
 #include <deque>
 #include <iterator>
+#include <regex>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -4888,28 +4890,111 @@ 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)
+           .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 (!(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 {
-  // The Linux kernel uses $28 and sp.
-  if (Subtarget.isGP64bit()) {
-    Register Reg = StringSwitch<Register>(RegName)
-                       .Case("$28", Mips::GP_64)
-                       .Case("sp", Mips::SP_64)
-                       .Default(Register());
-    if (Reg)
-      return Reg;
-  } else {
-    Register Reg = StringSwitch<Register>(RegName)
-                       .Case("$28", Mips::GP)
-                       .Case("sp", Mips::SP)
-                       .Default(Register());
-    if (Reg)
-      return Reg;
+  // 1. Delete symbol '$'.
+  std::string newRegName = RegName;
+  if (StringRef(RegName).starts_with("$"))
+    newRegName = StringRef(RegName).substr(1);
+
+  // 2. Check if number [0-31], then transform to int.
+  std::smatch matchResult;
+  static const std::regex matchStr("^[0-9]*$");
+  if (std::regex_match(newRegName, matchResult, matchStr)) {
+    int regIdx = std::stoi(newRegName);
+    if (regIdx >= 0 && regIdx < 32) {
+      return Subtarget.isGP64bit() ? MF.getContext()
+                                         .getRegisterInfo()
+                                         ->getRegClass(Mips::GPR64RegClassID)
+                                         .getRegister(regIdx)
+                                   : MF.getContext()
+                                         .getRegisterInfo()
+                                         ->getRegClass(Mips::GPR32RegClassID)
+                                         .getRegister(regIdx);
+    }
+  }
+
+  // 3. Use function `getCPURegisterIndex` to get register index value
+  newRegName = StringRef(newRegName).lower();
+  int regNo = getCPURegisterIndex(StringRef(newRegName));
+  if (regNo >= 0 && regNo < 32) {
+    return Subtarget.isGP64bit() ? MF.getContext()
+                                       .getRegisterInfo()
+                                       ->getRegClass(Mips::GPR64RegClassID)
+                                       .getRegister(regNo)
+                                 : MF.getContext()
+                                       .getRegisterInfo()
+                                       ->getRegClass(Mips::GPR32RegClassID)
+                                       .getRegister(regNo);
   }
-  report_fatal_error("Invalid register name global variable");
+
+  report_fatal_error(
+      Twine("Invalid register name \"" + StringRef(RegName) + "\"."));
 }
 
 MachineBasicBlock *MipsTargetLowering::emitLDR_W(MachineInstr &MI,
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 5bd7b09ded45b..7983c99500f4e 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -715,6 +715,8 @@ class TargetRegisterClass;
       return true;
     }
 
+    int getCPURegisterIndex(StringRef Name) const;
+
     /// Emit a sign-extension using sll/sra, seb, or seh appropriately.
     MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI,
                                                 MachineBasicBlock *BB,
diff --git a/llvm/test/CodeGen/Mips/named-register-n32.ll b/llvm/test/CodeGen/Mips/named-register-n32.ll
index 112e04e14b2ac..617e03f95b050 100644
--- a/llvm/test/CodeGen/Mips/named-register-n32.ll
+++ b/llvm/test/CodeGen/Mips/named-register-n32.ll
@@ -4,12 +4,39 @@
 
 declare i64 @llvm.read_register.i64(metadata)
 
+define i64 @get_$28() {
+; CHECK-LABEL: get_$28:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %1
+}
+
 define i64 @get_gp() {
 ; CHECK-LABEL: get_gp:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $gp
-  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  %1 = call i64 @llvm.read_register.i64(metadata !1)
+  ret i64 %1
+}
+
+define i64 @get_$gp() {
+; CHECK-LABEL: get_$gp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i64 @llvm.read_register.i64(metadata !2)
+  ret i64 %1
+}
+
+define i64 @get_$29() {
+; CHECK-LABEL: get_$29:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i64 @llvm.read_register.i64(metadata !3)
   ret i64 %1
 }
 
@@ -18,12 +45,29 @@ define i64 @get_sp() {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $sp
-  %1 = call i64 @llvm.read_register.i64(metadata !1)
+  %1 = call i64 @llvm.read_register.i64(metadata !4)
+  ret i64 %1
+}
+
+define i64 @get_$sp() {
+; CHECK-LABEL: get_$sp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i64 @llvm.read_register.i64(metadata !5)
   ret i64 %1
 }
 
 !llvm.named.register.$28 = !{!0}
-!llvm.named.register.sp = !{!1}
+!llvm.named.register.gp = !{!1}
+!llvm.named.register.$gp = !{!2}
+!llvm.named.register.$29 = !{!3}
+!llvm.named.register.sp = !{!4}
+!llvm.named.register.$sp = !{!5}
 
 !0 = !{!"$28"}
-!1 = !{!"sp"}
+!1 = !{!"gp"}
+!2 = !{!"$gp"}
+!3 = !{!"$29"}
+!4 = !{!"sp"}
+!5 = !{!"$sp"}
diff --git a/llvm/test/CodeGen/Mips/named-register-n64.ll b/llvm/test/CodeGen/Mips/named-register-n64.ll
index 42d9ba1e1f15c..bee8643fabfee 100644
--- a/llvm/test/CodeGen/Mips/named-register-n64.ll
+++ b/llvm/test/CodeGen/Mips/named-register-n64.ll
@@ -4,12 +4,39 @@
 
 declare i64 @llvm.read_register.i64(metadata)
 
+define i64 @get_$28() {
+; CHECK-LABEL: get_$28:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  ret i64 %1
+}
+
 define i64 @get_gp() {
 ; CHECK-LABEL: get_gp:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $gp
-  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  %1 = call i64 @llvm.read_register.i64(metadata !1)
+  ret i64 %1
+}
+
+define i64 @get_$gp() {
+; CHECK-LABEL: get_$gp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i64 @llvm.read_register.i64(metadata !2)
+  ret i64 %1
+}
+
+define i64 @get_$29() {
+; CHECK-LABEL: get_$29:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i64 @llvm.read_register.i64(metadata !3)
   ret i64 %1
 }
 
@@ -18,12 +45,29 @@ define i64 @get_sp() {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $sp
-  %1 = call i64 @llvm.read_register.i64(metadata !1)
+  %1 = call i64 @llvm.read_register.i64(metadata !4)
+  ret i64 %1
+}
+
+define i64 @get_$sp() {
+; CHECK-LABEL: get_$sp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i64 @llvm.read_register.i64(metadata !5)
   ret i64 %1
 }
 
 !llvm.named.register.$28 = !{!0}
-!llvm.named.register.sp = !{!1}
+!llvm.named.register.gp = !{!1}
+!llvm.named.register.$gp = !{!2}
+!llvm.named.register.$29 = !{!3}
+!llvm.named.register.sp = !{!4}
+!llvm.named.register.$sp = !{!5}
 
 !0 = !{!"$28"}
-!1 = !{!"sp"}
+!1 = !{!"gp"}
+!2 = !{!"$gp"}
+!3 = !{!"$29"}
+!4 = !{!"sp"}
+!5 = !{!"$sp"}
diff --git a/llvm/test/CodeGen/Mips/named-register-o32.ll b/llvm/test/CodeGen/Mips/named-register-o32.ll
index 280c56e4db6a4..c01c110bcbd77 100644
--- a/llvm/test/CodeGen/Mips/named-register-o32.ll
+++ b/llvm/test/CodeGen/Mips/named-register-o32.ll
@@ -4,12 +4,39 @@
 
 declare i32 @llvm.read_register.i32(metadata)
 
+define i32 @get_$28() {
+; CHECK-LABEL: get_$28:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i32 @llvm.read_register.i32(metadata !0)
+  ret i32 %1
+}
+
 define i32 @get_gp() {
 ; CHECK-LABEL: get_gp:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $gp
-  %1 = call i32 @llvm.read_register.i32(metadata !0)
+  %1 = call i32 @llvm.read_register.i32(metadata !1)
+  ret i32 %1
+}
+
+define i32 @get_$gp() {
+; CHECK-LABEL: get_$gp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $gp
+  %1 = call i32 @llvm.read_register.i32(metadata !2)
+  ret i32 %1
+}
+
+define i32 @get_$29() {
+; CHECK-LABEL: get_$29:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i32 @llvm.read_register.i32(metadata !3)
   ret i32 %1
 }
 
@@ -18,12 +45,29 @@ define i32 @get_sp() {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    move $2, $sp
-  %1 = call i32 @llvm.read_register.i32(metadata !1)
+  %1 = call i32 @llvm.read_register.i32(metadata !4)
+  ret i32 %1
+}
+
+define i32 @get_$sp() {
+; CHECK-LABEL: get_$sp:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    move $2, $sp
+  %1 = call i32 @llvm.read_register.i32(metadata !5)
   ret i32 %1
 }
 
 !llvm.named.register.$28 = !{!0}
-!llvm.named.register.sp = !{!1}
+!llvm.named.register.gp = !{!1}
+!llvm.named.register.$gp = !{!2}
+!llvm.named.register.$29 = !{!3}
+!llvm.named.register.sp = !{!4}
+!llvm.named.register.$sp = !{!5}
 
 !0 = !{!"$28"}
-!1 = !{!"sp"}
+!1 = !{!"gp"}
+!2 = !{!"$gp"}
+!3 = !{!"$29"}
+!4 = !{!"sp"}
+!5 = !{!"$sp"}



More information about the llvm-commits mailing list