1 // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
3 
4 struct S {
fooS5   int __attribute__((target("sse4.2"))) foo(int) { return 0; }
6   int __attribute__((target("arch=sandybridge"))) foo(int);
fooS7   int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; }
fooS8   int __attribute__((target("default"))) foo(int) { return 2; }
9 
operator =S10   S &__attribute__((target("arch=ivybridge"))) operator=(const S &) {
11     return *this;
12   }
operator =S13   S &__attribute__((target("default"))) operator=(const S &) {
14     return *this;
15   }
16 };
17 
18 struct ConvertTo {
operator SConvertTo19   __attribute__((target("arch=ivybridge"))) operator S() const {
20     return S{};
21   }
operator SConvertTo22   __attribute__((target("default"))) operator S() const {
23     return S{};
24   }
25 };
26 
bar()27 int bar() {
28   S s;
29   S s2;
30   s2 = s;
31 
32   ConvertTo C;
33   s2 = static_cast<S>(C);
34 
35   return s.foo(0);
36 }
37 
38 struct S2 {
39   int __attribute__((target("sse4.2"))) foo(int);
40   int __attribute__((target("arch=sandybridge"))) foo(int);
41   int __attribute__((target("arch=ivybridge"))) foo(int);
42   int __attribute__((target("default"))) foo(int);
43 };
44 
bar2()45 int bar2() {
46   S2 s;
47   return s.foo(0);
48 }
49 
foo(int)50 int __attribute__((target("sse4.2"))) S2::foo(int) { return 0; }
foo(int)51 int __attribute__((target("arch=ivybridge"))) S2::foo(int) { return 1; }
foo(int)52 int __attribute__((target("default"))) S2::foo(int) { return 2; }
53 
54 template<typename T>
55 struct templ {
footempl56   int __attribute__((target("sse4.2"))) foo(int) { return 0; }
57   int __attribute__((target("arch=sandybridge"))) foo(int);
footempl58   int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; }
footempl59   int __attribute__((target("default"))) foo(int) { return 2; }
60 };
61 
templ_use()62 int templ_use() {
63   templ<int> a;
64   templ<double> b;
65   return a.foo(1) + b.foo(2);
66 }
67 
68 // LINUX: @_ZN1SaSERKS_.ifunc = weak_odr ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
69 // LINUX: @_ZNK9ConvertTocv1SEv.ifunc = weak_odr ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
70 // LINUX: @_ZN1S3fooEi.ifunc = weak_odr ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
71 // LINUX: @_ZN2S23fooEi.ifunc = weak_odr ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
72 // Templates:
73 // LINUX: @_ZN5templIiE3fooEi.ifunc = weak_odr ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
74 // LINUX: @_ZN5templIdE3fooEi.ifunc = weak_odr ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
75 
76 // LINUX: define{{.*}} i32 @_Z3barv()
77 // LINUX: %s = alloca %struct.S, align 1
78 // LINUX: %s2 = alloca %struct.S, align 1
79 // LINUX: %C = alloca %struct.ConvertTo, align 1
80 // LINUX: call nonnull align 1 dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* {{[^,]*}} %s2
81 // LINUX: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* {{[^,]*}} %C)
82 // LINUX: call nonnull align 1 dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* {{[^,]*}} %s2
83 // LINUX: call i32 @_ZN1S3fooEi.ifunc(%struct.S* {{[^,]*}} %s, i32 0)
84 
85 // WINDOWS: define dso_local i32 @"?bar@@YAHXZ"()
86 // WINDOWS: %s = alloca %struct.S, align 1
87 // WINDOWS: %s2 = alloca %struct.S, align 1
88 // WINDOWS: %C = alloca %struct.ConvertTo, align 1
89 // WINDOWS: call nonnull align 1 dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* {{[^,]*}} %s2
90 // WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* {{[^,]*}} %C
91 // WINDOWS: call nonnull align 1 dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* {{[^,]*}} %s2
92 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* {{[^,]*}} %s, i32 0)
93 
94 // LINUX: define weak_odr %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
95 // LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge
96 // LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_
97 
98 // WINDOWS: define weak_odr dso_local %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %0, %struct.S* %1)
99 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.arch_ivybridge"
100 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z"
101 
102 // LINUX: define weak_odr void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
103 // LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge
104 // LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv
105 
106 // WINDOWS: define weak_odr dso_local void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* %0, %struct.S* %1)
107 // WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.arch_ivybridge"
108 // WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ"
109 
110 // LINUX: define weak_odr i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
111 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
112 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
113 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
114 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
115 
116 // WINDOWS: define weak_odr dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %0, i32 %1)
117 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"
118 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"
119 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"
120 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z"
121 
122 // LINUX: define{{.*}} i32 @_Z4bar2v()
123 // LINUX: call i32 @_ZN2S23fooEi.ifunc
124 
125 // WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"()
126 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.resolver"
127 
128 // LINUX: define weak_odr i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
129 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge
130 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge
131 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2
132 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi
133 
134 // WINDOWS: define weak_odr dso_local i32 @"?foo@S2@@QEAAHH@Z.resolver"(%struct.S2* %0, i32 %1)
135 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_sandybridge"
136 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"
137 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.sse4.2"
138 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z"
139 
140 // LINUX: define{{.*}} i32 @_ZN2S23fooEi.sse4.2(%struct.S2* {{[^,]*}} %this, i32 %0)
141 // LINUX: define{{.*}} i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* {{[^,]*}} %this, i32 %0)
142 // LINUX: define{{.*}} i32 @_ZN2S23fooEi(%struct.S2* {{[^,]*}} %this, i32 %0)
143 
144 // WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.sse4.2"(%struct.S2* {{[^,]*}} %this, i32 %0)
145 // WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"(%struct.S2* {{[^,]*}} %this, i32 %0)
146 // WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z"(%struct.S2* {{[^,]*}} %this, i32 %0)
147 
148 // LINUX: define{{.*}} i32 @_Z9templ_usev()
149 // LINUX: call i32 @_ZN5templIiE3fooEi.ifunc
150 // LINUX: call i32 @_ZN5templIdE3fooEi.ifunc
151 
152 // WINDOWS: define dso_local i32 @"?templ_use@@YAHXZ"()
153 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"
154 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"
155 
156 // LINUX: define weak_odr i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
157 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
158 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
159 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
160 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
161 
162 // WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"(%struct.templ* %0, i32 %1)
163 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge"
164 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge"
165 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2"
166 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z"
167 
168 // LINUX: define weak_odr i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
169 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
170 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
171 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
172 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
173 
174 // WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"(%struct.templ.0* %0, i32 %1) comdat
175 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge"
176 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge"
177 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2"
178 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z"
179 
180 // LINUX: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* {{[^,]*}} %this, i32 %0)
181 // LINUX: ret i32 0
182 
183 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* {{[^,]*}} %this, i32 %0)
184 // WINDOWS: ret i32 0
185 
186 // LINUX: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S* {{[^,]*}}, i32)
187 
188 // WINDOWS: declare dso_local i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S* {{[^,]*}}, i32)
189 
190 // LINUX: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* {{[^,]*}} %this, i32 %0)
191 // LINUX: ret i32 1
192 
193 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* {{[^,]*}} %this, i32 %0)
194 // WINDOWS: ret i32 1
195 
196 // LINUX: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* {{[^,]*}} %this, i32 %0)
197 // LINUX: ret i32 2
198 
199 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z"(%struct.S* {{[^,]*}} %this, i32 %0)
200 // WINDOWS: ret i32 2
201 
202 // LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2
203 // LINUX: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
204 // LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge
205 // LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi
206 
207 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2"
208 // WINDOWS: declare dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge"
209 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge"
210 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z"
211 
212 // LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2
213 // LINUX: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge
214 // LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge
215 // LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi
216 
217 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2"
218 // WINDOWS: declare dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge"
219 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge"
220 // WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z"
221