346 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			11 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) {
 | |
| ;   test_noop2(f, 0);
 | |
| ; }
 | |
| ; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
 | |
| ;   f->p64 = (int * __ptr64)i;
 | |
| ;   use_foo(f);
 | |
| ; }
 | |
| ; void test_unrecognized2(Foo *f, int * __ptr64 i) {
 | |
| ;   f->p_other = i;
 | |
| ;   use_foo(f);
 | |
| ; }
 | |
| ;
 | |
| ; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
 | |
| 
 | |
| target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
 | |
| target triple = "i686-unknown-windows-msvc"
 | |
| 
 | |
| %struct.Foo = type { i32*, i32 addrspace(272)*, i32 addrspace(9)* }
 | |
| declare dso_local void @use_foo(%struct.Foo*)
 | |
| 
 | |
| define dso_local void @test_sign_ext(%struct.Foo* %f, i32* %i) {
 | |
| ; CHECK-LABEL: test_sign_ext:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %ecx, 8(%eax)
 | |
| ; CHECK-NEXT:    sarl $31, %ecx
 | |
| ; CHECK-NEXT:    movl %ecx, 12(%eax)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_sign_ext:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %edx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %edx, %ecx
 | |
| ; CHECK-O0-NEXT:    sarl $31, %ecx
 | |
| ; CHECK-O0-NEXT:    movl %edx, 8(%eax)
 | |
| ; CHECK-O0-NEXT:    movl %ecx, 12(%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %0 = addrspacecast i32* %i to i32 addrspace(272)*
 | |
|   %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 1
 | |
|   store i32 addrspace(272)* %0, i32 addrspace(272)** %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 {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, 8(%ecx)
 | |
| ; CHECK-NEXT:    movl $0, 12(%ecx)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_zero_ext:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, 8(%eax)
 | |
| ; CHECK-O0-NEXT:    movl $0, 12(%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %0 = addrspacecast i32 addrspace(271)* %i to i32 addrspace(272)*
 | |
|   %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 1
 | |
|   store i32 addrspace(272)* %0, i32 addrspace(272)** %p64, align 8
 | |
|   tail call void @use_foo(%struct.Foo* %f)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define dso_local void @test_trunc(%struct.Foo* %f, i32 addrspace(272)* %i) {
 | |
| ; CHECK-LABEL: test_trunc:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, (%ecx)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_trunc:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %0 = addrspacecast i32 addrspace(272)* %i to i32*
 | |
|   %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 0
 | |
|   store i32* %0, i32** %p32, align 8
 | |
|   tail call void @use_foo(%struct.Foo* %f)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define dso_local void @test_noop1(%struct.Foo* %f, i32* %i) {
 | |
| ; CHECK-LABEL: test_noop1:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, (%ecx)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_noop1:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 0
 | |
|   store i32* %i, i32** %p32, align 8
 | |
|   tail call void @use_foo(%struct.Foo* %f)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define dso_local void @test_noop2(%struct.Foo* %f, i32 addrspace(272)* %i) {
 | |
| ; CHECK-LABEL: test_noop2:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %edx
 | |
| ; CHECK-NEXT:    movl %ecx, 12(%edx)
 | |
| ; CHECK-NEXT:    movl %eax, 8(%edx)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_noop2:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %edx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %edx, 8(%eax)
 | |
| ; CHECK-O0-NEXT:    movl %ecx, 12(%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 1
 | |
|   store i32 addrspace(272)* %i, i32 addrspace(272)** %p64, align 8
 | |
|   tail call void @use_foo(%struct.Foo* %f)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| ; Test that null can be passed as a 64-bit pointer.
 | |
| define dso_local void @test_null_arg(%struct.Foo* %f) {
 | |
| ; CHECK-LABEL: test_null_arg:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    pushl $0
 | |
| ; CHECK-NEXT:    pushl $0
 | |
| ; CHECK-NEXT:    pushl {{[0-9]+}}(%esp)
 | |
| ; CHECK-NEXT:    calll _test_noop2
 | |
| ; CHECK-NEXT:    addl $12, %esp
 | |
| ; CHECK-NEXT:    retl
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_null_arg:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    subl $12, %esp
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl %esp, %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    movl $0, 8(%eax)
 | |
| ; CHECK-O0-NEXT:    movl $0, 4(%eax)
 | |
| ; CHECK-O0-NEXT:    calll _test_noop2
 | |
| ; CHECK-O0-NEXT:    addl $12, %esp
 | |
| ; CHECK-O0-NEXT:    retl
 | |
| entry:
 | |
|   call void @test_noop2(%struct.Foo* %f, i32 addrspace(272)* null)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define dso_local void @test_unrecognized(%struct.Foo* %f, i32 addrspace(14)* %i) {
 | |
| ; CHECK-LABEL: test_unrecognized:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %ecx, 8(%eax)
 | |
| ; CHECK-NEXT:    sarl $31, %ecx
 | |
| ; CHECK-NEXT:    movl %ecx, 12(%eax)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_unrecognized:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %edx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %edx, %ecx
 | |
| ; CHECK-O0-NEXT:    sarl $31, %ecx
 | |
| ; CHECK-O0-NEXT:    movl %edx, 8(%eax)
 | |
| ; CHECK-O0-NEXT:    movl %ecx, 12(%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %0 = addrspacecast i32 addrspace(14)* %i to i32 addrspace(272)*
 | |
|   %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 1
 | |
|   store i32 addrspace(272)* %0, i32 addrspace(272)** %p64, align 8
 | |
|   tail call void @use_foo(%struct.Foo* %f)
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define dso_local void @test_unrecognized2(%struct.Foo* %f, i32 addrspace(272)* %i) {
 | |
| ; CHECK-LABEL: test_unrecognized2:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, 16(%ecx)
 | |
| ; CHECK-NEXT:    jmp _use_foo # TAILCALL
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_unrecognized2:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, 16(%eax)
 | |
| ; CHECK-O0-NEXT:    jmp _use_foo # TAILCALL
 | |
| entry:
 | |
|   %0 = addrspacecast i32 addrspace(272)* %i to i32 addrspace(9)*
 | |
|   %p_other = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 2
 | |
|   store i32 addrspace(9)* %0, i32 addrspace(9)** %p_other, 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:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; ALL-NEXT:    movl (%eax), %eax
 | |
| ; ALL-NEXT:    retl
 | |
| entry:
 | |
|   %0 = load i32, i32 addrspace(270)* %i, align 4
 | |
|   ret i32 %0
 | |
| }
 | |
| 
 | |
| define i32 @test_load_uptr32(i32 addrspace(271)* %i) {
 | |
| ; ALL-LABEL: test_load_uptr32:
 | |
| ; ALL:       # %bb.0: # %entry
 | |
| ; ALL-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; ALL-NEXT:    movl (%eax), %eax
 | |
| ; ALL-NEXT:    retl
 | |
| entry:
 | |
|   %0 = load i32, i32 addrspace(271)* %i, align 4
 | |
|   ret i32 %0
 | |
| }
 | |
| 
 | |
| define i32 @test_load_ptr64(i32 addrspace(272)* %i) {
 | |
| ; CHECK-LABEL: test_load_ptr64:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl (%eax), %eax
 | |
| ; CHECK-NEXT:    retl
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_load_ptr64:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl (%eax), %eax
 | |
| ; CHECK-O0-NEXT:    retl
 | |
| entry:
 | |
|   %0 = load i32, i32 addrspace(272)* %i, align 8
 | |
|   ret i32 %0
 | |
| }
 | |
| 
 | |
| define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) {
 | |
| ; CHECK-LABEL: test_store_sptr32:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, (%ecx)
 | |
| ; CHECK-NEXT:    retl
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_store_sptr32:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    retl
 | |
| 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 {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, (%ecx)
 | |
| ; CHECK-NEXT:    retl
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_store_uptr32:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    retl
 | |
| entry:
 | |
|   store i32 %i, i32 addrspace(271)* %s, align 4
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) {
 | |
| ; CHECK-LABEL: test_store_ptr64:
 | |
| ; CHECK:       # %bb.0: # %entry
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-NEXT:    movl %eax, (%ecx)
 | |
| ; CHECK-NEXT:    retl
 | |
| ;
 | |
| ; CHECK-O0-LABEL: test_store_ptr64:
 | |
| ; CHECK-O0:       # %bb.0: # %entry
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %eax
 | |
| ; CHECK-O0-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 | |
| ; CHECK-O0-NEXT:    movl %ecx, (%eax)
 | |
| ; CHECK-O0-NEXT:    retl
 | |
| entry:
 | |
|   store i32 %i, i32 addrspace(272)* %s, align 8
 | |
|   ret void
 | |
| }
 |