Skip to content

Commit f797b69

Browse files
committed
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.
1 parent 04bf1a4 commit f797b69

File tree

3 files changed

+61
-20
lines changed

3 files changed

+61
-20
lines changed

llvm/lib/Target/X86/X86CallingConv.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,11 +1063,13 @@ def CC_X86_64_Preserve_None : CallingConv<[
10631063
// - R10 'nest' parameter
10641064
// - RBX base pointer
10651065
// - R16 - R31 these are not available everywhere
1066-
CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D,
1067-
R11D, R12D, R13D, R14D, R15D, EAX]>>,
1066+
// Use non-volatile registers first, so functions using this convention can
1067+
// call "normal" functions without saving and restoring incoming values:
1068+
CCIfType<[i32], CCAssignToReg<[R12D, R13D, R14D, R15D, EDI, ESI,
1069+
EDX, ECX, R8D, R9D, R11D, EAX]>>,
10681070

1069-
CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8, R9,
1070-
R11, R12, R13, R14, R15, RAX]>>,
1071+
CCIfType<[i64], CCAssignToReg<[R12, R13, R14, R15, RDI, RSI,
1072+
RDX, RCX, R8, R9, R11, RAX]>>,
10711073

10721074
// Otherwise it's the same as the regular C calling convention.
10731075
CCDelegateTo<CC_X86_64_C>

llvm/test/CodeGen/X86/preserve_nonecc_call.ll

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ define void @caller1(ptr %a) {
2727
; CHECK-NEXT: .cfi_offset %r13, -32
2828
; CHECK-NEXT: .cfi_offset %r14, -24
2929
; CHECK-NEXT: .cfi_offset %r15, -16
30+
; CHECK-NEXT: movq %rdi, %r12
3031
; CHECK-NEXT: callq callee@PLT
3132
; CHECK-NEXT: popq %rbx
3233
; 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
6162
; CHECK: # %bb.0:
6263
; CHECK-NEXT: pushq %rax
6364
; CHECK-NEXT: .cfi_def_cfa_offset 16
65+
; CHECK-NEXT: movq %r13, %r12
66+
; CHECK-NEXT: movq %r14, %r13
67+
; CHECK-NEXT: movq %r15, %r14
68+
; CHECK-NEXT: movq %rdi, %r15
6469
; CHECK-NEXT: movq %rsi, %rdi
6570
; CHECK-NEXT: movq %rdx, %rsi
6671
; CHECK-NEXT: movq %rcx, %rdx
6772
; CHECK-NEXT: movq %r8, %rcx
6873
; CHECK-NEXT: movq %r9, %r8
6974
; CHECK-NEXT: movq %r11, %r9
70-
; CHECK-NEXT: movq %r12, %r11
71-
; CHECK-NEXT: movq %r13, %r12
72-
; CHECK-NEXT: movq %r14, %r13
73-
; CHECK-NEXT: movq %r15, %r14
74-
; CHECK-NEXT: movq %rax, %r15
75+
; CHECK-NEXT: movq %rax, %r11
7576
; CHECK-NEXT: callq callee_with_many_param2@PLT
7677
; CHECK-NEXT: popq %rcx
7778
; CHECK-NEXT: .cfi_def_cfa_offset 8
@@ -98,17 +99,17 @@ define i64 @caller3() {
9899
; CHECK-NEXT: .cfi_offset %r13, -32
99100
; CHECK-NEXT: .cfi_offset %r14, -24
100101
; CHECK-NEXT: .cfi_offset %r15, -16
101-
; CHECK-NEXT: movl $1, %edi
102-
; CHECK-NEXT: movl $2, %esi
103-
; CHECK-NEXT: movl $3, %edx
104-
; CHECK-NEXT: movl $4, %ecx
105-
; CHECK-NEXT: movl $5, %r8d
106-
; CHECK-NEXT: movl $6, %r9d
107-
; CHECK-NEXT: movl $7, %r11d
108-
; CHECK-NEXT: movl $8, %r12d
109-
; CHECK-NEXT: movl $9, %r13d
110-
; CHECK-NEXT: movl $10, %r14d
111-
; CHECK-NEXT: movl $11, %r15d
102+
; CHECK-NEXT: movl $1, %r12d
103+
; CHECK-NEXT: movl $2, %r13d
104+
; CHECK-NEXT: movl $3, %r14d
105+
; CHECK-NEXT: movl $4, %r15d
106+
; CHECK-NEXT: movl $5, %edi
107+
; CHECK-NEXT: movl $6, %esi
108+
; CHECK-NEXT: movl $7, %edx
109+
; CHECK-NEXT: movl $8, %ecx
110+
; CHECK-NEXT: movl $9, %r8d
111+
; CHECK-NEXT: movl $10, %r9d
112+
; CHECK-NEXT: movl $11, %r11d
112113
; CHECK-NEXT: movl $12, %eax
113114
; CHECK-NEXT: callq callee_with_many_param@PLT
114115
; CHECK-NEXT: popq %rbx
@@ -125,3 +126,20 @@ define i64 @caller3() {
125126
%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)
126127
ret i64 %ret
127128
}
129+
130+
; Non-volatile registers are used to pass the first few parameters.
131+
declare void @boring()
132+
declare preserve_nonecc void @continuation(ptr, ptr, ptr, ptr)
133+
define preserve_nonecc void @entry(ptr %r12, ptr %r13, ptr %r14, ptr %r15) {
134+
; CHECK-LABEL: entry:
135+
; CHECK: # %bb.0:
136+
; CHECK-NEXT: pushq %rax
137+
; CHECK-NEXT: .cfi_def_cfa_offset 16
138+
; CHECK-NEXT: callq boring@PLT
139+
; CHECK-NEXT: popq %rax
140+
; CHECK-NEXT: .cfi_def_cfa_offset 8
141+
; CHECK-NEXT: jmp continuation@PLT # TAILCALL
142+
call void @boring()
143+
musttail call preserve_nonecc void @continuation(ptr %r12, ptr %r13, ptr %r14, ptr %r15)
144+
ret void
145+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2+
; RUN: llc -mtriple=x86_64-pc-windows-msvc -mcpu=corei7 < %s | FileCheck %s
3+
4+
; Non-volatile registers are used to pass the first few parameters.
5+
declare void @boring()
6+
declare preserve_nonecc void @continuation(ptr, ptr, ptr, ptr, ptr, ptr)
7+
define preserve_nonecc void @entry(ptr %r12, ptr %r13, ptr %r14, ptr %r15, ptr %rdi, ptr %rsi) {
8+
; CHECK-LABEL: entry:
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: subq $40, %rsp
11+
; CHECK-NEXT: .seh_stackalloc 40
12+
; CHECK-NEXT: .seh_endprologue
13+
; CHECK-NEXT: callq boring
14+
; CHECK-NEXT: nop
15+
; CHECK-NEXT: addq $40, %rsp
16+
; CHECK-NEXT: jmp continuation # TAILCALL
17+
; CHECK-NEXT: .seh_endproc
18+
call void @boring()
19+
musttail call preserve_nonecc void @continuation(ptr %r12, ptr %r13, ptr %r14, ptr %r15, ptr %rdi, ptr %rsi)
20+
ret void
21+
}

0 commit comments

Comments
 (0)