325 lines · c
1// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LINUX,CHECK2// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=DARWIN,CHECK3// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefixes=WINDOWS,CHECK4 5// LINUX: $foo.resolver = comdat any6// LINUX: $foo_dupes.resolver = comdat any7// LINUX: $unused.resolver = comdat any8// LINUX: $foo_inline.resolver = comdat any9// LINUX: $foo_inline2.resolver = comdat any10 11// DARWIN-NOT: comdat any12 13// WINDOWS: $foo = comdat any14// WINDOWS: $foo_dupes = comdat any15// WINDOWS: $unused = comdat any16// WINDOWS: $foo_inline = comdat any17// WINDOWS: $foo_inline2 = comdat any18 19// LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }20// LINUX: @__cpu_features2 = external dso_local global [3 x i32]21 22// DARWIN: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }23// DARWIN: @__cpu_features2 = external dso_local global [3 x i32]24 25// LINUX: @internal.ifunc = internal alias i32 (), ptr @internal26// LINUX: @foo.ifunc = weak_odr alias i32 (), ptr @foo27// LINUX: @foo_dupes.ifunc = weak_odr alias void (), ptr @foo_dupes28// LINUX: @unused.ifunc = weak_odr alias void (), ptr @unused29// LINUX: @foo_inline.ifunc = weak_odr alias i32 (), ptr @foo_inline30// LINUX: @foo_inline2.ifunc = weak_odr alias i32 (), ptr @foo_inline231// LINUX: @foo_used_no_defn.ifunc = weak_odr alias i32 (), ptr @foo_used_no_defn32// LINUX: @isa_level.ifunc = weak_odr alias i32 (i32), ptr @isa_level33 34// LINUX: @internal = internal ifunc i32 (), ptr @internal.resolver35// LINUX: @foo = weak_odr ifunc i32 (), ptr @foo.resolver36// LINUX: @foo_dupes = weak_odr ifunc void (), ptr @foo_dupes.resolver37// LINUX: @unused = weak_odr ifunc void (), ptr @unused.resolver38// LINUX: @foo_inline = weak_odr ifunc i32 (), ptr @foo_inline.resolver39// LINUX: @foo_inline2 = weak_odr ifunc i32 (), ptr @foo_inline2.resolver40// LINUX: @foo_used_no_defn = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver41// LINUX: @isa_level = weak_odr ifunc i32 (i32), ptr @isa_level.resolver42 43 44static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }45int use(void) { return internal(); }46/// Internal linkage resolvers do not use comdat.47// LINUX: define internal ptr @internal.resolver() #[[ATTR_RESOLVER:[0-9]+]] {48// DARWIN: define internal ptr @internal.resolver() #[[ATTR_RESOLVER:[0-9]+]] {49// WINDOWS: define internal i32 @internal() #[[ATTR_RESOLVER:[0-9]+]] {50 51int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }52// LINUX: define {{.*}}i32 @foo.sse4.2.0()53// LINUX: define {{.*}}i32 @foo.default.1()54// LINUX: define weak_odr ptr @foo.resolver() #[[ATTR_RESOLVER]] comdat55// LINUX: ret ptr @foo.sse4.2.056// LINUX: ret ptr @foo.default.157 58// DARWIN: define {{.*}}i32 @foo.sse4.2.0()59// DARWIN: define {{.*}}i32 @foo.default.1()60// DARWIN: define weak_odr ptr @foo.resolver() #[[ATTR_RESOLVER]] {61// DARWIN: ret ptr @foo.sse4.2.062// DARWIN: ret ptr @foo.default.163 64// WINDOWS: define dso_local i32 @foo.sse4.2.0()65// WINDOWS: define dso_local i32 @foo.default.1()66// WINDOWS: define weak_odr dso_local i32 @foo() #[[ATTR_RESOLVER]] comdat67// WINDOWS: musttail call i32 @foo.sse4.2.068// WINDOWS: musttail call i32 @foo.default.169 70__attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {}71// LINUX: define {{.*}}void @foo_dupes.default.1()72// LINUX: define {{.*}}void @foo_dupes.sse4.2.0()73// LINUX: define weak_odr ptr @foo_dupes.resolver() #[[ATTR_RESOLVER]] comdat74// LINUX: ret ptr @foo_dupes.sse4.2.075// LINUX: ret ptr @foo_dupes.default.176 77// DARWIN: define {{.*}}void @foo_dupes.default.1()78// DARWIN: define {{.*}}void @foo_dupes.sse4.2.0()79// DARWIN: define weak_odr ptr @foo_dupes.resolver() #[[ATTR_RESOLVER]] {80// DARWIN: ret ptr @foo_dupes.sse4.2.081// DARWIN: ret ptr @foo_dupes.default.182 83// WINDOWS: define dso_local void @foo_dupes.default.1()84// WINDOWS: define dso_local void @foo_dupes.sse4.2.0()85// WINDOWS: define weak_odr dso_local void @foo_dupes() #[[ATTR_RESOLVER]] comdat86// WINDOWS: musttail call void @foo_dupes.sse4.2.087// WINDOWS: musttail call void @foo_dupes.default.188 89void bar2(void) {90 // LINUX: define {{.*}}void @bar2()91 // DARWIN: define {{.*}}void @bar2()92 // WINDOWS: define dso_local void @bar2()93 foo_dupes();94 // LINUX: call void @foo_dupes()95 // DARWIN: call void @foo_dupes()96 // WINDOWS: call void @foo_dupes()97}98 99int bar(void) {100 // LINUX: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]101 // DARWIN: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]102 // WINDOWS: define dso_local i32 @bar() #[[DEF:[0-9]+]]103 return foo();104 // LINUX: call i32 @foo()105 // DARWIN: call i32 @foo()106 // WINDOWS: call i32 @foo()107}108 109void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}110// LINUX: define {{.*}}void @unused.default.1()111// LINUX: define {{.*}}void @unused.arch_ivybridge.0()112// LINUX: define weak_odr ptr @unused.resolver() #[[ATTR_RESOLVER]] comdat113// LINUX: ret ptr @unused.arch_ivybridge.0114// LINUX: ret ptr @unused.default.1115 116// DARWIN: define {{.*}}void @unused.default.1()117// DARWIN: define {{.*}}void @unused.arch_ivybridge.0()118// DARWIN: define weak_odr ptr @unused.resolver() #[[ATTR_RESOLVER]] {119// DARWIN: ret ptr @unused.arch_ivybridge.0120// DARWIN: ret ptr @unused.default.1121 122// WINDOWS: define dso_local void @unused.default.1()123// WINDOWS: define dso_local void @unused.arch_ivybridge.0()124// WINDOWS: define weak_odr dso_local void @unused() #[[ATTR_RESOLVER]] comdat125// WINDOWS: musttail call void @unused.arch_ivybridge.0126// WINDOWS: musttail call void @unused.default.1127 128int __attribute__((target_clones("sse4.2, default"))) inherited(void);129int inherited(void) { return 0; }130// LINUX: define {{.*}}i32 @inherited.sse4.2.0()131// LINUX: define {{.*}}i32 @inherited.default.1()132// LINUX: define weak_odr ptr @inherited.resolver() #[[ATTR_RESOLVER]] comdat133// LINUX: ret ptr @inherited.sse4.2.0134// LINUX: ret ptr @inherited.default.1135 136// DARWIN: define {{.*}}i32 @inherited.sse4.2.0()137// DARWIN: define {{.*}}i32 @inherited.default.1()138// DARWIN: define weak_odr ptr @inherited.resolver() #[[ATTR_RESOLVER]] {139// DARWIN: ret ptr @inherited.sse4.2.0140// DARWIN: ret ptr @inherited.default.1141 142// WINDOWS: define dso_local i32 @inherited.sse4.2.0()143// WINDOWS: define dso_local i32 @inherited.default.1()144// WINDOWS: define weak_odr dso_local i32 @inherited() #[[ATTR_RESOLVER]] comdat145// WINDOWS: musttail call i32 @inherited.sse4.2.0146// WINDOWS: musttail call i32 @inherited.default.1147 148int test_inherited(void) {149 // LINUX: define {{.*}}i32 @test_inherited() #[[DEF:[0-9]+]]150 // DARWIN: define {{.*}}i32 @test_inherited() #[[DEF:[0-9]+]]151 // WINDOWS: define dso_local i32 @test_inherited() #[[DEF:[0-9]+]]152 return inherited();153 // LINUX: call i32 @inherited()154 // DARWIN: call i32 @inherited()155 // WINDOWS: call i32 @inherited()156}157 158inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))159foo_inline(void) { return 0; }160inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))161foo_inline2(void);162 163int bar3(void) {164 // LINUX: define {{.*}}i32 @bar3()165 // DARWIN: define {{.*}}i32 @bar3()166 // WINDOWS: define dso_local i32 @bar3()167 return foo_inline() + foo_inline2();168 // LINUX: call i32 @foo_inline()169 // LINUX: call i32 @foo_inline2()170 // DARWIN: call i32 @foo_inline()171 // DARWIN: call i32 @foo_inline2()172 // WINDOWS: call i32 @foo_inline()173 // WINDOWS: call i32 @foo_inline2()174}175 176// LINUX: define weak_odr ptr @foo_inline.resolver() #[[ATTR_RESOLVER]] comdat177// LINUX: ret ptr @foo_inline.arch_sandybridge.0178// LINUX: ret ptr @foo_inline.sse4.2.1179// LINUX: ret ptr @foo_inline.default.2180 181// DARWIN: define weak_odr ptr @foo_inline.resolver() #[[ATTR_RESOLVER]] {182// DARWIN: ret ptr @foo_inline.arch_sandybridge.0183// DARWIN: ret ptr @foo_inline.sse4.2.1184// DARWIN: ret ptr @foo_inline.default.2185 186// WINDOWS: define weak_odr dso_local i32 @foo_inline() #[[ATTR_RESOLVER]] comdat187// WINDOWS: musttail call i32 @foo_inline.arch_sandybridge.0188// WINDOWS: musttail call i32 @foo_inline.sse4.2.1189// WINDOWS: musttail call i32 @foo_inline.default.2190 191inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))192foo_inline2(void){ return 0; }193// LINUX: define weak_odr ptr @foo_inline2.resolver() #[[ATTR_RESOLVER]] comdat194// LINUX: ret ptr @foo_inline2.arch_sandybridge.0195// LINUX: ret ptr @foo_inline2.sse4.2.1196// LINUX: ret ptr @foo_inline2.default.2197 198// DARWIN: define weak_odr ptr @foo_inline2.resolver() #[[ATTR_RESOLVER]] {199// DARWIN: ret ptr @foo_inline2.arch_sandybridge.0200// DARWIN: ret ptr @foo_inline2.sse4.2.1201// DARWIN: ret ptr @foo_inline2.default.2202 203// WINDOWS: define weak_odr dso_local i32 @foo_inline2() #[[ATTR_RESOLVER]] comdat204// WINDOWS: musttail call i32 @foo_inline2.arch_sandybridge.0205// WINDOWS: musttail call i32 @foo_inline2.sse4.2.1206// WINDOWS: musttail call i32 @foo_inline2.default.2207 208 209int __attribute__((target_clones("default", "sse4.2")))210foo_unused_no_defn(void);211 212int __attribute__((target_clones("default", "sse4.2")))213foo_used_no_defn(void);214 215int test_foo_used_no_defn(void) {216 // LINUX: define {{.*}}i32 @test_foo_used_no_defn()217 // DARWIN: define {{.*}}i32 @test_foo_used_no_defn()218 // WINDOWS: define dso_local i32 @test_foo_used_no_defn()219 return foo_used_no_defn();220 // LINUX: call i32 @foo_used_no_defn()221 // DARWIN: call i32 @foo_used_no_defn()222 // WINDOWS: call i32 @foo_used_no_defn()223}224 225 226// LINUX: define weak_odr ptr @foo_used_no_defn.resolver() #[[ATTR_RESOLVER]] comdat227// LINUX: ret ptr @foo_used_no_defn.sse4.2.0228// LINUX: ret ptr @foo_used_no_defn.default.1229 230// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver() #[[ATTR_RESOLVER]] {231// DARWIN: ret ptr @foo_used_no_defn.sse4.2.0232// DARWIN: ret ptr @foo_used_no_defn.default.1233 234// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() #[[ATTR_RESOLVER]] comdat235// WINDOWS: musttail call i32 @foo_used_no_defn.sse4.2.0236// WINDOWS: musttail call i32 @foo_used_no_defn.default.1237 238__attribute__((target_clones("default", "arch=x86-64", "arch=x86-64-v2", "arch=x86-64-v3", "arch=x86-64-v4")))239int isa_level(int) { return 0; }240// LINUX: define{{.*}} i32 @isa_level.default.4(241// LINUX: define{{.*}} i32 @isa_level.arch_x86-64.0(242// LINUX: define{{.*}} i32 @isa_level.arch_x86-64-v2.1(243// LINUX: define{{.*}} i32 @isa_level.arch_x86-64-v3.2(244// LINUX: define{{.*}} i32 @isa_level.arch_x86-64-v4.3(245// LINUX: define weak_odr ptr @isa_level.resolver() #[[ATTR_RESOLVER]] comdat246// LINUX: call void @__cpu_indicator_init()247// LINUX-NEXT: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)248// LINUX-NEXT: and i32 %[[#]], 4249// LINUX: ret ptr @isa_level.arch_x86-64-v4.3250// LINUX: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)251// LINUX-NEXT: and i32 %[[#]], 2252// LINUX: ret ptr @isa_level.arch_x86-64-v3.2253// LINUX: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)254// LINUX-NEXT: and i32 %[[#]], 1255// LINUX: ret ptr @isa_level.arch_x86-64-v2.1256// LINUX: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1)257// LINUX-NEXT: and i32 %[[#]], -2147483648258// LINUX: ret ptr @isa_level.arch_x86-64.0259// LINUX: ret ptr @isa_level.default.4260 261// DARWIN: define{{.*}} i32 @isa_level.default.4(262// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64.0(263// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v2.1(264// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v3.2(265// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v4.3(266// DARWIN: define weak_odr ptr @isa_level.resolver() #[[ATTR_RESOLVER]] {267// DARWIN: call void @__cpu_indicator_init()268// DARWIN-NEXT: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)269// DARWIN-NEXT: and i32 %[[#]], 4270// DARWIN: ret ptr @isa_level.arch_x86-64-v4.3271// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)272// DARWIN-NEXT: and i32 %[[#]], 2273// DARWIN: ret ptr @isa_level.arch_x86-64-v3.2274// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)275// DARWIN-NEXT: and i32 %[[#]], 1276// DARWIN: ret ptr @isa_level.arch_x86-64-v2.1277// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1)278// DARWIN-NEXT: and i32 %[[#]], -2147483648279// DARWIN: ret ptr @isa_level.arch_x86-64.0280// DARWIN: ret ptr @isa_level.default.4281 282// Deferred emission of inline definitions.283 284// LINUX: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]285// LINUX: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]286// LINUX: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]287 288// DARWIN: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]289// DARWIN: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]290// DARWIN: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]291 292// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]293// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.default.2() #[[DEF]]294// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]295 296 297// LINUX: define linkonce i32 @foo_inline2.arch_sandybridge.0() #[[SB]]298// LINUX: define linkonce i32 @foo_inline2.default.2() #[[DEF]]299// LINUX: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]300 301// DARWIN: define linkonce i32 @foo_inline2.arch_sandybridge.0() #[[SB]]302// DARWIN: define linkonce i32 @foo_inline2.default.2() #[[DEF]]303// DARWIN: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]304 305// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.arch_sandybridge.0() #[[SB]]306// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.default.2() #[[DEF]]307// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.sse4.2.1() #[[SSE42]]308 309 310// LINUX: declare i32 @foo_used_no_defn.default.1()311// LINUX: declare i32 @foo_used_no_defn.sse4.2.0()312 313// DARWIN: declare i32 @foo_used_no_defn.default.1()314// DARWIN: declare i32 @foo_used_no_defn.sse4.2.0()315 316// WINDOWS: declare dso_local i32 @foo_used_no_defn.default.1()317// WINDOWS: declare dso_local i32 @foo_used_no_defn.sse4.2.0()318 319 320// CHECK: attributes #[[ATTR_RESOLVER]] = { disable_sanitizer_instrumentation }321// CHECK: attributes #[[SSE42]] =322// CHECK-SAME: "target-features"="+crc32,+cx8,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87"323// CHECK: attributes #[[SB]] =324// CHECK-SAME: "target-features"="+avx,+cmov,+crc32,+cx16,+cx8,+fxsr,+mmx,+pclmul,+popcnt,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"325