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