[llvm] [MIPS][ISel] Fix musttail (PR #161860)
Djordje Todorovic via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 18 23:50:39 PDT 2025
https://github.com/djtodoro updated https://github.com/llvm/llvm-project/pull/161860
>From ac9497ed3fffb45a8044c043f703487baeedb4e5 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Fri, 3 Oct 2025 17:03:52 +0200
Subject: [PATCH 1/6] [MIPS][ISel] Fix musttail
Properly handle clang::musttail attribute on MIPS backend.
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 7 +++--
llvm/test/CodeGen/Mips/musttail.ll | 38 +++++++++++++++++++++++
2 files changed, 42 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/musttail.ll
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 881ba8e2f9eff..d79db127f01a2 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3407,7 +3407,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Check if it's really possible to do a tail call. Restrict it to functions
// that are part of this compilation unit.
bool InternalLinkage = false;
- if (IsTailCall) {
+ bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
+ if (IsTailCall && !IsMustTail) {
IsTailCall = isEligibleForTailCallOptimization(
CCInfo, StackSize, *MF.getInfo<MipsFunctionInfo>());
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
@@ -3416,9 +3417,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
G->getGlobal()->hasPrivateLinkage() ||
G->getGlobal()->hasHiddenVisibility() ||
G->getGlobal()->hasProtectedVisibility());
- }
+ }
}
- if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall())
+ if (!IsTailCall && IsMustTail)
report_fatal_error("failed to perform tail call elimination on a call "
"site marked musttail");
diff --git a/llvm/test/CodeGen/Mips/musttail.ll b/llvm/test/CodeGen/Mips/musttail.ll
new file mode 100644
index 0000000000000..d5f457f6eb665
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/musttail.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=mips-unknown-linux-gnu < %s | FileCheck %s --check-prefix=MIPS32
+; RUN: llc -mtriple=mips64-unknown-linux-gnu < %s | FileCheck %s --check-prefix=MIPS64
+
+; Test musttail support for MIPS
+
+declare void @external_func()
+
+; Test basic musttail with external function
+define void @test_musttail_external() {
+; MIPS32-LABEL: test_musttail_external:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: j external_func
+; MIPS32-NEXT: nop
+;
+; MIPS64-LABEL: test_musttail_external:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: j external_func
+; MIPS64-NEXT: nop
+ musttail call void @external_func()
+ ret void
+}
+
+declare i32 @callee_args(i32 %a, i32 %b, i32 %c)
+
+define i32 @test_musttail_args(i32 %x, i32 %y, i32 %z) {
+; MIPS32-LABEL: test_musttail_args:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: j callee_args
+; MIPS32-NEXT: nop
+;
+; MIPS64-LABEL: test_musttail_args:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: j callee_args
+; MIPS64-NEXT: nop
+ %ret = musttail call i32 @callee_args(i32 %x, i32 %y, i32 %z)
+ ret i32 %ret
+}
>From 9a77adf5a2d1217ac419413c06480f92998dafe8 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Tue, 7 Oct 2025 10:04:21 +0200
Subject: [PATCH 2/6] Address comments
---
llvm/lib/Target/Mips/Mips16ISelLowering.cpp | 2 +-
llvm/lib/Target/Mips/Mips16ISelLowering.h | 3 ++-
llvm/lib/Target/Mips/MipsISelLowering.cpp | 19 +++++++++++--------
llvm/lib/Target/Mips/MipsISelLowering.h | 3 ++-
llvm/lib/Target/Mips/MipsSEISelLowering.cpp | 4 ++--
llvm/lib/Target/Mips/MipsSEISelLowering.h | 3 ++-
llvm/test/CodeGen/Mips/musttail.ll | 19 ++-----------------
7 files changed, 22 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
index 330cb4e0e206f..e7144d1fecfb9 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -248,7 +248,7 @@ Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
bool Mips16TargetLowering::isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI) const {
+ const MipsFunctionInfo &FI, bool IsMustTail) const {
// No tail call optimization for mips16.
return false;
}
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.h b/llvm/lib/Target/Mips/Mips16ISelLowering.h
index f120cbbd24f91..8ac40644dce0a 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.h
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.h
@@ -33,7 +33,8 @@ namespace llvm {
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI) const override;
+ const MipsFunctionInfo &FI,
+ bool IsMustTail = false) const override;
void setMips16HardFloatLibCalls();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index d79db127f01a2..52a6e65abfd29 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3408,15 +3408,18 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// that are part of this compilation unit.
bool InternalLinkage = false;
bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
- if (IsTailCall && !IsMustTail) {
+ if (IsTailCall) {
IsTailCall = isEligibleForTailCallOptimization(
- CCInfo, StackSize, *MF.getInfo<MipsFunctionInfo>());
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- InternalLinkage = G->getGlobal()->hasInternalLinkage();
- IsTailCall &= (InternalLinkage || G->getGlobal()->hasLocalLinkage() ||
- G->getGlobal()->hasPrivateLinkage() ||
- G->getGlobal()->hasHiddenVisibility() ||
- G->getGlobal()->hasProtectedVisibility());
+ CCInfo, StackSize, *MF.getInfo<MipsFunctionInfo>(), IsMustTail);
+ if (IsTailCall) {
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ InternalLinkage = G->getGlobal()->hasInternalLinkage();
+ IsTailCall &= (InternalLinkage || G->getGlobal()->hasLocalLinkage() ||
+ G->getGlobal()->isDSOLocal() ||
+ G->getGlobal()->hasPrivateLinkage() ||
+ G->getGlobal()->hasHiddenVisibility() ||
+ G->getGlobal()->hasProtectedVisibility());
+ }
}
}
if (!IsTailCall && IsMustTail)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index c65c76ccffc75..3189f94046b35 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -598,7 +598,8 @@ class TargetRegisterClass;
virtual bool
isEligibleForTailCallOptimization(const CCState &CCInfo,
unsigned NextStackOffset,
- const MipsFunctionInfo &FI) const = 0;
+ const MipsFunctionInfo &FI,
+ bool IsMustTail = false) const = 0;
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index 71a70d9c2dd46..33e31bb06e50f 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -1180,8 +1180,8 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
bool MipsSETargetLowering::isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI) const {
- if (!UseMipsTailCalls)
+ const MipsFunctionInfo &FI, bool IsMustTail) const {
+ if (!UseMipsTailCalls && !IsMustTail)
return false;
// Exception has to be cleared with eret.
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.h b/llvm/lib/Target/Mips/MipsSEISelLowering.h
index 675131aefb6dd..7230e9cff6efa 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.h
@@ -65,7 +65,8 @@ class TargetRegisterClass;
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI) const override;
+ const MipsFunctionInfo &FI,
+ bool IsMustTail = false) const override;
void
getOpndList(SmallVectorImpl<SDValue> &Ops,
diff --git a/llvm/test/CodeGen/Mips/musttail.ll b/llvm/test/CodeGen/Mips/musttail.ll
index d5f457f6eb665..48d3d7178b203 100644
--- a/llvm/test/CodeGen/Mips/musttail.ll
+++ b/llvm/test/CodeGen/Mips/musttail.ll
@@ -4,25 +4,10 @@
; Test musttail support for MIPS
-declare void @external_func()
-
-; Test basic musttail with external function
-define void @test_musttail_external() {
-; MIPS32-LABEL: test_musttail_external:
-; MIPS32: # %bb.0:
-; MIPS32-NEXT: j external_func
-; MIPS32-NEXT: nop
-;
-; MIPS64-LABEL: test_musttail_external:
-; MIPS64: # %bb.0:
-; MIPS64-NEXT: j external_func
-; MIPS64-NEXT: nop
- musttail call void @external_func()
- ret void
+define dso_local i32 @callee_args(i32 %a, i32 %b, i32 %c) {
+ ret i32 %a;
}
-declare i32 @callee_args(i32 %a, i32 %b, i32 %c)
-
define i32 @test_musttail_args(i32 %x, i32 %y, i32 %z) {
; MIPS32-LABEL: test_musttail_args:
; MIPS32: # %bb.0:
>From 1e26120441a1278257561a7f10cd18056368ffca Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Tue, 7 Oct 2025 10:13:39 +0200
Subject: [PATCH 3/6] Apply clang-format
---
llvm/lib/Target/Mips/Mips16ISelLowering.cpp | 4 ++--
llvm/lib/Target/Mips/Mips16ISelLowering.h | 3 +--
llvm/lib/Target/Mips/MipsISelLowering.h | 8 +++-----
llvm/lib/Target/Mips/MipsSEISelLowering.cpp | 4 ++--
llvm/lib/Target/Mips/MipsSEISelLowering.h | 3 +--
5 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
index e7144d1fecfb9..72019008bbd1c 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -247,8 +247,8 @@ Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
}
bool Mips16TargetLowering::isEligibleForTailCallOptimization(
- const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail) const {
+ const CCState &CCInfo, unsigned NextStackOffset, const MipsFunctionInfo &FI,
+ bool IsMustTail) const {
// No tail call optimization for mips16.
return false;
}
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.h b/llvm/lib/Target/Mips/Mips16ISelLowering.h
index 8ac40644dce0a..6d0b909b748de 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.h
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.h
@@ -33,8 +33,7 @@ namespace llvm {
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI,
- bool IsMustTail = false) const override;
+ const MipsFunctionInfo &FI, bool IsMustTail = false) const override;
void setMips16HardFloatLibCalls();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 3189f94046b35..c8e0de89639a8 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -595,11 +595,9 @@ class TargetRegisterClass;
/// isEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization.
- virtual bool
- isEligibleForTailCallOptimization(const CCState &CCInfo,
- unsigned NextStackOffset,
- const MipsFunctionInfo &FI,
- bool IsMustTail = false) const = 0;
+ virtual bool isEligibleForTailCallOptimization(
+ const CCState &CCInfo, unsigned NextStackOffset,
+ const MipsFunctionInfo &FI, bool IsMustTail = false) const = 0;
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index 33e31bb06e50f..cb6bd9c385519 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -1179,8 +1179,8 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
}
bool MipsSETargetLowering::isEligibleForTailCallOptimization(
- const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail) const {
+ const CCState &CCInfo, unsigned NextStackOffset, const MipsFunctionInfo &FI,
+ bool IsMustTail) const {
if (!UseMipsTailCalls && !IsMustTail)
return false;
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.h b/llvm/lib/Target/Mips/MipsSEISelLowering.h
index 7230e9cff6efa..9a44957027dee 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.h
@@ -65,8 +65,7 @@ class TargetRegisterClass;
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI,
- bool IsMustTail = false) const override;
+ const MipsFunctionInfo &FI, bool IsMustTail = false) const override;
void
getOpndList(SmallVectorImpl<SDValue> &Ops,
>From 20d634f42afeb918f1a12422e9fb4d55550ecd70 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Fri, 17 Oct 2025 18:31:27 +0200
Subject: [PATCH 4/6] address comments
---
llvm/lib/Target/Mips/Mips16ISelLowering.h | 2 +-
llvm/lib/Target/Mips/MipsISelLowering.cpp | 13 ++--
llvm/lib/Target/Mips/MipsISelLowering.h | 2 +-
llvm/lib/Target/Mips/MipsSEISelLowering.h | 2 +-
llvm/test/CodeGen/Mips/musttail.ll | 74 +++++++++++++++++++++++
5 files changed, 84 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/Mips/Mips16ISelLowering.h b/llvm/lib/Target/Mips/Mips16ISelLowering.h
index 6d0b909b748de..ea6f049393327 100644
--- a/llvm/lib/Target/Mips/Mips16ISelLowering.h
+++ b/llvm/lib/Target/Mips/Mips16ISelLowering.h
@@ -33,7 +33,7 @@ namespace llvm {
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail = false) const override;
+ const MipsFunctionInfo &FI, bool IsMustTail) const override;
void setMips16HardFloatLibCalls();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 52a6e65abfd29..92404effe3896 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3404,19 +3404,20 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall())
CSInfo = MachineFunction::CallSiteInfo(*CB);
- // Check if it's really possible to do a tail call. Restrict it to functions
- // that are part of this compilation unit.
+ // Check if it's really possible to do a tail call.
+ // For non-musttail calls, restrict to functions that won't require $gp
+ // restoration. In PIC mode, calling external functions via tail call can
+ // cause issues with $gp register handling (see D24763).
bool InternalLinkage = false;
bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
if (IsTailCall) {
IsTailCall = isEligibleForTailCallOptimization(
CCInfo, StackSize, *MF.getInfo<MipsFunctionInfo>(), IsMustTail);
- if (IsTailCall) {
+ // For non-musttail calls, restrict to local or non-interposable functions
+ if (IsTailCall && !IsMustTail) {
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
InternalLinkage = G->getGlobal()->hasInternalLinkage();
- IsTailCall &= (InternalLinkage || G->getGlobal()->hasLocalLinkage() ||
- G->getGlobal()->isDSOLocal() ||
- G->getGlobal()->hasPrivateLinkage() ||
+ IsTailCall &= (G->getGlobal()->hasLocalLinkage() ||
G->getGlobal()->hasHiddenVisibility() ||
G->getGlobal()->hasProtectedVisibility());
}
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index c8e0de89639a8..866b2d36fb893 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -597,7 +597,7 @@ class TargetRegisterClass;
/// for tail call optimization.
virtual bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail = false) const = 0;
+ const MipsFunctionInfo &FI, bool IsMustTail) const = 0;
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.h b/llvm/lib/Target/Mips/MipsSEISelLowering.h
index 9a44957027dee..978abd4490c39 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.h
@@ -65,7 +65,7 @@ class TargetRegisterClass;
private:
bool isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail = false) const override;
+ const MipsFunctionInfo &FI, bool IsMustTail) const override;
void
getOpndList(SmallVectorImpl<SDValue> &Ops,
diff --git a/llvm/test/CodeGen/Mips/musttail.ll b/llvm/test/CodeGen/Mips/musttail.ll
index 48d3d7178b203..0bcce8882d6b0 100644
--- a/llvm/test/CodeGen/Mips/musttail.ll
+++ b/llvm/test/CodeGen/Mips/musttail.ll
@@ -21,3 +21,77 @@ define i32 @test_musttail_args(i32 %x, i32 %y, i32 %z) {
%ret = musttail call i32 @callee_args(i32 %x, i32 %y, i32 %z)
ret i32 %ret
}
+
+; Test musttail with many arguments that spill to stack (involves memory)
+; MIPS O32 ABI: first 4 args in $a0-$a3, rest on stack
+declare i32 @many_args_callee(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
+
+define i32 @test_musttail_many_args(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
+; MIPS32-LABEL: test_musttail_many_args:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: lw $1, 24($sp)
+; MIPS32-NEXT: lw $2, 20($sp)
+; MIPS32-NEXT: lw $3, 16($sp)
+; MIPS32-NEXT: sw $3, 16($sp)
+; MIPS32-NEXT: sw $2, 20($sp)
+; MIPS32-NEXT: sw $1, 24($sp)
+; MIPS32-NEXT: lw $1, 28($sp)
+; MIPS32-NEXT: j many_args_callee
+; MIPS32-NEXT: sw $1, 28($sp)
+;
+; MIPS64-LABEL: test_musttail_many_args:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: j many_args_callee
+; MIPS64-NEXT: nop
+ %ret = musttail call i32 @many_args_callee(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
+ ret i32 %ret
+}
+
+; Test musttail with large struct passed by value (involves memory)
+%struct.large = type { i32, i32, i32, i32, i32, i32, i32, i32 }
+
+declare i32 @callee_with_struct(%struct.large %s, i32 %x)
+
+define i32 @test_musttail_struct(%struct.large %s, i32 %x) {
+; MIPS32-LABEL: test_musttail_struct:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: lw $1, 28($sp)
+; MIPS32-NEXT: lw $2, 24($sp)
+; MIPS32-NEXT: lw $3, 20($sp)
+; MIPS32-NEXT: lw $8, 16($sp)
+; MIPS32-NEXT: sw $8, 16($sp)
+; MIPS32-NEXT: sw $3, 20($sp)
+; MIPS32-NEXT: sw $2, 24($sp)
+; MIPS32-NEXT: sw $1, 28($sp)
+; MIPS32-NEXT: lw $1, 32($sp)
+; MIPS32-NEXT: j callee_with_struct
+; MIPS32-NEXT: sw $1, 32($sp)
+;
+; MIPS64-LABEL: test_musttail_struct:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: ld $1, 0($sp)
+; MIPS64-NEXT: j callee_with_struct
+; MIPS64-NEXT: sd $1, 0($sp)
+ %ret = musttail call i32 @callee_with_struct(%struct.large %s, i32 %x)
+ ret i32 %ret
+}
+
+; Test musttail with mixed int and float arguments that use stack
+declare float @mixed_args_callee(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f)
+
+define float @test_musttail_mixed_args(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f) {
+; MIPS32-LABEL: test_musttail_mixed_args:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: lw $1, 16($sp)
+; MIPS32-NEXT: sw $1, 16($sp)
+; MIPS32-NEXT: lwc1 $f0, 20($sp)
+; MIPS32-NEXT: j mixed_args_callee
+; MIPS32-NEXT: swc1 $f0, 20($sp)
+;
+; MIPS64-LABEL: test_musttail_mixed_args:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: j mixed_args_callee
+; MIPS64-NEXT: nop
+ %ret = musttail call float @mixed_args_callee(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f)
+ ret float %ret
+}
>From eaa5678dfed669abb8d733b2243dc1ced89d73f0 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Sat, 18 Oct 2025 20:40:58 +0200
Subject: [PATCH 5/6] Clean up and improve tests
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 3 +--
llvm/lib/Target/Mips/MipsSEISelLowering.h | 7 ++++---
llvm/test/CodeGen/Mips/musttail.ll | 17 +++++++++++++++++
3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 92404effe3896..262c2212b1a4f 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3408,7 +3408,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// For non-musttail calls, restrict to functions that won't require $gp
// restoration. In PIC mode, calling external functions via tail call can
// cause issues with $gp register handling (see D24763).
- bool InternalLinkage = false;
bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
if (IsTailCall) {
IsTailCall = isEligibleForTailCallOptimization(
@@ -3416,7 +3415,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// For non-musttail calls, restrict to local or non-interposable functions
if (IsTailCall && !IsMustTail) {
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- InternalLinkage = G->getGlobal()->hasInternalLinkage();
IsTailCall &= (G->getGlobal()->hasLocalLinkage() ||
G->getGlobal()->hasHiddenVisibility() ||
G->getGlobal()->hasProtectedVisibility());
@@ -3600,6 +3598,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
}
}
+ bool InternalLinkage = false;
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
if (Subtarget.isTargetCOFF() &&
G->getGlobal()->hasDLLImportStorageClass()) {
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.h b/llvm/lib/Target/Mips/MipsSEISelLowering.h
index 978abd4490c39..392e8dc3dbb11 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.h
@@ -63,9 +63,10 @@ class TargetRegisterClass;
const TargetRegisterClass *getRepRegClassFor(MVT VT) const override;
private:
- bool isEligibleForTailCallOptimization(
- const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail) const override;
+ bool isEligibleForTailCallOptimization(const CCState &CCInfo,
+ unsigned NextStackOffset,
+ const MipsFunctionInfo &FI,
+ bool IsMustTail) const override;
void
getOpndList(SmallVectorImpl<SDValue> &Ops,
diff --git a/llvm/test/CodeGen/Mips/musttail.ll b/llvm/test/CodeGen/Mips/musttail.ll
index 0bcce8882d6b0..c486ea5c59eea 100644
--- a/llvm/test/CodeGen/Mips/musttail.ll
+++ b/llvm/test/CodeGen/Mips/musttail.ll
@@ -95,3 +95,20 @@ define float @test_musttail_mixed_args(i32 %a, float %b, i32 %c, float %d, i32 %
%ret = musttail call float @mixed_args_callee(i32 %a, float %b, i32 %c, float %d, i32 %e, float %f)
ret float %ret
}
+
+; Test musttail with indirect call
+define i32 @test_musttail_fptr(ptr %fptr, i32 %x) {
+; MIPS32-LABEL: test_musttail_fptr:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: move $25, $4
+; MIPS32-NEXT: jr $25
+; MIPS32-NEXT: nop
+;
+; MIPS64-LABEL: test_musttail_fptr:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: move $25, $4
+; MIPS64-NEXT: jr $25
+; MIPS64-NEXT: nop
+ %ret = musttail call i32 %fptr(ptr %fptr, i32 %x)
+ ret i32 %ret
+}
>From 54412fe1481c39b8537ae847a9b056ed726b2c88 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Sun, 19 Oct 2025 08:50:16 +0200
Subject: [PATCH 6/6] apply clang-format
---
llvm/lib/Target/Mips/MipsISelLowering.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 866b2d36fb893..3aa0a0d3ad7c4 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -595,9 +595,10 @@ class TargetRegisterClass;
/// isEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization.
- virtual bool isEligibleForTailCallOptimization(
- const CCState &CCInfo, unsigned NextStackOffset,
- const MipsFunctionInfo &FI, bool IsMustTail) const = 0;
+ virtual bool isEligibleForTailCallOptimization(const CCState &CCInfo,
+ unsigned NextStackOffset,
+ const MipsFunctionInfo &FI,
+ bool IsMustTail) const = 0;
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
More information about the llvm-commits
mailing list