[llvm] Update preserve_most to treat XMM registers like C (PR #73866)
Seth Brenith via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 29 14:59:39 PST 2023
https://github.com/sethbrenith updated https://github.com/llvm/llvm-project/pull/73866
>From 4a3a38c5171d4e5f12ea627b33973420418c1c6b Mon Sep 17 00:00:00 2001
From: Seth Brenith <seth.brenith at microsoft.com>
Date: Wed, 29 Nov 2023 14:00:36 -0800
Subject: [PATCH] Update preserve_most to treat XMM registers like C
---
llvm/docs/LangRef.rst | 5 +-
llvm/lib/Target/X86/X86CallingConv.td | 3 +
llvm/lib/Target/X86/X86RegisterInfo.cpp | 5 +-
.../test/CodeGen/X86/preserve_mostcc64_win.ll | 91 +++++++++++++++++++
4 files changed, 100 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/preserve_mostcc64_win.ll
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index e448c5ed5c5d947..29257933cc62b5b 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -362,8 +362,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 27e4fe0cb7a02fa..16014d6a2f60241 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 379a9d448a963ca..5c32519dab3714f 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 000000000000000..7042a2e77da1b6a
--- /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