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 #include #include +#include +#include #include #include @@ -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(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(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(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(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"}