https://github.com/brandtbucher updated
https://github.com/llvm/llvm-project/pull/88333
>From f797b695ce38f46563f3724dcffee4005c65c659 Mon Sep 17 00:00:00 2001
From: Brandt Bucher
Date: Wed, 10 Apr 2024 17:03:19 -0700
Subject: [PATCH 1/2] Prefer non-volatile registers for preserve_none
Use non-volatile registers for the first four (six
on Windows) registers used for preserve_none
argument passing. This allows these registers to
stay "pinned" across a chain of tail calls, even
when the body of a preserve_none function contains
other calls.
---
llvm/lib/Target/X86/X86CallingConv.td | 10 ++--
llvm/test/CodeGen/X86/preserve_nonecc_call.ll | 50 +--
.../CodeGen/X86/preserve_nonecc_call_win.ll | 21
3 files changed, 61 insertions(+), 20 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/preserve_nonecc_call_win.ll
diff --git a/llvm/lib/Target/X86/X86CallingConv.td
b/llvm/lib/Target/X86/X86CallingConv.td
index 12178bcaf042db..9ec68bfb8e0f7e 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -1063,11 +1063,13 @@ def CC_X86_64_Preserve_None : CallingConv<[
// - R10'nest' parameter
// - RBXbase pointer
// - R16 - R31 these are not available everywhere
- CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D,
-R11D, R12D, R13D, R14D, R15D, EAX]>>,
+ // Use non-volatile registers first, so functions using this convention can
+ // call "normal" functions without saving and restoring incoming values:
+ CCIfType<[i32], CCAssignToReg<[R12D, R13D, R14D, R15D, EDI, ESI,
+ EDX, ECX, R8D, R9D, R11D, EAX]>>,
- CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8, R9,
- R11, R12, R13, R14, R15, RAX]>>,
+ CCIfType<[i64], CCAssignToReg<[R12, R13, R14, R15, RDI, RSI,
+ RDX, RCX, R8, R9, R11, RAX]>>,
// Otherwise it's the same as the regular C calling convention.
CCDelegateTo
diff --git a/llvm/test/CodeGen/X86/preserve_nonecc_call.ll
b/llvm/test/CodeGen/X86/preserve_nonecc_call.ll
index e4ad056913c5dc..500ebb139811aa 100644
--- a/llvm/test/CodeGen/X86/preserve_nonecc_call.ll
+++ b/llvm/test/CodeGen/X86/preserve_nonecc_call.ll
@@ -27,6 +27,7 @@ define void @caller1(ptr %a) {
; CHECK-NEXT:.cfi_offset %r13, -32
; CHECK-NEXT:.cfi_offset %r14, -24
; CHECK-NEXT:.cfi_offset %r15, -16
+; CHECK-NEXT:movq %rdi, %r12
; CHECK-NEXT:callq callee@PLT
; CHECK-NEXT:popq %rbx
; CHECK-NEXT:.cfi_def_cfa_offset 40
@@ -61,17 +62,17 @@ define preserve_nonecc i64 @callee_with_many_param(i64 %a1,
i64 %a2, i64 %a3, i6
; CHECK: # %bb.0:
; CHECK-NEXT:pushq %rax
; CHECK-NEXT:.cfi_def_cfa_offset 16
+; CHECK-NEXT:movq %r13, %r12
+; CHECK-NEXT:movq %r14, %r13
+; CHECK-NEXT:movq %r15, %r14
+; CHECK-NEXT:movq %rdi, %r15
; CHECK-NEXT:movq %rsi, %rdi
; CHECK-NEXT:movq %rdx, %rsi
; CHECK-NEXT:movq %rcx, %rdx
; CHECK-NEXT:movq %r8, %rcx
; CHECK-NEXT:movq %r9, %r8
; CHECK-NEXT:movq %r11, %r9
-; CHECK-NEXT:movq %r12, %r11
-; CHECK-NEXT:movq %r13, %r12
-; CHECK-NEXT:movq %r14, %r13
-; CHECK-NEXT:movq %r15, %r14
-; CHECK-NEXT:movq %rax, %r15
+; CHECK-NEXT:movq %rax, %r11
; CHECK-NEXT:callq callee_with_many_param2@PLT
; CHECK-NEXT:popq %rcx
; CHECK-NEXT:.cfi_def_cfa_offset 8
@@ -98,17 +99,17 @@ define i64 @caller3() {
; CHECK-NEXT:.cfi_offset %r13, -32
; CHECK-NEXT:.cfi_offset %r14, -24
; CHECK-NEXT:.cfi_offset %r15, -16
-; CHECK-NEXT:movl $1, %edi
-; CHECK-NEXT:movl $2, %esi
-; CHECK-NEXT:movl $3, %edx
-; CHECK-NEXT:movl $4, %ecx
-; CHECK-NEXT:movl $5, %r8d
-; CHECK-NEXT:movl $6, %r9d
-; CHECK-NEXT:movl $7, %r11d
-; CHECK-NEXT:movl $8, %r12d
-; CHECK-NEXT:movl $9, %r13d
-; CHECK-NEXT:movl $10, %r14d
-; CHECK-NEXT:movl $11, %r15d
+; CHECK-NEXT:movl $1, %r12d
+; CHECK-NEXT:movl $2, %r13d
+; CHECK-NEXT:movl $3, %r14d
+; CHECK-NEXT:movl $4, %r15d
+; CHECK-NEXT:movl $5, %edi
+; CHECK-NEXT:movl $6, %esi
+; CHECK-NEXT:movl $7, %edx
+; CHECK-NEXT:movl $8, %ecx
+; CHECK-NEXT:movl $9, %r8d
+; CHECK-NEXT:movl $10, %r9d
+; CHECK-NEXT:movl $11, %r11d
; CHECK-NEXT:movl $12, %eax
; CHECK-NEXT:callq callee_with_many_param@PLT
; CHECK-NEXT:popq %rbx
@@ -125,3 +126,20 @@ define i64 @caller3() {
%ret = call preserve_nonecc i64 @callee_with_many_param(i64 1, i64 2, i64 3,
i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12)
ret i64 %ret
}
+
+; Non-volatile registers are used to pass the first few parameters.
+declare void @boring()
+declare preserve_nonecc void @continuation(ptr, ptr, ptr, ptr)
+define preserve_nonecc void @entry(ptr %r12, ptr %r13, ptr %r14, ptr %r15) {
+; CHECK-LABEL: entry:
+; CHECK: # %bb.0:
+; CHECK-NEXT:pushq %rax
+;