[llvm] [win/arm64] Enable tail call with inreg arguments when possible (PR #134671)
Hans Wennborg via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 8 00:49:22 PDT 2025
https://github.com/zmodem updated https://github.com/llvm/llvm-project/pull/134671
>From 62a35c522ddbf9e28c2b70ffcb7c84bbbc2b79b8 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans at chromium.org>
Date: Wed, 2 Apr 2025 16:04:50 +0200
Subject: [PATCH 1/4] [win/arm64] Enable tail call with inreg arguments when
possible
---
.../Target/AArch64/AArch64ISelLowering.cpp | 20 ++++++++++------
.../CodeGen/AArch64/arm64-windows-tailcall.ll | 24 +++++++++++++++++++
2 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 0534d2d546325..90ae1a7e57cdb 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8703,13 +8703,19 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
return false;
// On Windows, "inreg" attributes signify non-aggregate indirect returns.
- // In this case, it is necessary to save/restore X0 in the callee. Tail
- // call opt interferes with this. So we disable tail call opt when the
- // caller has an argument with "inreg" attribute.
-
- // FIXME: Check whether the callee also has an "inreg" argument.
- if (i->hasInRegAttr())
- return false;
+ // In this case, it is necessary to save X0/X1 in the callee and return it
+ // in X0. Tail call opt may interfere with this, so we disable tail call
+ // opt when the caller has an "inreg" attribute -- except if the callee
+ // also has that attribute on the same argument, and the same value is
+ // passed.
+ if (i->hasInRegAttr()) {
+ unsigned ArgNum = i - CallerF.arg_begin();
+ if (!CLI.CB || CLI.CB->arg_size() <= ArgNum ||
+ !CLI.CB->getParamAttr(ArgNum, Attribute::InReg).isValid() ||
+ CLI.CB->getArgOperand(ArgNum) != i) {
+ return false;
+ }
+ }
}
if (canGuaranteeTCO(CalleeCC, getTargetMachine().Options.GuaranteedTailCallOpt))
diff --git a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
index 55799d0dcb2d2..64491abd1bad7 100644
--- a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
@@ -16,3 +16,27 @@ entry:
}
declare dso_local void @"?foo"(ptr dereferenceable(4))
+
+
+declare void @inreg_callee(ptr, ptr inreg sret(%class.C))
+
+define void @inreg_caller_1(ptr %a, ptr inreg sret(%class.C) %b) {
+; A different value is passed to the inreg parameter, so tail call is not possible.
+; CHECK-LABEL: inreg_caller_1
+; CHECK: mov x19, x1
+; CHECK: bl inreg_callee
+; CHECK: mov x0, x19
+
+ tail call void @inreg_callee(ptr %b, ptr inreg sret(%class.C) %a)
+ ret void
+}
+
+define void @inreg_caller_2(ptr %a, ptr inreg sret(%class.C) %b) {
+; The inreg attribute and value lines up between caller and callee, so it can
+; be tail called.
+; CHECK-LABEL: inreg_caller_2
+; CHECK: b inreg_callee
+
+ tail call void @inreg_callee(ptr %a, ptr inreg sret(%class.C) %b)
+ ret void
+}
>From 8aff76cdc789a1a7939754fbf972003575e1eed5 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans at chromium.org>
Date: Tue, 8 Apr 2025 09:25:55 +0200
Subject: [PATCH 2/4] add sret checks
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 90ae1a7e57cdb..deb05b0dcb97c 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8712,6 +8712,8 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
unsigned ArgNum = i - CallerF.arg_begin();
if (!CLI.CB || CLI.CB->arg_size() <= ArgNum ||
!CLI.CB->getParamAttr(ArgNum, Attribute::InReg).isValid() ||
+ !i->hasStructRetAttr() ||
+ !CLI.CB->getParamAttr(ArgNum, Attribute::StructRet).isValid() ||
CLI.CB->getArgOperand(ArgNum) != i) {
return false;
}
>From 1e66e3e5340bc511442ad79f15dd541957962166 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans at chromium.org>
Date: Tue, 8 Apr 2025 09:30:01 +0200
Subject: [PATCH 3/4] typo
---
llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
index 64491abd1bad7..cd0a77a280aec 100644
--- a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
@@ -32,7 +32,7 @@ define void @inreg_caller_1(ptr %a, ptr inreg sret(%class.C) %b) {
}
define void @inreg_caller_2(ptr %a, ptr inreg sret(%class.C) %b) {
-; The inreg attribute and value lines up between caller and callee, so it can
+; The inreg attribute and value line up between caller and callee, so it can
; be tail called.
; CHECK-LABEL: inreg_caller_2
; CHECK: b inreg_callee
>From a50dc332e7093af6e9eb9a6ffd2c751d6e52095d Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans at chromium.org>
Date: Tue, 8 Apr 2025 09:46:14 +0200
Subject: [PATCH 4/4] break up the if statement
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index deb05b0dcb97c..4092680d3234f 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8709,12 +8709,13 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
// also has that attribute on the same argument, and the same value is
// passed.
if (i->hasInRegAttr()) {
- unsigned ArgNum = i - CallerF.arg_begin();
- if (!CLI.CB || CLI.CB->arg_size() <= ArgNum ||
- !CLI.CB->getParamAttr(ArgNum, Attribute::InReg).isValid() ||
- !i->hasStructRetAttr() ||
- !CLI.CB->getParamAttr(ArgNum, Attribute::StructRet).isValid() ||
- CLI.CB->getArgOperand(ArgNum) != i) {
+ unsigned ArgIdx = i - CallerF.arg_begin();
+ if (!CLI.CB || CLI.CB->arg_size() <= ArgIdx)
+ return false;
+ AttributeSet Attrs = CLI.CB->getParamAttributes(ArgIdx);
+ if (!Attrs.hasAttribute(Attribute::InReg) ||
+ !Attrs.hasAttribute(Attribute::StructRet) || !i->hasStructRetAttr() ||
+ CLI.CB->getArgOperand(ArgIdx) != i) {
return false;
}
}
More information about the llvm-commits
mailing list