Files
clang-p2996/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
Martin Storsjö 6f792041a5 Reapply "[CodeGen] [WinException] Only produce handler data at the end of the function if needed"
This reapplies 36c64af9d7 in updated
form.

Emit the xdata for each function at .seh_endproc. This keeps the
exact same output header order for most code generated by the LLVM
CodeGen layer. (Sections still change order for code built from
assembly where functions lack an explicit .seh_handlerdata
directive, and functions with chained unwind info.)

The practical effect should be that assembly output lacks
superfluous ".seh_handlerdata; .text" pairs at the end of functions
that don't handle exceptions, which allows such functions to use
the AArch64 packed unwind format again.

Differential Revision: https://reviews.llvm.org/D87448
2020-11-23 23:17:03 +02:00

262 lines
7.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s | FileCheck %s --check-prefixes=ALL,CHECK
; RUN: llc -O0 < %s | FileCheck %s --check-prefixes=ALL,CHECK-O0
; Source to regenerate:
; struct Foo {
; int * __ptr32 p32;
; int * __ptr64 p64;
; __attribute__((address_space(9))) int *p_other;
; };
; void use_foo(Foo *f);
; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
; f->p64 = i;
; use_foo(f);
; }
; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
; f->p64 = i;
; use_foo(f);
; }
; void test_trunc(Foo *f, int * __ptr64 i) {
; f->p32 = i;
; use_foo(f);
; }
; void test_noop1(Foo *f, int * __ptr32 i) {
; f->p32 = i;
; use_foo(f);
; }
; void test_noop2(Foo *f, int * __ptr64 i) {
; f->p64 = i;
; use_foo(f);
; }
; void test_null_arg(Foo *f, int * __ptr32 i) {
; test_noop1(f, 0);
; }
; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
; f->p32 = (int * __ptr32)i;
; use_foo(f);
; }
;
; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-windows-msvc"
%struct.Foo = type { i32 addrspace(270)*, i32*, i32 addrspace(9)* }
declare dso_local void @use_foo(%struct.Foo*)
define dso_local void @test_sign_ext(%struct.Foo* %f, i32 addrspace(270)* %i) {
; ALL-LABEL: test_sign_ext:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movslq %edx, %rax
; ALL-NEXT: movq %rax, 8(%rcx)
; ALL-NEXT: jmp use_foo # TAILCALL
entry:
%0 = addrspacecast i32 addrspace(270)* %i to i32*
%p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
store i32* %0, i32** %p64, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define dso_local void @test_zero_ext(%struct.Foo* %f, i32 addrspace(271)* %i) {
; CHECK-LABEL: test_zero_ext:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edx, %eax
; CHECK-NEXT: movq %rax, 8(%rcx)
; CHECK-NEXT: jmp use_foo # TAILCALL
;
; CHECK-O0-LABEL: test_zero_ext:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %edx, %eax
; CHECK-O0-NEXT: # kill: def $rax killed $eax
; CHECK-O0-NEXT: movq %rax, 8(%rcx)
; CHECK-O0-NEXT: jmp use_foo # TAILCALL
entry:
%0 = addrspacecast i32 addrspace(271)* %i to i32*
%p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
store i32* %0, i32** %p64, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define dso_local void @test_trunc(%struct.Foo* %f, i32* %i) {
; CHECK-LABEL: test_trunc:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edx, (%rcx)
; CHECK-NEXT: jmp use_foo # TAILCALL
;
; CHECK-O0-LABEL: test_trunc:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %edx, %eax
; CHECK-O0-NEXT: movl %eax, (%rcx)
; CHECK-O0-NEXT: jmp use_foo # TAILCALL
entry:
%0 = addrspacecast i32* %i to i32 addrspace(270)*
%p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define dso_local void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* %i) {
; ALL-LABEL: test_noop1:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movl %edx, (%rcx)
; ALL-NEXT: jmp use_foo # TAILCALL
entry:
%p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define dso_local void @test_noop2(%struct.Foo* %f, i32* %i) {
; ALL-LABEL: test_noop2:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movq %rdx, 8(%rcx)
; ALL-NEXT: jmp use_foo # TAILCALL
entry:
%p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
store i32* %i, i32** %p64, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
; Test that null can be passed as a 32-bit pointer.
define dso_local void @test_null_arg(%struct.Foo* %f) {
; ALL-LABEL: test_null_arg:
; ALL: # %bb.0: # %entry
; ALL-NEXT: subq $40, %rsp
; ALL-NEXT: .seh_stackalloc 40
; ALL-NEXT: .seh_endprologue
; ALL-NEXT: xorl %edx, %edx
; ALL-NEXT: callq test_noop1
; ALL-NEXT: nop
; ALL-NEXT: addq $40, %rsp
; ALL-NEXT: retq
; ALL-NEXT: .seh_endproc
entry:
call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null)
ret void
}
; Test casts between unrecognized address spaces.
define void @test_unrecognized(%struct.Foo* %f, i32 addrspace(14)* %i) {
; CHECK-LABEL: test_unrecognized:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edx, (%rcx)
; CHECK-NEXT: jmp use_foo # TAILCALL
;
; CHECK-O0-LABEL: test_unrecognized:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %edx, %eax
; CHECK-O0-NEXT: movl %eax, (%rcx)
; CHECK-O0-NEXT: jmp use_foo # TAILCALL
entry:
%0 = addrspacecast i32 addrspace(14)* %i to i32 addrspace(270)*
%p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define void @test_unrecognized2(%struct.Foo* %f, i32 addrspace(271)* %i) {
; CHECK-LABEL: test_unrecognized2:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %edx, %eax
; CHECK-NEXT: movq %rax, 16(%rcx)
; CHECK-NEXT: jmp use_foo # TAILCALL
;
; CHECK-O0-LABEL: test_unrecognized2:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %edx, %eax
; CHECK-O0-NEXT: # kill: def $rax killed $eax
; CHECK-O0-NEXT: movq %rax, 16(%rcx)
; CHECK-O0-NEXT: jmp use_foo # TAILCALL
entry:
%0 = addrspacecast i32 addrspace(271)* %i to i32 addrspace(9)*
%p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 2
store i32 addrspace(9)* %0, i32 addrspace(9)** %p32, align 8
tail call void @use_foo(%struct.Foo* %f)
ret void
}
define i32 @test_load_sptr32(i32 addrspace(270)* %i) {
; ALL-LABEL: test_load_sptr32:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movslq %ecx, %rax
; ALL-NEXT: movl (%rax), %eax
; ALL-NEXT: retq
entry:
%0 = load i32, i32 addrspace(270)* %i, align 4
ret i32 %0
}
define i32 @test_load_uptr32(i32 addrspace(271)* %i) {
; CHECK-LABEL: test_load_uptr32:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: movl (%rax), %eax
; CHECK-NEXT: retq
;
; CHECK-O0-LABEL: test_load_uptr32:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %ecx, %eax
; CHECK-O0-NEXT: # kill: def $rax killed $eax
; CHECK-O0-NEXT: movl (%rax), %eax
; CHECK-O0-NEXT: retq
entry:
%0 = load i32, i32 addrspace(271)* %i, align 4
ret i32 %0
}
define i32 @test_load_ptr64(i32 addrspace(272)* %i) {
; ALL-LABEL: test_load_ptr64:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movl (%rcx), %eax
; ALL-NEXT: retq
entry:
%0 = load i32, i32 addrspace(272)* %i, align 8
ret i32 %0
}
define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) {
; ALL-LABEL: test_store_sptr32:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movslq %ecx, %rax
; ALL-NEXT: movl %edx, (%rax)
; ALL-NEXT: retq
entry:
store i32 %i, i32 addrspace(270)* %s, align 4
ret void
}
define void @test_store_uptr32(i32 addrspace(271)* %s, i32 %i) {
; CHECK-LABEL: test_store_uptr32:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: movl %edx, (%rax)
; CHECK-NEXT: retq
;
; CHECK-O0-LABEL: test_store_uptr32:
; CHECK-O0: # %bb.0: # %entry
; CHECK-O0-NEXT: movl %ecx, %eax
; CHECK-O0-NEXT: # kill: def $rax killed $eax
; CHECK-O0-NEXT: movl %edx, (%rax)
; CHECK-O0-NEXT: retq
entry:
store i32 %i, i32 addrspace(271)* %s, align 4
ret void
}
define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) {
; ALL-LABEL: test_store_ptr64:
; ALL: # %bb.0: # %entry
; ALL-NEXT: movl %edx, (%rcx)
; ALL-NEXT: retq
entry:
store i32 %i, i32 addrspace(272)* %s, align 8
ret void
}