1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
2 // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
3 
4 int __attribute__((target("sse4.2"))) foo(void) { return 0; }
5 int __attribute__((target("arch=sandybridge"))) foo(void);
6 int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;}
7 int __attribute__((target("default"))) foo(void) { return 2; }
8 
9 int bar() {
10   return foo();
11 }
12 
13 inline int __attribute__((target("sse4.2"))) foo_inline(void) { return 0; }
14 inline int __attribute__((target("arch=sandybridge"))) foo_inline(void);
15 inline int __attribute__((target("arch=ivybridge"))) foo_inline(void) {return 1;}
16 inline int __attribute__((target("default"))) foo_inline(void) { return 2; }
17 
18 int bar2() {
19   return foo_inline();
20 }
21 
22 inline __attribute__((target("default"))) void foo_decls(void);
23 inline __attribute__((target("sse4.2"))) void foo_decls(void);
24 void bar3() {
25   foo_decls();
26 }
27 inline __attribute__((target("default"))) void foo_decls(void) {}
28 inline __attribute__((target("sse4.2"))) void foo_decls(void) {}
29 
30 inline __attribute__((target("default"))) void foo_multi(int i, double d) {}
31 inline __attribute__((target("avx,sse4.2"))) void foo_multi(int i, double d) {}
32 inline __attribute__((target("sse4.2,fma4"))) void foo_multi(int i, double d) {}
33 inline __attribute__((target("arch=ivybridge,fma4,sse4.2"))) void foo_multi(int i, double d) {}
34 void bar4() {
35   foo_multi(1, 5.0);
36 }
37 
38 int fwd_decl_default(void);
39 int __attribute__((target("default"))) fwd_decl_default(void) { return 2; }
40 
41 int fwd_decl_avx(void);
42 int __attribute__((target("avx"))) fwd_decl_avx(void) { return 2; }
43 int __attribute__((target("default"))) fwd_decl_avx(void) { return 2; }
44 
45 void bar5() {
46   fwd_decl_default();
47   fwd_decl_avx();
48 }
49 
50 // LINUX: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver
51 // LINUX: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver
52 // LINUX: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver
53 // LINUX: @foo_multi.ifunc = ifunc void (i32, double), void (i32, double)* ()* @foo_multi.resolver
54 // LINUX: @fwd_decl_default.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_default.resolver
55 // LINUX: @fwd_decl_avx.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_avx.resolver
56 
57 // LINUX: define i32 @foo.sse4.2()
58 // LINUX: ret i32 0
59 // LINUX: define i32 @foo.arch_ivybridge()
60 // LINUX: ret i32 1
61 // LINUX: define i32 @foo()
62 // LINUX: ret i32 2
63 // LINUX: define i32 @bar()
64 // LINUX: call i32 @foo.ifunc()
65 
66 // WINDOWS: define dso_local i32 @foo.sse4.2()
67 // WINDOWS: ret i32 0
68 // WINDOWS: define dso_local i32 @foo.arch_ivybridge()
69 // WINDOWS: ret i32 1
70 // WINDOWS: define dso_local i32 @foo()
71 // WINDOWS: ret i32 2
72 // WINDOWS: define dso_local i32 @bar()
73 // WINDOWS: call i32 @foo.resolver()
74 
75 // LINUX: define i32 ()* @foo.resolver() comdat
76 // LINUX: call void @__cpu_indicator_init()
77 // LINUX: ret i32 ()* @foo.arch_sandybridge
78 // LINUX: ret i32 ()* @foo.arch_ivybridge
79 // LINUX: ret i32 ()* @foo.sse4.2
80 // LINUX: ret i32 ()* @foo
81 
82 // WINDOWS: define dso_local i32 @foo.resolver() comdat
83 // WINDOWS: call void @__cpu_indicator_init()
84 // WINDOWS: call i32 @foo.arch_sandybridge
85 // WINDOWS: call i32 @foo.arch_ivybridge
86 // WINDOWS: call i32 @foo.sse4.2
87 // WINDOWS: call i32 @foo
88 
89 // LINUX: define i32 @bar2()
90 // LINUX: call i32 @foo_inline.ifunc()
91 
92 // WINDOWS: define dso_local i32 @bar2()
93 // WINDOWS: call i32 @foo_inline.resolver()
94 
95 // LINUX: define i32 ()* @foo_inline.resolver() comdat
96 // LINUX: call void @__cpu_indicator_init()
97 // LINUX: ret i32 ()* @foo_inline.arch_sandybridge
98 // LINUX: ret i32 ()* @foo_inline.arch_ivybridge
99 // LINUX: ret i32 ()* @foo_inline.sse4.2
100 // LINUX: ret i32 ()* @foo_inline
101 
102 // WINDOWS: define dso_local i32 @foo_inline.resolver() comdat
103 // WINDOWS: call void @__cpu_indicator_init()
104 // WINDOWS: call i32 @foo_inline.arch_sandybridge
105 // WINDOWS: call i32 @foo_inline.arch_ivybridge
106 // WINDOWS: call i32 @foo_inline.sse4.2
107 // WINDOWS: call i32 @foo_inline
108 
109 // LINUX: define void @bar3()
110 // LINUX: call void @foo_decls.ifunc()
111 
112 // WINDOWS: define dso_local void @bar3()
113 // WINDOWS: call void @foo_decls.resolver()
114 
115 // LINUX: define void ()* @foo_decls.resolver() comdat
116 // LINUX: ret void ()* @foo_decls.sse4.2
117 // LINUX: ret void ()* @foo_decls
118 
119 // WINDOWS: define dso_local void @foo_decls.resolver() comdat
120 // WINDOWS: call void @foo_decls.sse4.2
121 // WINDOWS: call void @foo_decls
122 
123 // LINUX: define void @bar4()
124 // LINUX: call void @foo_multi.ifunc(i32 1, double 5.{{[0+e]*}})
125 
126 // WINDOWS: define dso_local void @bar4()
127 // WINDOWS: call void @foo_multi.resolver(i32 1, double 5.{{[0+e]*}})
128 
129 // LINUX: define void (i32, double)* @foo_multi.resolver() comdat
130 // LINUX: and i32 %{{.*}}, 4352
131 // LINUX: icmp eq i32 %{{.*}}, 4352
132 // LINUX: ret void (i32, double)* @foo_multi.fma4_sse4.2
133 // LINUX: icmp eq i32 %{{.*}}, 12
134 // LINUX: and i32 %{{.*}}, 4352
135 // LINUX: icmp eq i32 %{{.*}}, 4352
136 // LINUX: ret void (i32, double)* @foo_multi.arch_ivybridge_fma4_sse4.2
137 // LINUX: and i32 %{{.*}}, 768
138 // LINUX: icmp eq i32 %{{.*}}, 768
139 // LINUX: ret void (i32, double)* @foo_multi.avx_sse4.2
140 // LINUX: ret void (i32, double)* @foo_multi
141 
142 // WINDOWS: define dso_local void @foo_multi.resolver(i32, double) comdat
143 // WINDOWS: and i32 %{{.*}}, 4352
144 // WINDOWS: icmp eq i32 %{{.*}}, 4352
145 // WINDOWS: call void @foo_multi.fma4_sse4.2(i32 %0, double %1)
146 // WINDOWS-NEXT: ret void
147 // WINDOWS: icmp eq i32 %{{.*}}, 12
148 // WINDOWS: and i32 %{{.*}}, 4352
149 // WINDOWS: icmp eq i32 %{{.*}}, 4352
150 // WINDOWS: call void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %0, double %1)
151 // WINDOWS-NEXT: ret void
152 // WINDOWS: and i32 %{{.*}}, 768
153 // WINDOWS: icmp eq i32 %{{.*}}, 768
154 // WINDOWS: call void @foo_multi.avx_sse4.2(i32 %0, double %1)
155 // WINDOWS-NEXT: ret void
156 // WINDOWS: call void @foo_multi(i32 %0, double %1)
157 // WINDOWS-NEXT: ret void
158 
159 // LINUX: define i32 @fwd_decl_default()
160 // LINUX: ret i32 2
161 // LINUX: define i32 @fwd_decl_avx.avx()
162 // LINUX: ret i32 2
163 // LINUX: define i32 @fwd_decl_avx()
164 // LINUX: ret i32 2
165 
166 // WINDOWS: define dso_local i32 @fwd_decl_default()
167 // WINDOWS: ret i32 2
168 // WINDOWS: define dso_local i32 @fwd_decl_avx.avx()
169 // WINDOWS: ret i32 2
170 // WINDOWS: define dso_local i32 @fwd_decl_avx()
171 // WINDOWS: ret i32 2
172 
173 // LINUX: define void @bar5()
174 // LINUX: call i32 @fwd_decl_default.ifunc()
175 // LINUX: call i32 @fwd_decl_avx.ifunc()
176 
177 // WINDOWS: define dso_local void @bar5()
178 // WINDOWS: call i32 @fwd_decl_default.resolver()
179 // WINDOWS: call i32 @fwd_decl_avx.resolver()
180 
181 // LINUX: define i32 ()* @fwd_decl_default.resolver() comdat
182 // LINUX: call void @__cpu_indicator_init()
183 // LINUX: ret i32 ()* @fwd_decl_default
184 // LINUX: define i32 ()* @fwd_decl_avx.resolver() comdat
185 // LINUX: call void @__cpu_indicator_init()
186 // LINUX: ret i32 ()* @fwd_decl_avx.avx
187 // LINUX: ret i32 ()* @fwd_decl_avx
188 
189 // WINDOWS: define dso_local i32 @fwd_decl_default.resolver() comdat
190 // WINDOWS: call void @__cpu_indicator_init()
191 // WINDOWS: call i32 @fwd_decl_default
192 // WINDOWS: define dso_local i32 @fwd_decl_avx.resolver() comdat
193 // WINDOWS: call void @__cpu_indicator_init()
194 // WINDOWS: call i32 @fwd_decl_avx.avx
195 // WINDOWS: call i32 @fwd_decl_avx
196 
197 // LINUX: declare i32 @foo.arch_sandybridge()
198 // WINDOWS: declare dso_local i32 @foo.arch_sandybridge()
199 
200 // LINUX: define linkonce i32 @foo_inline.sse4.2()
201 // LINUX: ret i32 0
202 
203 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2()
204 // WINDOWS: ret i32 0
205 
206 // LINUX: declare i32 @foo_inline.arch_sandybridge()
207 
208 // WINDOWS: declare dso_local i32 @foo_inline.arch_sandybridge()
209 
210 // LINUX: define linkonce i32 @foo_inline.arch_ivybridge()
211 // LINUX: ret i32 1
212 // LINUX: define linkonce i32 @foo_inline()
213 // LINUX: ret i32 2
214 
215 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_ivybridge()
216 // WINDOWS: ret i32 1
217 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline()
218 // WINDOWS: ret i32 2
219 
220 // LINUX: define linkonce void @foo_decls()
221 // LINUX: define linkonce void @foo_decls.sse4.2()
222 
223 // WINDOWS: define linkonce_odr dso_local void @foo_decls()
224 // WINDOWS: define linkonce_odr dso_local void @foo_decls.sse4.2()
225 
226 // LINUX: define linkonce void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
227 // LINUX: define linkonce void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
228 // LINUX: define linkonce void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
229 // LINUX: define linkonce void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
230 
231 // WINDOWS: define linkonce_odr dso_local void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
232 // WINDOWS: define linkonce_odr dso_local void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
233 // WINDOWS: define linkonce_odr dso_local void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
234 // WINDOWS: define linkonce_odr dso_local void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
235