Skip to content

Conversation

yingopq
Copy link
Contributor

@yingopq yingopq commented Apr 23, 2025

Fix #47656.

@el-ev
Copy link
Member

el-ev commented Apr 23, 2025

Looks good for adding support for $sp. Should we other general purpose registers as well? The Clang frontend accepts $1 through $31 along with their aliases. Currently,$28, sp and $sp work here, but the rest still cause a crash.

@yingopq
Copy link
Contributor Author

yingopq commented Apr 23, 2025

Looks good for adding support for $sp. Should we other general purpose registers as well? The Clang frontend accepts $1 through $31 along with their aliases. Currently,$28, sp and $sp work here, but the rest still cause a crash.

We can see the code comments The Linux kernel uses $28 and sp, so we keep consistent with the Linux kernel. May I understand it correctly?

@wzssyqa
Copy link
Contributor

wzssyqa commented May 11, 2025

I think that we need something to support something like $0-$31 and something like $gp, $t1 etc.

@yingopq
Copy link
Contributor Author

yingopq commented May 14, 2025

I think that we need something to support something like $0-$31 and something like $gp, $t1 etc.

You mean we need to process all registers?

@wzssyqa
Copy link
Contributor

wzssyqa commented May 14, 2025

I think that we need something to support something like $0-$31 and something like $gp, $t1 etc.

You mean we need to process all registers?

yes.

@yingopq yingopq force-pushed the Fix_bug_issue_47656 branch 3 times, most recently from 9a585ca to 5233436 Compare June 5, 2025 09:30
@yingopq
Copy link
Contributor Author

yingopq commented Jun 6, 2025

@wzssyqa Could you help review again? Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More test cases with other reg names?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have appended test with other reg, can you help review again?

@yingopq yingopq force-pushed the Fix_bug_issue_47656 branch from 5233436 to 1a3f307 Compare June 9, 2025 07:38
@yingopq
Copy link
Contributor Author

yingopq commented Jul 22, 2025

ping @wzssyqa

@yingopq
Copy link
Contributor Author

yingopq commented Aug 21, 2025

Ping

@yingopq
Copy link
Contributor Author

yingopq commented Sep 2, 2025

ping

@yingopq
Copy link
Contributor Author

yingopq commented Oct 10, 2025

@wzssyqa Can you help review again, thanks!

@wzssyqa
Copy link
Contributor

wzssyqa commented Oct 10, 2025

@wzssyqa Can you help review again, thanks!

You need to resolve the conflicts.

@llvmbot
Copy link
Member

llvmbot commented Oct 10, 2025

@llvm/pr-subscribers-backend-mips

Author: None (yingopq)

Changes

Fix #47656.


Full diff: https://github.com/llvm/llvm-project/pull/136821.diff

5 Files Affected:

  • (modified) llvm/lib/Target/Mips/MipsISelLowering.cpp (+100-12)
  • (modified) llvm/lib/Target/Mips/MipsISelLowering.h (+2)
  • (modified) llvm/test/CodeGen/Mips/named-register-n32.ll (+48-4)
  • (modified) llvm/test/CodeGen/Mips/named-register-n64.ll (+48-4)
  • (modified) llvm/test/CodeGen/Mips/named-register-o32.ll (+48-4)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index b05de49d8332a..020a8325a32fd 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>
 
@@ -4937,25 +4939,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());
-    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);
   }
 
-  Register Reg = StringSwitch<Register>(RegName)
-                     .Case("$28", Mips::GP)
-                     .Case("sp", Mips::SP)
-                     .Default(Register());
-  return Reg;
+  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 c65c76ccffc75..09a59905c8c25 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -718,6 +718,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"}

@yingopq
Copy link
Contributor Author

yingopq commented Oct 11, 2025

@wzssyqa Can you help review again, thanks!

You need to resolve the conflicts.

OK, updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

internal compiler error: Invalid register name global variable

4 participants