1; RUN: llc < %s | FileCheck --check-prefixes=CHECK %s
2; RUN: llc -O0 < %s | FileCheck --check-prefixes=CHECK %s
3
4; Source to regenerate:
5; struct Foo {
6;   int * __ptr32 p32;
7;   int * __ptr64 p64;
8;   __attribute__((address_space(9))) int *p_other;
9; };
10; void use_foo(Foo *f);
11; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
12;   f->p64 = i;
13;   use_foo(f);
14; }
15; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
16;   f->p64 = i;
17;   use_foo(f);
18; }
19; void test_trunc(Foo *f, int * __ptr64 i) {
20;   f->p32 = i;
21;   use_foo(f);
22; }
23; void test_noop1(Foo *f, int * __ptr32 i) {
24;   f->p32 = i;
25;   use_foo(f);
26; }
27; void test_noop2(Foo *f, int * __ptr64 i) {
28;   f->p64 = i;
29;   use_foo(f);
30; }
31; void test_null_arg(Foo *f, int * __ptr32 i) {
32;   test_noop1(f, 0);
33; }
34; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
35;   f->p32 = (int * __ptr32)i;
36;   use_foo(f);
37; }
38;
39; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
40
41target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
42target triple = "x86_64-unknown-windows-msvc"
43
44%struct.Foo = type { i32 addrspace(270)*, i32*, i32 addrspace(9)* }
45declare dso_local void @use_foo(%struct.Foo*)
46
47define dso_local void @test_sign_ext(%struct.Foo* %f, i32 addrspace(270)* %i) {
48; CHECK-LABEL: test_sign_ext
49; CHECK:       movslq %edx, %rax
50entry:
51  %0 = addrspacecast i32 addrspace(270)* %i to i32*
52  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
53  store i32* %0, i32** %p64, align 8
54  tail call void @use_foo(%struct.Foo* %f)
55  ret void
56}
57
58define dso_local void @test_zero_ext(%struct.Foo* %f, i32 addrspace(271)* %i) {
59; CHECK-LABEL: test_zero_ext
60; CHECK:       movl %edx, %eax
61entry:
62  %0 = addrspacecast i32 addrspace(271)* %i to i32*
63  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
64  store i32* %0, i32** %p64, align 8
65  tail call void @use_foo(%struct.Foo* %f)
66  ret void
67}
68
69define dso_local void @test_trunc(%struct.Foo* %f, i32* %i) {
70; CHECK-LABEL: test_trunc
71; CHECK:       movl %edx, (%rcx)
72entry:
73  %0 = addrspacecast i32* %i to i32 addrspace(270)*
74  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
75  store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
76  tail call void @use_foo(%struct.Foo* %f)
77  ret void
78}
79
80define dso_local void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* %i) {
81; CHECK-LABEL: test_noop1
82; CHECK:       movl %edx, (%rcx)
83entry:
84  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
85  store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8
86  tail call void @use_foo(%struct.Foo* %f)
87  ret void
88}
89
90define dso_local void @test_noop2(%struct.Foo* %f, i32* %i) {
91; CHECK-LABEL: test_noop2
92; CHECK:       movq %rdx, 8(%rcx)
93entry:
94  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
95  store i32* %i, i32** %p64, align 8
96  tail call void @use_foo(%struct.Foo* %f)
97  ret void
98}
99
100; Test that null can be passed as a 32-bit pointer.
101define dso_local void @test_null_arg(%struct.Foo* %f) {
102entry:
103  call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null)
104  ret void
105}
106
107; Test casts between unrecognized address spaces.
108define void @test_unrecognized(%struct.Foo* %f, i32 addrspace(14)* %i) {
109; CHECK-LABEL: test_unrecognized
110; CHECK:       movl %edx, (%rcx)
111entry:
112  %0 = addrspacecast i32 addrspace(14)* %i to i32 addrspace(270)*
113  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
114  store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
115  tail call void @use_foo(%struct.Foo* %f)
116  ret void
117}
118
119define void @test_unrecognized2(%struct.Foo* %f, i32 addrspace(271)* %i) {
120; CHECK-LABEL: test_unrecognized2
121; CHECK:       movl %edx, %eax
122entry:
123  %0 = addrspacecast i32 addrspace(271)* %i to i32 addrspace(9)*
124  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 2
125  store i32 addrspace(9)* %0, i32 addrspace(9)** %p32, align 8
126  tail call void @use_foo(%struct.Foo* %f)
127  ret void
128}
129