Skip to content

Commit 0276fa8

Browse files
author
Anton Bikineev
committed
[X86][ABI] Don't preserve return regs for preserve_all/preserve_most CCs
Currently both calling conventions preserve registers that are used to store a return value. This causes the returned value to be lost: define i32 @bar() { %1 = call preserve_mostcc i32 @foo() ret i32 %1 } define preserve_mostcc i32 @foo() { ret i32 2 ; preserve_mostcc will restore %rax, ; whatever it was before the call. } This contradicts the current documentation (preserve_allcc "behaves identical to the `C` calling conventions on how arguments and return values are passed") and also breaks [[clang::preserve_most]]. This change makes CSRs be preserved iff they are not used to store a return value (e.g. %rax for scalars, {%rax:%rdx} for __int128, %xmm0 for double). For void functions no additional registers are preserved, i.e. the behaviour is backward compatible with existing code. Differential Revision: https://reviews.llvm.org/D141020
1 parent 291a7fc commit 0276fa8

File tree

7 files changed

+334
-135
lines changed

7 files changed

+334
-135
lines changed

llvm/docs/LangRef.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,9 @@ added in the future:
366366
apply for values returned in callee-saved registers.
367367

368368
- On X86-64 the callee preserves all general purpose registers, except for
369-
R11. R11 can be used as a scratch register. Floating-point registers
370-
(XMMs/YMMs) are not preserved and need to be saved by the caller.
369+
R11 and return registers, if any. R11 can be used as a scratch register.
370+
Floating-point registers (XMMs/YMMs) are not preserved and need to be
371+
saved by the caller.
371372

372373
The idea behind this convention is to support calls to runtime functions
373374
that have a hot path and a cold path. The hot path is usually a small piece

llvm/lib/Target/X86/X86CallingConv.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,11 +1154,11 @@ def CSR_64_CXX_TLS_Darwin_PE : CalleeSavedRegs<(add RBP)>;
11541154
// CSRs that are handled explicitly via copies.
11551155
def CSR_64_CXX_TLS_Darwin_ViaCopy : CalleeSavedRegs<(sub CSR_64_TLS_Darwin, RBP)>;
11561156

1157-
// All GPRs - except r11
1157+
// All GPRs - except r11 and return registers.
11581158
def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI,
11591159
R8, R9, R10)>;
11601160

1161-
// All registers - except r11
1161+
// All registers - except r11 and return registers.
11621162
def CSR_64_RT_AllRegs : CalleeSavedRegs<(add CSR_64_RT_MostRegs,
11631163
(sequence "XMM%u", 0, 15))>;
11641164
def CSR_64_RT_AllRegs_AVX : CalleeSavedRegs<(add CSR_64_RT_MostRegs,

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ static void errorUnsupported(SelectionDAG &DAG, const SDLoc &dl,
104104
DiagnosticInfoUnsupported(MF.getFunction(), Msg, dl.getDebugLoc()));
105105
}
106106

107+
/// Returns true if a CC can dynamically exclude a register from the list of
108+
/// callee-saved-registers (TargetRegistryInfo::getCalleeSavedRegs()) based on
109+
/// params/returns.
110+
static bool shouldDisableCalleeSavedRegisterCC(CallingConv::ID CC) {
111+
switch (CC) {
112+
default:
113+
return false;
114+
case CallingConv::X86_RegCall:
115+
case CallingConv::PreserveMost:
116+
case CallingConv::PreserveAll:
117+
return true;
118+
}
119+
}
120+
107121
X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
108122
const X86Subtarget &STI)
109123
: TargetLowering(TM), Subtarget(STI) {
@@ -3167,7 +3181,7 @@ X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
31673181
// In some cases we need to disable registers from the default CSR list.
31683182
// For example, when they are used for argument passing.
31693183
bool ShouldDisableCalleeSavedRegister =
3170-
CallConv == CallingConv::X86_RegCall ||
3184+
shouldDisableCalleeSavedRegisterCC(CallConv) ||
31713185
MF.getFunction().hasFnAttribute("no_caller_saved_registers");
31723186

31733187
if (CallConv == CallingConv::X86_INTR && !Outs.empty())
@@ -4319,7 +4333,7 @@ SDValue X86TargetLowering::LowerFormalArguments(
43194333
}
43204334
}
43214335

4322-
if (CallConv == CallingConv::X86_RegCall ||
4336+
if (shouldDisableCalleeSavedRegisterCC(CallConv) ||
43234337
F.hasFnAttribute("no_caller_saved_registers")) {
43244338
MachineRegisterInfo &MRI = MF.getRegInfo();
43254339
for (std::pair<Register, Register> Pair : MRI.liveins())
@@ -4880,7 +4894,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
48804894

48814895
// In some calling conventions we need to remove the used physical registers
48824896
// from the reg mask.
4883-
if (CallConv == CallingConv::X86_RegCall || HasNCSR) {
4897+
if (shouldDisableCalleeSavedRegisterCC(CallConv) || HasNCSR) {
48844898
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
48854899

48864900
// Allocate a new Reg Mask and copy Mask.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck --check-prefixes=ALL,SSE %s
2+
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx | FileCheck --check-prefixes=ALL,AVX %s
3+
4+
define preserve_allcc double @preserve_allcc1() nounwind {
5+
entry:
6+
;ALL-LABEL: preserve_allcc1
7+
;SSE: movaps %xmm1
8+
;SSE-NOT: movaps %xmm0
9+
;AVX: vmovups %ymm1
10+
;AVX-NOT: vmovups %ymm0
11+
;SSE-NOT: movaps {{.*}} %xmm0
12+
;SSE: movaps {{.*}} %xmm1
13+
;AVX-NOT: vmovups {{.*}} %ymm0
14+
;AVX: vmovups {{.*}} %ymm1
15+
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}"()
16+
ret double 0.
17+
}
18+
19+
; Make sure XMM0 (return register) and R11 are saved before the call
20+
declare preserve_allcc double @bar_double(i64, i64)
21+
define void @preserve_allcc2() nounwind {
22+
entry:
23+
;SSE-LABEL: preserve_allcc2
24+
;SSE: movq %r11, [[REG1:%[a-z0-9]+]]
25+
;SSE: movaps %xmm0, [[REG2:[-0-9]*\(%r[sb]p\)]]
26+
;SSE: movq [[REG1]], %r11
27+
;SSE: movaps [[REG2]], %xmm0
28+
%a0 = call i64 asm sideeffect "", "={rax}"() nounwind
29+
%a1 = call i64 asm sideeffect "", "={rcx}"() nounwind
30+
%a2 = call i64 asm sideeffect "", "={rdx}"() nounwind
31+
%a3 = call i64 asm sideeffect "", "={r8}"() nounwind
32+
%a4 = call i64 asm sideeffect "", "={r9}"() nounwind
33+
%a5 = call i64 asm sideeffect "", "={r10}"() nounwind
34+
%a6 = call i64 asm sideeffect "", "={r11}"() nounwind
35+
%a10 = call <2 x double> asm sideeffect "", "={xmm0}"() nounwind
36+
%a11 = call <2 x double> asm sideeffect "", "={xmm1}"() nounwind
37+
%a12 = call <2 x double> asm sideeffect "", "={xmm2}"() nounwind
38+
%a13 = call <2 x double> asm sideeffect "", "={xmm3}"() nounwind
39+
%a14 = call <2 x double> asm sideeffect "", "={xmm4}"() nounwind
40+
%a15 = call <2 x double> asm sideeffect "", "={xmm5}"() nounwind
41+
%a16 = call <2 x double> asm sideeffect "", "={xmm6}"() nounwind
42+
%a17 = call <2 x double> asm sideeffect "", "={xmm7}"() nounwind
43+
%a18 = call <2 x double> asm sideeffect "", "={xmm8}"() nounwind
44+
%a19 = call <2 x double> asm sideeffect "", "={xmm9}"() nounwind
45+
%a20 = call <2 x double> asm sideeffect "", "={xmm10}"() nounwind
46+
%a21 = call <2 x double> asm sideeffect "", "={xmm11}"() nounwind
47+
%a22 = call <2 x double> asm sideeffect "", "={xmm12}"() nounwind
48+
%a23 = call <2 x double> asm sideeffect "", "={xmm13}"() nounwind
49+
%a24 = call <2 x double> asm sideeffect "", "={xmm14}"() nounwind
50+
%a25 = call <2 x double> asm sideeffect "", "={xmm15}"() nounwind
51+
call preserve_allcc double @bar_double(i64 1, i64 2)
52+
call void asm sideeffect "", "{rax},{rcx},{rdx},{r8},{r9},{r10},{r11},{xmm0},{xmm1},{xmm2},{xmm3},{xmm4},{xmm5},{xmm6},{xmm7},{xmm8},{xmm9},{xmm10},{xmm11},{xmm12},{xmm13},{xmm14},{xmm15}"(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, <2 x double> %a10, <2 x double> %a11, <2 x double> %a12, <2 x double> %a13, <2 x double> %a14, <2 x double> %a15, <2 x double> %a16, <2 x double> %a17, <2 x double> %a18, <2 x double> %a19, <2 x double> %a20, <2 x double> %a21, <2 x double> %a22, <2 x double> %a23, <2 x double> %a24, <2 x double> %a25)
53+
ret void
54+
}
Lines changed: 129 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,138 @@
1-
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck --check-prefix=SSE %s
2-
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx | FileCheck --check-prefix=AVX %s
1+
; RUN: sed -e "s/RETTYPE/void/;s/RETVAL//" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck --check-prefixes=ALL,SSE,VOID %s
2+
; RUN: sed -e "s/RETTYPE/i32/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck --check-prefixes=ALL,SSE,INT %s
3+
; RUN: sed -e "s/RETTYPE/\{i64\,i64\}/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck --check-prefixes=ALL,SSE,INT128 %s
4+
;
5+
; RUN: sed -e "s/RETTYPE/void/;s/RETVAL//" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7-avx | FileCheck --check-prefixes=ALL,AVX,VOID %s
6+
; RUN: sed -e "s/RETTYPE/i32/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7-avx | FileCheck --check-prefixes=ALL,AVX,INT %s
7+
; RUN: sed -e "s/RETTYPE/\{i64\,i64\}/;s/RETVAL/undef/" %s | llc -mtriple=x86_64-apple-darwin -mcpu=corei7-avx | FileCheck --check-prefixes=ALL,AVX,INT128 %s
38

4-
define preserve_allcc void @preserve_allcc1() nounwind {
9+
define preserve_allcc RETTYPE @preserve_allcc1() nounwind {
510
entry:
6-
;SSE-LABEL: preserve_allcc1
7-
;SSE: pushq %r10
8-
;SSE-NEXT: pushq %r9
9-
;SSE-NEXT: pushq %r8
10-
;SSE-NEXT: pushq %rdi
11-
;SSE-NEXT: pushq %rsi
12-
;SSE-NEXT: pushq %rdx
13-
;SSE-NEXT: pushq %rcx
14-
;SSE-NEXT: pushq %rax
15-
;SSE-NEXT: pushq %rbp
16-
;SSE-NEXT: pushq %r15
17-
;SSE-NEXT: pushq %r14
18-
;SSE-NEXT: pushq %r13
19-
;SSE-NEXT: pushq %r12
20-
;SSE-NEXT: pushq %rbx
21-
;SSE: movaps %xmm15
22-
;SSE-NEXT: movaps %xmm14
23-
;SSE-NEXT: movaps %xmm13
24-
;SSE-NEXT: movaps %xmm12
25-
;SSE-NEXT: movaps %xmm11
26-
;SSE-NEXT: movaps %xmm10
27-
;SSE-NEXT: movaps %xmm9
28-
;SSE-NEXT: movaps %xmm8
29-
;SSE-NEXT: movaps %xmm7
30-
;SSE-NEXT: movaps %xmm6
31-
;SSE-NEXT: movaps %xmm5
32-
;SSE-NEXT: movaps %xmm4
33-
;SSE-NEXT: movaps %xmm3
34-
;SSE-NEXT: movaps %xmm2
35-
;SSE-NEXT: movaps %xmm1
36-
;SSE-NEXT: movaps %xmm0
37-
;AVX-LABEL: preserve_allcc1
38-
;AVX: pushq %r10
39-
;AVX-NEXT: pushq %r9
40-
;AVX-NEXT: pushq %r8
41-
;AVX-NEXT: pushq %rdi
42-
;AVX-NEXT: pushq %rsi
43-
;AVX-NEXT: pushq %rdx
44-
;AVX-NEXT: pushq %rcx
45-
;AVX-NEXT: pushq %rax
46-
;AVX-NEXT: pushq %rbp
47-
;AVX-NEXT: pushq %r15
48-
;AVX-NEXT: pushq %r14
49-
;AVX-NEXT: pushq %r13
50-
;AVX-NEXT: pushq %r12
51-
;AVX-NEXT: pushq %rbx
52-
;AVX: vmovups %ymm15
53-
;AVX-NEXT: vmovups %ymm14
54-
;AVX-NEXT: vmovups %ymm13
55-
;AVX-NEXT: vmovups %ymm12
56-
;AVX-NEXT: vmovups %ymm11
57-
;AVX-NEXT: vmovups %ymm10
58-
;AVX-NEXT: vmovups %ymm9
59-
;AVX-NEXT: vmovups %ymm8
60-
;AVX-NEXT: vmovups %ymm7
61-
;AVX-NEXT: vmovups %ymm6
62-
;AVX-NEXT: vmovups %ymm5
63-
;AVX-NEXT: vmovups %ymm4
64-
;AVX-NEXT: vmovups %ymm3
65-
;AVX-NEXT: vmovups %ymm2
66-
;AVX-NEXT: vmovups %ymm1
67-
;AVX-NEXT: vmovups %ymm0
11+
;ALL-LABEL: preserve_allcc1
12+
;ALL: pushq %r10
13+
;ALL-NEXT: pushq %r9
14+
;ALL-NEXT: pushq %r8
15+
;ALL-NEXT: pushq %rdi
16+
;ALL-NEXT: pushq %rsi
17+
;VOID-NEXT: pushq %rdx
18+
;INT-NEXT: pushq %rdx
19+
;INT128-NOT: pushq %rdx
20+
;ALL-NEXT: pushq %rcx
21+
;VOID-NEXT: pushq %rax
22+
;INT-NOT: pushq %rax
23+
;INT128-NOT: pushq %rax
24+
;ALL-NEXT: pushq %rbp
25+
;ALL-NEXT: pushq %r15
26+
;ALL-NEXT: pushq %r14
27+
;ALL-NEXT: pushq %r13
28+
;ALL-NEXT: pushq %r12
29+
;ALL-NEXT: pushq %rbx
30+
;SSE: movaps %xmm15
31+
;SSE-NEXT: movaps %xmm14
32+
;SSE-NEXT: movaps %xmm13
33+
;SSE-NEXT: movaps %xmm12
34+
;SSE-NEXT: movaps %xmm11
35+
;SSE-NEXT: movaps %xmm10
36+
;SSE-NEXT: movaps %xmm9
37+
;SSE-NEXT: movaps %xmm8
38+
;SSE-NEXT: movaps %xmm7
39+
;SSE-NEXT: movaps %xmm6
40+
;SSE-NEXT: movaps %xmm5
41+
;SSE-NEXT: movaps %xmm4
42+
;SSE-NEXT: movaps %xmm3
43+
;SSE-NEXT: movaps %xmm2
44+
;SSE-NEXT: movaps %xmm1
45+
;SSE-NEXT: movaps %xmm0
46+
;AVX: vmovups %ymm15
47+
;AVX-NEXT: vmovups %ymm14
48+
;AVX-NEXT: vmovups %ymm13
49+
;AVX-NEXT: vmovups %ymm12
50+
;AVX-NEXT: vmovups %ymm11
51+
;AVX-NEXT: vmovups %ymm10
52+
;AVX-NEXT: vmovups %ymm9
53+
;AVX-NEXT: vmovups %ymm8
54+
;AVX-NEXT: vmovups %ymm7
55+
;AVX-NEXT: vmovups %ymm6
56+
;AVX-NEXT: vmovups %ymm5
57+
;AVX-NEXT: vmovups %ymm4
58+
;AVX-NEXT: vmovups %ymm3
59+
;AVX-NEXT: vmovups %ymm2
60+
;AVX-NEXT: vmovups %ymm1
61+
;AVX-NEXT: vmovups %ymm0
62+
;SSE: movaps {{.*}} %xmm0
63+
;SSE-NEXT: movaps {{.*}} %xmm1
64+
;SSE-NEXT: movaps {{.*}} %xmm2
65+
;SSE-NEXT: movaps {{.*}} %xmm3
66+
;SSE-NEXT: movaps {{.*}} %xmm4
67+
;SSE-NEXT: movaps {{.*}} %xmm5
68+
;SSE-NEXT: movaps {{.*}} %xmm6
69+
;SSE-NEXT: movaps {{.*}} %xmm7
70+
;SSE-NEXT: movaps {{.*}} %xmm8
71+
;SSE-NEXT: movaps {{.*}} %xmm9
72+
;SSE-NEXT: movaps {{.*}} %xmm10
73+
;SSE-NEXT: movaps {{.*}} %xmm11
74+
;SSE-NEXT: movaps {{.*}} %xmm12
75+
;SSE-NEXT: movaps {{.*}} %xmm13
76+
;SSE-NEXT: movaps {{.*}} %xmm14
77+
;SSE-NEXT: movaps {{.*}} %xmm15
78+
;AVX: vmovups {{.*}} %ymm0
79+
;AVX-NEXT: vmovups {{.*}} %ymm1
80+
;AVX-NEXT: vmovups {{.*}} %ymm2
81+
;AVX-NEXT: vmovups {{.*}} %ymm3
82+
;AVX-NEXT: vmovups {{.*}} %ymm4
83+
;AVX-NEXT: vmovups {{.*}} %ymm5
84+
;AVX-NEXT: vmovups {{.*}} %ymm6
85+
;AVX-NEXT: vmovups {{.*}} %ymm7
86+
;AVX-NEXT: vmovups {{.*}} %ymm8
87+
;AVX-NEXT: vmovups {{.*}} %ymm9
88+
;AVX-NEXT: vmovups {{.*}} %ymm10
89+
;AVX-NEXT: vmovups {{.*}} %ymm11
90+
;AVX-NEXT: vmovups {{.*}} %ymm12
91+
;AVX-NEXT: vmovups {{.*}} %ymm13
92+
;AVX-NEXT: vmovups {{.*}} %ymm14
93+
;AVX-NEXT: vmovups {{.*}} %ymm15
94+
;ALL: popq %rbx
95+
;ALL-NEXT: popq %r12
96+
;ALL-NEXT: popq %r13
97+
;ALL-NEXT: popq %r14
98+
;ALL-NEXT: popq %r15
99+
;ALL-NEXT: popq %rbp
100+
;VOID-NEXT: popq %rax
101+
;INT-NOT: popq %rax
102+
;INT128-NOT: popq %rax
103+
;ALL-NEXT: popq %rcx
104+
;VOID-NEXT: popq %rdx
105+
;INT-NEXT: popq %rdx
106+
;INT128-NOT: popq %rdx
107+
;ALL-NEXT: popq %rsi
108+
;ALL-NEXT: popq %rdi
109+
;ALL-NEXT: popq %r8
110+
;ALL-NEXT: popq %r9
111+
;ALL-NEXT: popq %r10
68112
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}"()
69-
ret void
113+
ret RETTYPE RETVAL
70114
}
71115

72-
; Make sure only R11 is saved before the call
73-
declare preserve_allcc void @bar(i64, i64, double, double)
116+
; Make sure R11 and return registers are saved before the call
117+
declare preserve_allcc RETTYPE @bar(i64, i64, double, double)
74118
define void @preserve_allcc2() nounwind {
75119
entry:
76-
;SSE-LABEL: preserve_allcc2
77-
;SSE: movq %r11, [[REG:%[a-z0-9]+]]
78-
;SSE-NOT: movaps %xmm
79-
;SSE: movq [[REG]], %r11
120+
;ALL-LABEL: preserve_allcc2
121+
;VOID-NOT: movq %rax, [[REG1:%[a-z0-9]+]]
122+
;INT: movq %rax, [[REG1:%[a-z0-9]+]]
123+
;INT128: movq %rax, [[REG1:%[a-z0-9]+]]
124+
;VOID-NOT: movq %rdx, [[REG2:%[a-z0-9]+]]
125+
;INT-NOT: movq %rdx, [[REG2:%[a-z0-9]+]]
126+
;INT128: movq %rdx, [[REG2:%[a-z0-9]+]]
127+
;ALL: movq %r11, [[REG3:%[a-z0-9]+]]
128+
;ALL-NOT: movaps %xmm
129+
;VOID-NOT: movq {{.*}}, %rax
130+
;INT: movq [[REG1]], %rax
131+
;INT128: movq [[REG1]], %rax
132+
;VOID-NOT: movq {{.*}}, %rdx
133+
;INT-NOT: movq {{.*}}, %rdx
134+
;INT128: movq [[REG2]], %rdx
135+
;ALL: movq [[REG3]], %r11
80136
%a0 = call i64 asm sideeffect "", "={rax}"() nounwind
81137
%a1 = call i64 asm sideeffect "", "={rcx}"() nounwind
82138
%a2 = call i64 asm sideeffect "", "={rdx}"() nounwind
@@ -98,7 +154,7 @@ entry:
98154
%a21 = call <2 x double> asm sideeffect "", "={xmm13}"() nounwind
99155
%a22 = call <2 x double> asm sideeffect "", "={xmm14}"() nounwind
100156
%a23 = call <2 x double> asm sideeffect "", "={xmm15}"() nounwind
101-
call preserve_allcc void @bar(i64 1, i64 2, double 3.0, double 4.0)
157+
call preserve_allcc RETTYPE @bar(i64 1, i64 2, double 3.0, double 4.0)
102158
call void asm sideeffect "", "{rax},{rcx},{rdx},{r8},{r9},{r10},{r11},{xmm2},{xmm3},{xmm4},{xmm5},{xmm6},{xmm7},{xmm8},{xmm9},{xmm10},{xmm11},{xmm12},{xmm13},{xmm14},{xmm15}"(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, <2 x double> %a10, <2 x double> %a11, <2 x double> %a12, <2 x double> %a13, <2 x double> %a14, <2 x double> %a15, <2 x double> %a16, <2 x double> %a17, <2 x double> %a18, <2 x double> %a19, <2 x double> %a20, <2 x double> %a21, <2 x double> %a22, <2 x double> %a23)
103159
ret void
104160
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 | FileCheck %s
2+
3+
; Make sure XMM0 (return register) and R11 are saved before the call
4+
declare preserve_mostcc double @foo_double(i64, i64)
5+
define void @preserve_mostcc1() nounwind {
6+
entry:
7+
;CHECK-LABEL: preserve_mostcc1
8+
;CHECK: movq %r11, [[REG1:%[a-z0-9]+]]
9+
;CHECK: movaps %xmm0, [[REG2:[-0-9]*\(%r[sb]p\)]]
10+
;CHECK: call
11+
;CHECK: movq [[REG1]], %r11
12+
;CHECK: movaps [[REG2]], %xmm0
13+
%a0 = call i64 asm sideeffect "", "={rax}"() nounwind
14+
%a1 = call i64 asm sideeffect "", "={rcx}"() nounwind
15+
%a2 = call i64 asm sideeffect "", "={rdx}"() nounwind
16+
%a3 = call i64 asm sideeffect "", "={r8}"() nounwind
17+
%a4 = call i64 asm sideeffect "", "={r9}"() nounwind
18+
%a5 = call i64 asm sideeffect "", "={r10}"() nounwind
19+
%a6 = call i64 asm sideeffect "", "={r11}"() nounwind
20+
%a10 = call <2 x double> asm sideeffect "", "={xmm0}"() nounwind
21+
%a11 = call <2 x double> asm sideeffect "", "={xmm1}"() nounwind
22+
%a12 = call <2 x double> asm sideeffect "", "={xmm2}"() nounwind
23+
%a13 = call <2 x double> asm sideeffect "", "={xmm3}"() nounwind
24+
%a14 = call <2 x double> asm sideeffect "", "={xmm4}"() nounwind
25+
%a15 = call <2 x double> asm sideeffect "", "={xmm5}"() nounwind
26+
%a16 = call <2 x double> asm sideeffect "", "={xmm6}"() nounwind
27+
%a17 = call <2 x double> asm sideeffect "", "={xmm7}"() nounwind
28+
%a18 = call <2 x double> asm sideeffect "", "={xmm8}"() nounwind
29+
%a19 = call <2 x double> asm sideeffect "", "={xmm9}"() nounwind
30+
%a20 = call <2 x double> asm sideeffect "", "={xmm10}"() nounwind
31+
%a21 = call <2 x double> asm sideeffect "", "={xmm11}"() nounwind
32+
%a22 = call <2 x double> asm sideeffect "", "={xmm12}"() nounwind
33+
%a23 = call <2 x double> asm sideeffect "", "={xmm13}"() nounwind
34+
%a24 = call <2 x double> asm sideeffect "", "={xmm14}"() nounwind
35+
%a25 = call <2 x double> asm sideeffect "", "={xmm15}"() nounwind
36+
call preserve_mostcc double @foo_double(i64 1, i64 2)
37+
call void asm sideeffect "", "{rax},{rcx},{rdx},{r8},{r9},{r10},{r11},{xmm0},{xmm1},{xmm2},{xmm3},{xmm4},{xmm5},{xmm6},{xmm7},{xmm8},{xmm9},{xmm10},{xmm11},{xmm12},{xmm13},{xmm14},{xmm15}"(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, <2 x double> %a10, <2 x double> %a11, <2 x double> %a12, <2 x double> %a13, <2 x double> %a14, <2 x double> %a15, <2 x double> %a16, <2 x double> %a17, <2 x double> %a18, <2 x double> %a19, <2 x double> %a20, <2 x double> %a21, <2 x double> %a22, <2 x double> %a23, <2 x double> %a24, <2 x double> %a25)
38+
ret void
39+
}

0 commit comments

Comments
 (0)