[llvm] f6c7bae - [Win/x64] Update preserve_most to treat XMM registers like C (#73866)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 4 11:53:41 PST 2023
Author: Seth Brenith
Date: 2023-12-04T11:53:36-08:00
New Revision: f6c7baea098aac03687f5041fc860ca95f070e4e
URL: https://github.com/llvm/llvm-project/commit/f6c7baea098aac03687f5041fc860ca95f070e4e
DIFF: https://github.com/llvm/llvm-project/commit/f6c7baea098aac03687f5041fc860ca95f070e4e.diff
LOG: [Win/x64] Update preserve_most to treat XMM registers like C (#73866)
As [scottmcm
described](https://discourse.llvm.org/t/conv-c-and-conv-preservemost-mix-badly-on-windows-x64/73054),
the `preserve_most` calling convention, as currently implemented, is a
bad fit for Windows on x64. The intent of `preserve_most` is "to make
the code in the caller as unintrusive as possible", but `preserve_most`
causes the caller to spill and restore ten SIMD registers. It would be
preferable to make `preserve_most` treat the XMM registers however the C
calling convention does on the target operating system.
This is a breaking change, but the documentation indicates that
`preserve_most` is still experimental, so I believe that ABI
compatibility is not yet a requirement.
Added:
llvm/test/CodeGen/X86/preserve_mostcc64_win.ll
Modified:
llvm/docs/LangRef.rst
llvm/lib/Target/X86/X86CallingConv.td
llvm/lib/Target/X86/X86RegisterInfo.cpp
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index af064d7ac2195..4bd19a332d8d8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -365,8 +365,9 @@ added in the future:
- On X86-64 the callee preserves all general purpose registers, except for
R11 and return registers, if any. R11 can be used as a scratch register.
- Floating-point registers (XMMs/YMMs) are not preserved and need to be
- saved by the caller.
+ The treatment of floating-point registers (XMMs/YMMs) matches the OS's C
+ calling convention: on most platforms, they are not preserved and need to
+ be saved by the caller, but on Windows, xmm6-xmm15 are preserved.
- On AArch64 the callee preserve all general purpose registers, except X0-X8
and X16-X18.
diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td
index 27e4fe0cb7a02..16014d6a2f602 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -1151,6 +1151,9 @@ def CSR_64_CXX_TLS_Darwin_ViaCopy : CalleeSavedRegs<(sub CSR_64_TLS_Darwin, RBP)
def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI,
R8, R9, R10)>;
+def CSR_Win64_RT_MostRegs : CalleeSavedRegs<(add CSR_64_RT_MostRegs,
+ (sequence "XMM%u", 6, 15))>;
+
// All registers - except r11 and return registers.
def CSR_64_RT_AllRegs : CalleeSavedRegs<(add CSR_64_RT_MostRegs,
(sequence "XMM%u", 0, 15))>;
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 379a9d448a963..5c32519dab371 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -310,7 +310,8 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_64_AllRegs_AVX_SaveList;
return CSR_64_AllRegs_SaveList;
case CallingConv::PreserveMost:
- return CSR_64_RT_MostRegs_SaveList;
+ return IsWin64 ? CSR_Win64_RT_MostRegs_SaveList
+ : CSR_64_RT_MostRegs_SaveList;
case CallingConv::PreserveAll:
if (HasAVX)
return CSR_64_RT_AllRegs_AVX_SaveList;
@@ -431,7 +432,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
return CSR_64_AllRegs_AVX_RegMask;
return CSR_64_AllRegs_RegMask;
case CallingConv::PreserveMost:
- return CSR_64_RT_MostRegs_RegMask;
+ return IsWin64 ? CSR_Win64_RT_MostRegs_RegMask : CSR_64_RT_MostRegs_RegMask;
case CallingConv::PreserveAll:
if (HasAVX)
return CSR_64_RT_AllRegs_AVX_RegMask;
diff --git a/llvm/test/CodeGen/X86/preserve_mostcc64_win.ll b/llvm/test/CodeGen/X86/preserve_mostcc64_win.ll
new file mode 100644
index 0000000000000..7042a2e77da1b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/preserve_mostcc64_win.ll
@@ -0,0 +1,91 @@
+; RUN: sed -e "s/RETTYPE/void/;s/RETVAL//" %s | llc -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck --check-prefixes=ALL,VOID %s
+; RUN: sed -e "s/RETTYPE/i32/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck --check-prefixes=ALL,INT %s
+; RUN: sed -e "s/RETTYPE/\{i64\,i64\}/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-win32 -mcpu=corei7 | FileCheck --check-prefixes=ALL,INT128 %s
+
+; Every GPR should be saved, except r11 and return registers.
+; XMM registers 6-15 should also be saved.
+define preserve_mostcc RETTYPE @preserve_mostcc1(i64, i64, double, double) nounwind {
+entry:
+;ALL-LABEL: preserve_mostcc1
+;ALL: pushq %r10
+;ALL-NEXT: pushq %r9
+;ALL-NEXT: pushq %r8
+;ALL-NEXT: pushq %rdi
+;ALL-NEXT: pushq %rsi
+;VOID-NEXT: pushq %rdx
+;INT-NEXT: pushq %rdx
+;INT128-NOT: pushq %rdx
+;ALL-NEXT: pushq %rcx
+;VOID-NEXT: pushq %rax
+;INT-NOT: pushq %rax
+;INT128-NOT: pushq %rax
+;ALL-NEXT: pushq %rbp
+;ALL-NEXT: pushq %r15
+;ALL-NEXT: pushq %r14
+;ALL-NEXT: pushq %r13
+;ALL-NEXT: pushq %r12
+;ALL-NEXT: pushq %rbx
+;ALL: movaps %xmm15
+;ALL-NEXT: movaps %xmm14
+;ALL-NEXT: movaps %xmm13
+;ALL-NEXT: movaps %xmm12
+;ALL-NEXT: movaps %xmm11
+;ALL-NEXT: movaps %xmm10
+;ALL-NEXT: movaps %xmm9
+;ALL-NEXT: movaps %xmm8
+;ALL-NEXT: movaps %xmm7
+;ALL-NEXT: movaps %xmm6
+;ALL-NOT: movaps %xmm5
+;ALL-NOT: movaps %xmm4
+;ALL-NOT: movaps %xmm3
+;ALL-NOT: movaps %xmm2
+;ALL-NOT: movaps %xmm1
+;ALL-NOT: movaps %xmm0
+;ALL-NOT: movaps {{.*}} %xmm0
+;ALL-NOT: movaps {{.*}} %xmm1
+;ALL-NOT: movaps {{.*}} %xmm2
+;ALL-NOT: movaps {{.*}} %xmm3
+;ALL-NOT: movaps {{.*}} %xmm4
+;ALL-NOT: movaps {{.*}} %xmm5
+;ALL: movaps {{.*}} %xmm6
+;ALL-NEXT: movaps {{.*}} %xmm7
+;ALL-NEXT: movaps {{.*}} %xmm8
+;ALL-NEXT: movaps {{.*}} %xmm9
+;ALL-NEXT: movaps {{.*}} %xmm10
+;ALL-NEXT: movaps {{.*}} %xmm11
+;ALL-NEXT: movaps {{.*}} %xmm12
+;ALL-NEXT: movaps {{.*}} %xmm13
+;ALL-NEXT: movaps {{.*}} %xmm14
+;ALL-NEXT: movaps {{.*}} %xmm15
+;ALL: popq %rbx
+;ALL-NEXT: popq %r12
+;ALL-NEXT: popq %r13
+;ALL-NEXT: popq %r14
+;ALL-NEXT: popq %r15
+;ALL-NEXT: popq %rbp
+;VOID-NEXT: popq %rax
+;INT-NOT: popq %rax
+;INT128-NOT: popq %rax
+;ALL-NEXT: popq %rcx
+;VOID-NEXT: popq %rdx
+;INT-NEXT: popq %rdx
+;INT128-NOT: popq %rdx
+;ALL-NEXT: popq %rsi
+;ALL-NEXT: popq %rdi
+;ALL-NEXT: popq %r8
+;ALL-NEXT: popq %r9
+;ALL-NEXT: popq %r10
+ call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{rbp},~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15}"()
+ ret RETTYPE RETVAL
+}
+
+; Make sure XMMs are not saved before the call
+declare preserve_mostcc RETTYPE @foo(i64, i64, double, double)
+define void @preserve_mostcc2() nounwind {
+entry:
+;ALL-LABEL: preserve_mostcc2
+;ALL-NOT: movaps
+;ALL-NOT: {{.*xmm[0-1,4-9].*}}
+ call preserve_mostcc RETTYPE @foo(i64 1, i64 2, double 3.0, double 4.0)
+ ret void
+}
More information about the llvm-commits
mailing list