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 { ptr addrspace(270), ptr, ptr addrspace(9) } 46declare dso_local void @use_foo(ptr) 47 48define dso_local void @test_sign_ext(ptr %f, ptr 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 ptr addrspace(270) %i to ptr 56 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 57 store ptr %0, ptr %p64, align 8 58 tail call void @use_foo(ptr %f) 59 ret void 60} 61 62define dso_local void @test_zero_ext(ptr %f, ptr 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 ptr addrspace(271) %i to ptr 77 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 78 store ptr %0, ptr %p64, align 8 79 tail call void @use_foo(ptr %f) 80 ret void 81} 82 83define dso_local void @test_trunc(ptr %f, ptr %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 ptr %i to ptr addrspace(270) 96 store ptr addrspace(270) %0, ptr %f, align 8 97 tail call void @use_foo(ptr %f) 98 ret void 99} 100 101define dso_local void @test_noop1(ptr %f, ptr addrspace(270) %i) { 102; ALL-LABEL: test_noop1: 103; ALL: # %bb.0: # %entry 104; ALL-NEXT: movl %edx, (%rcx) 105; ALL-NEXT: jmp use_foo # TAILCALL 106entry: 107 store ptr addrspace(270) %i, ptr %f, align 8 108 tail call void @use_foo(ptr %f) 109 ret void 110} 111 112define dso_local void @test_noop2(ptr %f, ptr %i) { 113; ALL-LABEL: test_noop2: 114; ALL: # %bb.0: # %entry 115; ALL-NEXT: movq %rdx, 8(%rcx) 116; ALL-NEXT: jmp use_foo # TAILCALL 117entry: 118 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 119 store ptr %i, ptr %p64, align 8 120 tail call void @use_foo(ptr %f) 121 ret void 122} 123 124; Test that null can be passed as a 32-bit pointer. 125define dso_local void @test_null_arg(ptr %f) { 126; ALL-LABEL: test_null_arg: 127; ALL: # %bb.0: # %entry 128; ALL-NEXT: subq $40, %rsp 129; ALL-NEXT: .seh_stackalloc 40 130; ALL-NEXT: .seh_endprologue 131; ALL-NEXT: xorl %edx, %edx 132; ALL-NEXT: callq test_noop1 133; ALL-NEXT: nop 134; ALL-NEXT: addq $40, %rsp 135; ALL-NEXT: retq 136; ALL-NEXT: .seh_endproc 137entry: 138 call void @test_noop1(ptr %f, ptr addrspace(270) null) 139 ret void 140} 141 142; Test casts between unrecognized address spaces. 143define void @test_unrecognized(ptr %f, ptr addrspace(14) %i) { 144; CHECK-LABEL: test_unrecognized: 145; CHECK: # %bb.0: # %entry 146; CHECK-NEXT: movl %edx, (%rcx) 147; CHECK-NEXT: jmp use_foo # TAILCALL 148; 149; CHECK-O0-LABEL: test_unrecognized: 150; CHECK-O0: # %bb.0: # %entry 151; CHECK-O0-NEXT: movl %edx, %eax 152; CHECK-O0-NEXT: movl %eax, (%rcx) 153; CHECK-O0-NEXT: jmp use_foo # TAILCALL 154entry: 155 %0 = addrspacecast ptr addrspace(14) %i to ptr addrspace(270) 156 store ptr addrspace(270) %0, ptr %f, align 8 157 tail call void @use_foo(ptr %f) 158 ret void 159} 160 161define void @test_unrecognized2(ptr %f, ptr addrspace(271) %i) { 162; CHECK-LABEL: test_unrecognized2: 163; CHECK: # %bb.0: # %entry 164; CHECK-NEXT: movl %edx, %eax 165; CHECK-NEXT: movq %rax, 16(%rcx) 166; CHECK-NEXT: jmp use_foo # TAILCALL 167; 168; CHECK-O0-LABEL: test_unrecognized2: 169; CHECK-O0: # %bb.0: # %entry 170; CHECK-O0-NEXT: movl %edx, %eax 171; CHECK-O0-NEXT: # kill: def $rax killed $eax 172; CHECK-O0-NEXT: movq %rax, 16(%rcx) 173; CHECK-O0-NEXT: jmp use_foo # TAILCALL 174entry: 175 %0 = addrspacecast ptr addrspace(271) %i to ptr addrspace(9) 176 %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2 177 store ptr addrspace(9) %0, ptr %p32, align 8 178 tail call void @use_foo(ptr %f) 179 ret void 180} 181 182define i32 @test_load_sptr32(ptr addrspace(270) %i) { 183; ALL-LABEL: test_load_sptr32: 184; ALL: # %bb.0: # %entry 185; ALL-NEXT: movslq %ecx, %rax 186; ALL-NEXT: movl (%rax), %eax 187; ALL-NEXT: retq 188entry: 189 %0 = load i32, ptr addrspace(270) %i, align 4 190 ret i32 %0 191} 192 193define i32 @test_load_uptr32(ptr addrspace(271) %i) { 194; CHECK-LABEL: test_load_uptr32: 195; CHECK: # %bb.0: # %entry 196; CHECK-NEXT: movl %ecx, %eax 197; CHECK-NEXT: movl (%rax), %eax 198; CHECK-NEXT: retq 199; 200; CHECK-O0-LABEL: test_load_uptr32: 201; CHECK-O0: # %bb.0: # %entry 202; CHECK-O0-NEXT: movl %ecx, %eax 203; CHECK-O0-NEXT: # kill: def $rax killed $eax 204; CHECK-O0-NEXT: movl (%rax), %eax 205; CHECK-O0-NEXT: retq 206entry: 207 %0 = load i32, ptr addrspace(271) %i, align 4 208 ret i32 %0 209} 210 211define i32 @test_load_ptr64(ptr addrspace(272) %i) { 212; ALL-LABEL: test_load_ptr64: 213; ALL: # %bb.0: # %entry 214; ALL-NEXT: movl (%rcx), %eax 215; ALL-NEXT: retq 216entry: 217 %0 = load i32, ptr addrspace(272) %i, align 8 218 ret i32 %0 219} 220 221define void @test_store_sptr32(ptr addrspace(270) %s, i32 %i) { 222; ALL-LABEL: test_store_sptr32: 223; ALL: # %bb.0: # %entry 224; ALL-NEXT: movslq %ecx, %rax 225; ALL-NEXT: movl %edx, (%rax) 226; ALL-NEXT: retq 227entry: 228 store i32 %i, ptr addrspace(270) %s, align 4 229 ret void 230} 231 232define void @test_store_uptr32(ptr addrspace(271) %s, i32 %i) { 233; CHECK-LABEL: test_store_uptr32: 234; CHECK: # %bb.0: # %entry 235; CHECK-NEXT: movl %ecx, %eax 236; CHECK-NEXT: movl %edx, (%rax) 237; CHECK-NEXT: retq 238; 239; CHECK-O0-LABEL: test_store_uptr32: 240; CHECK-O0: # %bb.0: # %entry 241; CHECK-O0-NEXT: movl %ecx, %eax 242; CHECK-O0-NEXT: # kill: def $rax killed $eax 243; CHECK-O0-NEXT: movl %edx, (%rax) 244; CHECK-O0-NEXT: retq 245entry: 246 store i32 %i, ptr addrspace(271) %s, align 4 247 ret void 248} 249 250define void @test_store_ptr64(ptr addrspace(272) %s, i32 %i) { 251; ALL-LABEL: test_store_ptr64: 252; ALL: # %bb.0: # %entry 253; ALL-NEXT: movl %edx, (%rcx) 254; ALL-NEXT: retq 255entry: 256 store i32 %i, ptr addrspace(272) %s, align 8 257 ret void 258} 259 260define i64 @test_load_sptr32_zext_i64(ptr addrspace(270) %i) { 261; CHECK-LABEL: test_load_sptr32_zext_i64: 262; CHECK: # %bb.0: # %entry 263; CHECK-NEXT: movslq %ecx, %rax 264; CHECK-NEXT: movl (%rax), %eax 265; CHECK-NEXT: retq 266; 267; CHECK-O0-LABEL: test_load_sptr32_zext_i64: 268; CHECK-O0: # %bb.0: # %entry 269; CHECK-O0-NEXT: movslq %ecx, %rax 270; CHECK-O0-NEXT: movl (%rax), %eax 271; CHECK-O0-NEXT: movl %eax, %eax 272; CHECK-O0-NEXT: # kill: def $rax killed $eax 273; CHECK-O0-NEXT: retq 274entry: 275 %0 = load i32, ptr addrspace(270) %i, align 4 276 %1 = zext i32 %0 to i64 277 ret i64 %1 278} 279 280define void @test_store_sptr32_trunc_i1(ptr addrspace(270) %s, i32 %i) { 281; CHECK-LABEL: test_store_sptr32_trunc_i1: 282; CHECK: # %bb.0: # %entry 283; CHECK-NEXT: movslq %ecx, %rax 284; CHECK-NEXT: andl $1, %edx 285; CHECK-NEXT: movb %dl, (%rax) 286; CHECK-NEXT: retq 287; 288; CHECK-O0-LABEL: test_store_sptr32_trunc_i1: 289; CHECK-O0: # %bb.0: # %entry 290; CHECK-O0-NEXT: movslq %ecx, %rax 291; CHECK-O0-NEXT: andl $1, %edx 292; CHECK-O0-NEXT: movb %dl, %cl 293; CHECK-O0-NEXT: movb %cl, (%rax) 294; CHECK-O0-NEXT: retq 295entry: 296 %0 = trunc i32 %i to i1 297 store i1 %0, ptr addrspace(270) %s 298 ret void 299} 300