[llvm] [Mips] Fix $gp was restored when used as global register variable (PR #184975)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 6 01:56:14 PST 2026
https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/184975
>From 62c11510f7016616defe3f3fc078fcaaaf5bfa85 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Fri, 6 Mar 2026 17:31:13 +0800
Subject: [PATCH] [Mips] Fix $gp was restored when used as global register
variable
The function `eliminateDeadMI` would check `if (MRI.isReserved(Reg))`,
now we only set GP to reserved when `!Subtarget.isABICalls()`. So
`eliminateDeadMI` delete the `move $gp, $4`. And we would restore
$gp after instr selection through `$gp_64 = LD $sp_64, 8`.
Add a bool val when process instr `write_register` selection to
represent whether $gp used as global register val.
Then append new conditon when set $gp to reserverd status and return
CalleeSavedRegs without $gp.
Fix #176546.
---
llvm/lib/Target/Mips/MipsCallingConv.td | 13 +++++++++++++
llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp | 10 ++++++++++
llvm/lib/Target/Mips/MipsMachineFunction.h | 5 +++++
llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 15 ++++++++++-----
llvm/test/CodeGen/Mips/write_register_gp.ll | 18 ++++++++++++++++++
5 files changed, 56 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/write_register_gp.ll
diff --git a/llvm/lib/Target/Mips/MipsCallingConv.td b/llvm/lib/Target/Mips/MipsCallingConv.td
index 748162525b091..d3e552bc71ca9 100644
--- a/llvm/lib/Target/Mips/MipsCallingConv.td
+++ b/llvm/lib/Target/Mips/MipsCallingConv.td
@@ -362,16 +362,29 @@ def CSR_O32_FP64 :
def CSR_N32 : CalleeSavedRegs<(add(decimate(sequence "D%u_64", 30, 20), 2),
RA_64, FP_64, GP_64, (sequence "S%u_64", 7, 0))>;
+def CSR_N32_NoGP : CalleeSavedRegs<(add(decimate(sequence "D%u_64", 30, 20), 2),
+ RA_64, FP_64, (sequence "S%u_64", 7, 0))>;
+
def CSR_N32_SingleFloat
: CalleeSavedRegs<(add(decimate(sequence "F%u", 30, 20), 2), RA_64, FP_64,
GP_64, (sequence "S%u_64", 7, 0))>;
+def CSR_N32_SingleFloat_NoGP
+ : CalleeSavedRegs<(add(decimate(sequence "F%u", 30, 20), 2), RA_64, FP_64,
+ (sequence "S%u_64", 7, 0))>;
+
def CSR_N64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64,
GP_64, (sequence "S%u_64", 7, 0))>;
+def CSR_N64_NoGP : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64,
+ (sequence "S%u_64", 7, 0))>;
+
def CSR_N64_SingleFloat : CalleeSavedRegs<(add(sequence "F%u", 31, 24), RA_64,
FP_64, GP_64, (sequence "S%u_64", 7, 0))>;
+def CSR_N64_SingleFloat_NoGP : CalleeSavedRegs<(add(sequence "F%u", 31, 24), RA_64,
+ FP_64, (sequence "S%u_64", 7, 0))>;
+
def CSR_Mips16RetHelper :
CalleeSavedRegs<(add V0, V1, FP,
(sequence "A%u", 3, 0), (sequence "S%u", 7, 0),
diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 36706243232c0..41345de1f0cd9 100644
--- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -254,6 +254,16 @@ void MipsDAGToDAGISel::Select(SDNode *Node) {
ReplaceNode(Node, getGlobalBaseReg());
return;
+ case ISD::WRITE_REGISTER: {
+ MDNodeSDNode *MD = cast<MDNodeSDNode>(Node->getOperand(1));
+ const MDString *RegStr = cast<MDString>(MD->getMD()->getOperand(0));
+ StringRef Reg = RegStr->getString();
+ if (Reg == "$gp" || Reg == "$28" || Reg == "$28_64" || Reg == "$gp_64") {
+ MachineFunction &MF = CurDAG->getMachineFunction();
+ MF.getInfo<MipsFunctionInfo>()->setGPGlobalRegister(true);
+ }
+ break;
+ }
#ifndef NDEBUG
case ISD::LOAD:
case ISD::STORE:
diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.h b/llvm/lib/Target/Mips/MipsMachineFunction.h
index b7b748838569f..cff249e8d9ba8 100644
--- a/llvm/lib/Target/Mips/MipsMachineFunction.h
+++ b/llvm/lib/Target/Mips/MipsMachineFunction.h
@@ -62,6 +62,9 @@ class MipsFunctionInfo : public MachineFunctionInfo {
int getEhDataRegFI(unsigned Reg) const { return EhDataRegFI[Reg]; }
bool isEhDataRegFI(int FI) const;
+ void setGPGlobalRegister(bool Val) { GPIsGlobalRegister = Val; }
+ bool isGPGlobalRegister() const { return GPIsGlobalRegister; }
+
/// Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue
/// object representing a GOT entry for an external function.
MachinePointerInfo callPtrInfo(MachineFunction &MF, const char *ES);
@@ -126,6 +129,8 @@ class MipsFunctionInfo : public MachineFunctionInfo {
/// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the
/// O32 FPXX ABI is enabled. -1 is used to denote invalid index.
int MoveF64ViaSpillFI = -1;
+
+ bool GPIsGlobalRegister = false;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 948d4db8585db..16fafcffdaa68 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -89,20 +89,23 @@ MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
: CSR_Interrupt_32_SaveList;
}
+ bool GPIsGlobal = MF->getInfo<MipsFunctionInfo>()->isGPGlobalRegister();
// N64 ABI
if (Subtarget.isABI_N64()) {
if (Subtarget.isSingleFloat())
- return CSR_N64_SingleFloat_SaveList;
+ return GPIsGlobal ? CSR_N64_SingleFloat_NoGP_SaveList
+ : CSR_N64_SingleFloat_SaveList;
- return CSR_N64_SaveList;
+ return GPIsGlobal ? CSR_N64_NoGP_SaveList : CSR_N64_SaveList;
}
// N32 ABI
if (Subtarget.isABI_N32()) {
if (Subtarget.isSingleFloat())
- return CSR_N32_SingleFloat_SaveList;
+ return GPIsGlobal ? CSR_N32_SingleFloat_NoGP_SaveList
+ : CSR_N32_SingleFloat_SaveList;
- return CSR_N32_SaveList;
+ return GPIsGlobal ? CSR_N32_NoGP_SaveList : CSR_N32_SaveList;
}
// O32 ABI
@@ -122,6 +125,7 @@ const uint32_t *
MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID) const {
const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
+
// N64 ABI
if (Subtarget.isABI_N64()) {
if (Subtarget.isSingleFloat())
@@ -175,7 +179,8 @@ getReservedRegs(const MachineFunction &MF) const {
Reserved.set(R);
// For mno-abicalls, GP is a program invariant!
- if (!Subtarget.isABICalls()) {
+ bool GPIsGlobal = MF.getInfo<MipsFunctionInfo>()->isGPGlobalRegister();
+ if (!Subtarget.isABICalls() || GPIsGlobal) {
Reserved.set(Mips::GP);
Reserved.set(Mips::GP_64);
}
diff --git a/llvm/test/CodeGen/Mips/write_register_gp.ll b/llvm/test/CodeGen/Mips/write_register_gp.ll
new file mode 100644
index 0000000000000..02b434126af81
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/write_register_gp.ll
@@ -0,0 +1,18 @@
+; RUN: llc -mtriple=mips64el -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=MIPS64
+
+define void @setglobal(i64 %x) {
+; MIPS64-LABEL: setglobal:
+; MIPS64: # %bb.0: # %entry
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: move $gp, $4
+
+entry:
+ tail call void @llvm.write_register.i64(metadata !0, i64 %x)
+ ret void
+}
+
+declare void @llvm.write_register.i64(metadata, i64) #1
+
+!llvm.named.register.$28 = !{!0}
+!0 = !{!"$28"}
+
More information about the llvm-commits
mailing list