summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2019-11-18 15:31:37 -0800
committerReid Kleckner <rnk@google.com>2019-11-19 16:54:00 -0800
commit606a2bd6218e8378728b6c1e021e64bb57084a97 (patch)
treedccb9878f3f8cb8e8b332d9ee63d910eb05033dc
parentbffdee8ef379126de3f2581214d89c1b29f440b7 (diff)
downloadbcm5719-llvm-606a2bd6218e8378728b6c1e021e64bb57084a97.tar.gz
bcm5719-llvm-606a2bd6218e8378728b6c1e021e64bb57084a97.zip
[musttail] Don't forward AL on Win64
AL is only used for varargs on SysV platforms. Don't forward it on Windows. This allows control flow guard to set up an extra hidden parameter in RAX, as described in PR44049. This also has the effect of freeing up RAX for use in virtual member pointer thunks, which may also be a nice little code size improvement on Win64. Fixes PR44049 Reviewers: ajpaverd, efriedma, hans Differential Revision: https://reviews.llvm.org/D70413
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp4
-rw-r--r--llvm/test/CodeGen/X86/cfguard-checks.ll33
-rw-r--r--llvm/test/CodeGen/X86/musttail-varargs.ll30
3 files changed, 47 insertions, 20 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d4aaa7a9ee6..38f82c04296 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -3467,8 +3467,8 @@ SDValue X86TargetLowering::LowerFormalArguments(
FuncInfo->getForwardedMustTailRegParms();
CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_X86);
- // Conservatively forward AL on x86_64, since it might be used for varargs.
- if (Is64Bit && !CCInfo.isAllocated(X86::AL)) {
+ // Forward AL for SysV x86_64 targets, since it is used for varargs.
+ if (Is64Bit && !IsWin64 && !CCInfo.isAllocated(X86::AL)) {
unsigned ALVReg = MF.addLiveIn(X86::AL, &X86::GR8RegClass);
Forwards.push_back(ForwardedRegister(ALVReg, X86::AL, MVT::i8));
}
diff --git a/llvm/test/CodeGen/X86/cfguard-checks.ll b/llvm/test/CodeGen/X86/cfguard-checks.ll
index d2cd3c9f3ee..efd6e7bc11b 100644
--- a/llvm/test/CodeGen/X86/cfguard-checks.ll
+++ b/llvm/test/CodeGen/X86/cfguard-checks.ll
@@ -176,6 +176,39 @@ entry:
; X64-NOT: callq
}
+%struct.Foo = type { i32 (%struct.Foo*)** }
+
+; Test that Control Flow Guard checks are correctly added for variadic musttail
+; calls. These are used for MS C++ ABI virtual member pointer thunks.
+; PR44049
+define i32 @vmptr_thunk(%struct.Foo* inreg %p) {
+entry:
+ %vptr.addr = getelementptr inbounds %struct.Foo, %struct.Foo* %p, i32 0, i32 0
+ %vptr = load i32 (%struct.Foo*)**, i32 (%struct.Foo*)*** %vptr.addr
+ %slot = getelementptr inbounds i32 (%struct.Foo*)*, i32 (%struct.Foo*)** %vptr, i32 1
+ %vmethod = load i32 (%struct.Foo*)*, i32 (%struct.Foo*)** %slot
+ %rv = musttail call i32 %vmethod(%struct.Foo* inreg %p)
+ ret i32 %rv
+
+ ; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
+ ; X32-LABEL: _vmptr_thunk:
+ ; X32: movl %eax, %esi
+ ; X32: movl (%eax), %eax
+ ; X32: movl 4(%eax), %ecx
+ ; X32: calll *___guard_check_icall_fptr
+ ; X32: movl %esi, %eax
+ ; X32: jmpl *%ecx # TAILCALL
+ ; X32-NOT: calll
+
+ ; Use NEXT here because we previously had an extra instruction in this sequence.
+ ; X64-LABEL: vmptr_thunk:
+ ; X64: movq (%rcx), %rax
+ ; X64-NEXT: movq 8(%rax), %rax
+ ; X64-NEXT: movq __guard_dispatch_icall_fptr(%rip), %rdx
+ ; X64-NEXT: addq $40, %rsp
+ ; X64-NEXT: rex64 jmpq *%rdx # TAILCALL
+ ; X64-NOT: callq
+}
; Test that longjmp targets have public labels and are included in the .gljmp section.
%struct._SETJMP_FLOAT128 = type { [2 x i64] }
diff --git a/llvm/test/CodeGen/X86/musttail-varargs.ll b/llvm/test/CodeGen/X86/musttail-varargs.ll
index 1144ce8eba7..5f5ce5f9af9 100644
--- a/llvm/test/CodeGen/X86/musttail-varargs.ll
+++ b/llvm/test/CodeGen/X86/musttail-varargs.ll
@@ -211,37 +211,31 @@ define void @f_thunk(i8* %this, ...) {
; WINDOWS-NEXT: .seh_pushreg %rsi
; WINDOWS-NEXT: pushq %rdi
; WINDOWS-NEXT: .seh_pushreg %rdi
-; WINDOWS-NEXT: pushq %rbp
-; WINDOWS-NEXT: .seh_pushreg %rbp
; WINDOWS-NEXT: pushq %rbx
; WINDOWS-NEXT: .seh_pushreg %rbx
-; WINDOWS-NEXT: subq $64, %rsp
-; WINDOWS-NEXT: .seh_stackalloc 64
+; WINDOWS-NEXT: subq $72, %rsp
+; WINDOWS-NEXT: .seh_stackalloc 72
; WINDOWS-NEXT: .seh_endprologue
-; WINDOWS-NEXT: movl %eax, %r14d
-; WINDOWS-NEXT: movq %r9, %rsi
+; WINDOWS-NEXT: movq %r9, %r14
; WINDOWS-NEXT: movq %r8, %rdi
; WINDOWS-NEXT: movq %rdx, %rbx
-; WINDOWS-NEXT: movq %rcx, %rbp
+; WINDOWS-NEXT: movq %rcx, %rsi
; WINDOWS-NEXT: movq %rdx, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: movq %r8, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: movq %r9, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: callq get_f
-; WINDOWS-NEXT: movq %rax, %r10
-; WINDOWS-NEXT: movq %rbp, %rcx
+; WINDOWS-NEXT: movq %rsi, %rcx
; WINDOWS-NEXT: movq %rbx, %rdx
; WINDOWS-NEXT: movq %rdi, %r8
-; WINDOWS-NEXT: movq %rsi, %r9
-; WINDOWS-NEXT: movl %r14d, %eax
-; WINDOWS-NEXT: addq $64, %rsp
+; WINDOWS-NEXT: movq %r14, %r9
+; WINDOWS-NEXT: addq $72, %rsp
; WINDOWS-NEXT: popq %rbx
-; WINDOWS-NEXT: popq %rbp
; WINDOWS-NEXT: popq %rdi
; WINDOWS-NEXT: popq %rsi
; WINDOWS-NEXT: popq %r14
-; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
+; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .seh_handlerdata
; WINDOWS-NEXT: .text
; WINDOWS-NEXT: .seh_endproc
@@ -397,14 +391,14 @@ define void @h_thunk(%struct.Foo* %this, ...) {
; WINDOWS-NEXT: cmpb $1, (%rcx)
; WINDOWS-NEXT: jne .LBB2_2
; WINDOWS-NEXT: # %bb.1: # %then
-; WINDOWS-NEXT: movq 8(%rcx), %r10
+; WINDOWS-NEXT: movq 8(%rcx), %rax
; WINDOWS-NEXT: addq $40, %rsp
-; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
+; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .LBB2_2: # %else
-; WINDOWS-NEXT: movq 16(%rcx), %r10
+; WINDOWS-NEXT: movq 16(%rcx), %rax
; WINDOWS-NEXT: movl $42, {{.*}}(%rip)
; WINDOWS-NEXT: addq $40, %rsp
-; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
+; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .seh_handlerdata
; WINDOWS-NEXT: .text
; WINDOWS-NEXT: .seh_endproc
OpenPOWER on IntegriCloud