1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s | FileCheck %s --check-prefixes=ALL,CHECK 3; RUN: llc -O0 < %s | FileCheck %s --check-prefixes=ALL,CHECK-O0 4 5; Source to regenerate: 6; struct Foo { 7; int * __ptr32 p32; 8; int * __ptr64 p64; 9; __attribute__((address_space(9))) int *p_other; 10; }; 11; void use_foo(Foo *f); 12; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) { 13; f->p64 = i; 14; use_foo(f); 15; } 16; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) { 17; f->p64 = i; 18; use_foo(f); 19; } 20; void test_trunc(Foo *f, int * __ptr64 i) { 21; f->p32 = i; 22; use_foo(f); 23; } 24; void test_noop1(Foo *f, int * __ptr32 i) { 25; f->p32 = i; 26; use_foo(f); 27; } 28; void test_noop2(Foo *f, int * __ptr64 i) { 29; f->p64 = i; 30; use_foo(f); 31; } 32; void test_null_arg(Foo *f, int * __ptr32 i) { 33; test_noop1(f, 0); 34; } 35; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) { 36; f->p32 = (int * __ptr32)i; 37; use_foo(f); 38; } 39; 40; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp 41 42target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 43target triple = "x86_64-unknown-windows-msvc" 44 45%struct.Foo = type { i32 addrspace(270)*, i32*, i32 addrspace(9)* } 46declare dso_local void @use_foo(%struct.Foo*) 47 48define dso_local void @test_sign_ext(%struct.Foo* %f, i32 addrspace(270)* %i) { 49; ALL-LABEL: test_sign_ext: 50; ALL: # %bb.0: # %entry 51; ALL-NEXT: movslq %edx, %rax 52; ALL-NEXT: movq %rax, 8(%rcx) 53; ALL-NEXT: jmp use_foo # TAILCALL 54entry: 55 %0 = addrspacecast i32 addrspace(270)* %i to i32* 56 %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1 57 store i32* %0, i32** %p64, align 8 58 tail call void @use_foo(%struct.Foo* %f) 59 ret void 60} 61 62define dso_local void @test_zero_ext(%struct.Foo* %f, i32 addrspace(271)* %i) { 63; CHECK-LABEL: test_zero_ext: 64; CHECK: # %bb.0: # %entry 65; CHECK-NEXT: movl %edx, %eax 66; CHECK-NEXT: movq %rax, 8(%rcx) 67; CHECK-NEXT: jmp use_foo # TAILCALL 68; 69; CHECK-O0-LABEL: test_zero_ext: 70; CHECK-O0: # %bb.0: # %entry 71; CHECK-O0-NEXT: movl %edx, %eax 72; CHECK-O0-NEXT: # kill: def $rax killed $eax 73; CHECK-O0-NEXT: movq %rax, 8(%rcx) 74; CHECK-O0-NEXT: jmp use_foo # TAILCALL 75entry: 76 %0 = addrspacecast i32 addrspace(271)* %i to i32* 77 %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1 78 store i32* %0, i32** %p64, align 8 79 tail call void @use_foo(%struct.Foo* %f) 80 ret void 81} 82 83define dso_local void @test_trunc(%struct.Foo* %f, i32* %i) { 84; CHECK-LABEL: test_trunc: 85; CHECK: # %bb.0: # %entry 86; CHECK-NEXT: movl %edx, (%rcx) 87; CHECK-NEXT: jmp use_foo # TAILCALL 88; 89; CHECK-O0-LABEL: test_trunc: 90; CHECK-O0: # %bb.0: # %entry 91; CHECK-O0-NEXT: movl %edx, %eax 92; CHECK-O0-NEXT: movl %eax, (%rcx) 93; CHECK-O0-NEXT: jmp use_foo # TAILCALL 94entry: 95 %0 = addrspacecast i32* %i to i32 addrspace(270)* 96 %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 97 store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8 98 tail call void @use_foo(%struct.Foo* %f) 99 ret void 100} 101 102define dso_local void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* %i) { 103; ALL-LABEL: test_noop1: 104; ALL: # %bb.0: # %entry 105; ALL-NEXT: movl %edx, (%rcx) 106; ALL-NEXT: jmp use_foo # TAILCALL 107entry: 108 %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 109 store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8 110 tail call void @use_foo(%struct.Foo* %f) 111 ret void 112} 113 114define dso_local void @test_noop2(%struct.Foo* %f, i32* %i) { 115; ALL-LABEL: test_noop2: 116; ALL: # %bb.0: # %entry 117; ALL-NEXT: movq %rdx, 8(%rcx) 118; ALL-NEXT: jmp use_foo # TAILCALL 119entry: 120 %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1 121 store i32* %i, i32** %p64, align 8 122 tail call void @use_foo(%struct.Foo* %f) 123 ret void 124} 125 126; Test that null can be passed as a 32-bit pointer. 127define dso_local void @test_null_arg(%struct.Foo* %f) { 128; ALL-LABEL: test_null_arg: 129; ALL: # %bb.0: # %entry 130; ALL-NEXT: subq $40, %rsp 131; ALL-NEXT: .seh_stackalloc 40 132; ALL-NEXT: .seh_endprologue 133; ALL-NEXT: xorl %edx, %edx 134; ALL-NEXT: callq test_noop1 135; ALL-NEXT: nop 136; ALL-NEXT: addq $40, %rsp 137; ALL-NEXT: retq 138; ALL-NEXT: .seh_endproc 139entry: 140 call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null) 141 ret void 142} 143 144; Test casts between unrecognized address spaces. 145define void @test_unrecognized(%struct.Foo* %f, i32 addrspace(14)* %i) { 146; CHECK-LABEL: test_unrecognized: 147; CHECK: # %bb.0: # %entry 148; CHECK-NEXT: movl %edx, (%rcx) 149; CHECK-NEXT: jmp use_foo # TAILCALL 150; 151; CHECK-O0-LABEL: test_unrecognized: 152; CHECK-O0: # %bb.0: # %entry 153; CHECK-O0-NEXT: movl %edx, %eax 154; CHECK-O0-NEXT: movl %eax, (%rcx) 155; CHECK-O0-NEXT: jmp use_foo # TAILCALL 156entry: 157 %0 = addrspacecast i32 addrspace(14)* %i to i32 addrspace(270)* 158 %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 159 store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8 160 tail call void @use_foo(%struct.Foo* %f) 161 ret void 162} 163 164define void @test_unrecognized2(%struct.Foo* %f, i32 addrspace(271)* %i) { 165; CHECK-LABEL: test_unrecognized2: 166; CHECK: # %bb.0: # %entry 167; CHECK-NEXT: movl %edx, %eax 168; CHECK-NEXT: movq %rax, 16(%rcx) 169; CHECK-NEXT: jmp use_foo # TAILCALL 170; 171; CHECK-O0-LABEL: test_unrecognized2: 172; CHECK-O0: # %bb.0: # %entry 173; CHECK-O0-NEXT: movl %edx, %eax 174; CHECK-O0-NEXT: # kill: def $rax killed $eax 175; CHECK-O0-NEXT: movq %rax, 16(%rcx) 176; CHECK-O0-NEXT: jmp use_foo # TAILCALL 177entry: 178 %0 = addrspacecast i32 addrspace(271)* %i to i32 addrspace(9)* 179 %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 2 180 store i32 addrspace(9)* %0, i32 addrspace(9)** %p32, align 8 181 tail call void @use_foo(%struct.Foo* %f) 182 ret void 183} 184 185define i32 @test_load_sptr32(i32 addrspace(270)* %i) { 186; ALL-LABEL: test_load_sptr32: 187; ALL: # %bb.0: # %entry 188; ALL-NEXT: movslq %ecx, %rax 189; ALL-NEXT: movl (%rax), %eax 190; ALL-NEXT: retq 191entry: 192 %0 = load i32, i32 addrspace(270)* %i, align 4 193 ret i32 %0 194} 195 196define i32 @test_load_uptr32(i32 addrspace(271)* %i) { 197; CHECK-LABEL: test_load_uptr32: 198; CHECK: # %bb.0: # %entry 199; CHECK-NEXT: movl %ecx, %eax 200; CHECK-NEXT: movl (%rax), %eax 201; CHECK-NEXT: retq 202; 203; CHECK-O0-LABEL: test_load_uptr32: 204; CHECK-O0: # %bb.0: # %entry 205; CHECK-O0-NEXT: movl %ecx, %eax 206; CHECK-O0-NEXT: # kill: def $rax killed $eax 207; CHECK-O0-NEXT: movl (%rax), %eax 208; CHECK-O0-NEXT: retq 209entry: 210 %0 = load i32, i32 addrspace(271)* %i, align 4 211 ret i32 %0 212} 213 214define i32 @test_load_ptr64(i32 addrspace(272)* %i) { 215; ALL-LABEL: test_load_ptr64: 216; ALL: # %bb.0: # %entry 217; ALL-NEXT: movl (%rcx), %eax 218; ALL-NEXT: retq 219entry: 220 %0 = load i32, i32 addrspace(272)* %i, align 8 221 ret i32 %0 222} 223 224define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) { 225; ALL-LABEL: test_store_sptr32: 226; ALL: # %bb.0: # %entry 227; ALL-NEXT: movslq %ecx, %rax 228; ALL-NEXT: movl %edx, (%rax) 229; ALL-NEXT: retq 230entry: 231 store i32 %i, i32 addrspace(270)* %s, align 4 232 ret void 233} 234 235define void @test_store_uptr32(i32 addrspace(271)* %s, i32 %i) { 236; CHECK-LABEL: test_store_uptr32: 237; CHECK: # %bb.0: # %entry 238; CHECK-NEXT: movl %ecx, %eax 239; CHECK-NEXT: movl %edx, (%rax) 240; CHECK-NEXT: retq 241; 242; CHECK-O0-LABEL: test_store_uptr32: 243; CHECK-O0: # %bb.0: # %entry 244; CHECK-O0-NEXT: movl %ecx, %eax 245; CHECK-O0-NEXT: # kill: def $rax killed $eax 246; CHECK-O0-NEXT: movl %edx, (%rax) 247; CHECK-O0-NEXT: retq 248entry: 249 store i32 %i, i32 addrspace(271)* %s, align 4 250 ret void 251} 252 253define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) { 254; ALL-LABEL: test_store_ptr64: 255; ALL: # %bb.0: # %entry 256; ALL-NEXT: movl %edx, (%rcx) 257; ALL-NEXT: retq 258entry: 259 store i32 %i, i32 addrspace(272)* %s, align 8 260 ret void 261} 262