368 lines · c
1// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX2// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX3// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS4 5#ifdef _WIN646#define ATTR(X) __declspec(X)7#else8#define ATTR(X) __attribute__((X))9#endif // _WIN6410 11// Each version should have an IFunc and an alias.12// LINUX: @SingleVersion = weak_odr alias void (), ptr @SingleVersion.ifunc13// LINUX: @TwoVersions = weak_odr alias void (), ptr @TwoVersions.ifunc14// LINUX: @OrderDispatchUsageSpecific = weak_odr alias void (), ptr @OrderDispatchUsageSpecific.ifunc15// LINUX: @TwoVersionsSameAttr = weak_odr alias void (), ptr @TwoVersionsSameAttr.ifunc16// LINUX: @ThreeVersionsSameAttr = weak_odr alias void (), ptr @ThreeVersionsSameAttr.ifunc17// LINUX: @OrderSpecificUsageDispatch = weak_odr alias void (), ptr @OrderSpecificUsageDispatch.ifunc18// LINUX: @NoSpecifics = weak_odr alias void (), ptr @NoSpecifics.ifunc19// LINUX: @HasGeneric = weak_odr alias void (), ptr @HasGeneric.ifunc20// LINUX: @HasParams = weak_odr alias void (i32, double), ptr @HasParams.ifunc21// LINUX: @HasParamsAndReturn = weak_odr alias i32 (i32, double), ptr @HasParamsAndReturn.ifunc22// LINUX: @GenericAndPentium = weak_odr alias i32 (i32, double), ptr @GenericAndPentium.ifunc23// LINUX: @DispatchFirst = weak_odr alias i32 (), ptr @DispatchFirst.ifunc24 25// LINUX: @SingleVersion.ifunc = weak_odr ifunc void (), ptr @SingleVersion.resolver26// LINUX: @TwoVersions.ifunc = weak_odr ifunc void (), ptr @TwoVersions.resolver27// LINUX: @OrderDispatchUsageSpecific.ifunc = weak_odr ifunc void (), ptr @OrderDispatchUsageSpecific.resolver28// LINUX: @TwoVersionsSameAttr.ifunc = weak_odr ifunc void (), ptr @TwoVersionsSameAttr.resolver29// LINUX: @ThreeVersionsSameAttr.ifunc = weak_odr ifunc void (), ptr @ThreeVersionsSameAttr.resolver30// LINUX: @OrderSpecificUsageDispatch.ifunc = weak_odr ifunc void (), ptr @OrderSpecificUsageDispatch.resolver31// LINUX: @NoSpecifics.ifunc = weak_odr ifunc void (), ptr @NoSpecifics.resolver32// LINUX: @HasGeneric.ifunc = weak_odr ifunc void (), ptr @HasGeneric.resolver33// LINUX: @HasParams.ifunc = weak_odr ifunc void (i32, double), ptr @HasParams.resolver34// LINUX: @HasParamsAndReturn.ifunc = weak_odr ifunc i32 (i32, double), ptr @HasParamsAndReturn.resolver35// LINUX: @GenericAndPentium.ifunc = weak_odr ifunc i32 (i32, double), ptr @GenericAndPentium.resolver36// LINUX: @DispatchFirst.ifunc = weak_odr ifunc i32 (), ptr @DispatchFirst.resolver37 38ATTR(cpu_specific(ivybridge))39void SingleVersion(void){}40// LINUX: define{{.*}} void @SingleVersion.S() #[[S:[0-9]+]]41// WINDOWS: define dso_local void @SingleVersion.S() #[[S:[0-9]+]]42 43ATTR(cpu_dispatch(ivybridge))44void SingleVersion(void);45// LINUX: define weak_odr ptr @SingleVersion.resolver() #[[ATTR_RESOLVER:[0-9]+]]46// LINUX: call void @__cpu_indicator_init47// LINUX: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 448// LINUX: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 52531149// LINUX: %[[FEAT_CHECK:.+]] = icmp eq i32 %[[FEAT_JOIN]], 52531150// LINUX: ret ptr @SingleVersion.S51// LINUX: call void @llvm.trap52// LINUX: unreachable53 54// WINDOWS: define weak_odr dso_local void @SingleVersion() #[[ATTR_RESOLVER:[0-9]+]] comdat55// WINDOWS: call void @__cpu_indicator_init()56// WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 457// WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 52531158// WINDOWS: %[[FEAT_CHECK:.+]] = icmp eq i32 %[[FEAT_JOIN]], 52531159// WINDOWS: call void @SingleVersion.S()60// WINDOWS-NEXT: ret void61// WINDOWS: call void @llvm.trap62// WINDOWS: unreachable63 64ATTR(cpu_specific(ivybridge))65void NotCalled(void){}66// LINUX: define{{.*}} void @NotCalled.S() #[[S]]67// WINDOWS: define dso_local void @NotCalled.S() #[[S:[0-9]+]]68 69// Done before any of the implementations. Also has an undecorated forward70// declaration.71void TwoVersions(void);72 73ATTR(cpu_dispatch(ivybridge, knl))74void TwoVersions(void);75// LINUX: define weak_odr ptr @TwoVersions.resolver() #[[ATTR_RESOLVER]]76// LINUX: call void @__cpu_indicator_init77// LINUX: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 478// LINUX: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 942284779// LINUX: %[[FEAT_CHECK:.+]] = icmp eq i32 %[[FEAT_JOIN]], 942284780// LINUX: ret ptr @TwoVersions.Z81// LINUX: ret ptr @TwoVersions.S82// LINUX: call void @llvm.trap83// LINUX: unreachable84 85// WINDOWS: define weak_odr dso_local void @TwoVersions() #[[ATTR_RESOLVER]] comdat86// WINDOWS: call void @__cpu_indicator_init()87// WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 488// WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 942284789// WINDOWS: %[[FEAT_CHECK:.+]] = icmp eq i32 %[[FEAT_JOIN]], 942284790// WINDOWS: call void @TwoVersions.Z()91// WINDOWS-NEXT: ret void92// WINDOWS: call void @TwoVersions.S()93// WINDOWS-NEXT: ret void94// WINDOWS: call void @llvm.trap95// WINDOWS: unreachable96 97ATTR(cpu_specific(ivybridge))98void TwoVersions(void){}99// CHECK: define {{.*}}void @TwoVersions.S() #[[S]]100 101ATTR(cpu_specific(knl))102void TwoVersions(void){}103// CHECK: define {{.*}}void @TwoVersions.Z() #[[K:[0-9]+]]104 105ATTR(cpu_specific(ivybridge, knl))106void TwoVersionsSameAttr(void){}107// CHECK: define {{.*}}void @TwoVersionsSameAttr.S() #[[S]]108// CHECK: define {{.*}}void @TwoVersionsSameAttr.Z() #[[K]]109 110ATTR(cpu_specific(atom, ivybridge, knl))111void ThreeVersionsSameAttr(void){}112// CHECK: define {{.*}}void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]113// CHECK: define {{.*}}void @ThreeVersionsSameAttr.S() #[[S]]114// CHECK: define {{.*}}void @ThreeVersionsSameAttr.Z() #[[K]]115 116ATTR(cpu_specific(knl))117void CpuSpecificNoDispatch(void) {}118// CHECK: define {{.*}}void @CpuSpecificNoDispatch.Z() #[[K:[0-9]+]]119 120ATTR(cpu_dispatch(knl))121void OrderDispatchUsageSpecific(void);122// LINUX: define weak_odr ptr @OrderDispatchUsageSpecific.resolver() #[[ATTR_RESOLVER]]123// LINUX: call void @__cpu_indicator_init124// LINUX: ret ptr @OrderDispatchUsageSpecific.Z125// LINUX: call void @llvm.trap126// LINUX: unreachable127 128// WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() #[[ATTR_RESOLVER]] comdat129// WINDOWS: call void @__cpu_indicator_init()130// WINDOWS: call void @OrderDispatchUsageSpecific.Z()131// WINDOWS-NEXT: ret void132// WINDOWS: call void @llvm.trap133// WINDOWS: unreachable134 135// CHECK: define {{.*}}void @OrderDispatchUsageSpecific.Z()136 137ATTR(cpu_specific(knl))138void OrderSpecificUsageDispatch(void) {}139// CHECK: define {{.*}}void @OrderSpecificUsageDispatch.Z() #[[K:[0-9]+]]140 141void usages(void) {142 SingleVersion();143 // LINUX: @SingleVersion.ifunc()144 // WINDOWS: @SingleVersion()145 TwoVersions();146 // LINUX: @TwoVersions.ifunc()147 // WINDOWS: @TwoVersions()148 TwoVersionsSameAttr();149 // LINUX: @TwoVersionsSameAttr.ifunc()150 // WINDOWS: @TwoVersionsSameAttr()151 ThreeVersionsSameAttr();152 // LINUX: @ThreeVersionsSameAttr.ifunc()153 // WINDOWS: @ThreeVersionsSameAttr()154 CpuSpecificNoDispatch();155 // LINUX: @CpuSpecificNoDispatch.ifunc()156 // WINDOWS: @CpuSpecificNoDispatch()157 //158 // Adding another use of CpuSpecificNoDispatch reproduces the159 // crash in https://github.com/llvm/llvm-project/issues/115299160 CpuSpecificNoDispatch();161 // LINUX: @CpuSpecificNoDispatch.ifunc()162 // WINDOWS: @CpuSpecificNoDispatch()163 OrderDispatchUsageSpecific();164 // LINUX: @OrderDispatchUsageSpecific.ifunc()165 // WINDOWS: @OrderDispatchUsageSpecific()166 OrderSpecificUsageDispatch();167 // LINUX: @OrderSpecificUsageDispatch.ifunc()168 // WINDOWS: @OrderSpecificUsageDispatch()169}170 171// LINUX: declare void @CpuSpecificNoDispatch.ifunc()172 173// has an extra config to emit!174ATTR(cpu_dispatch(ivybridge, knl, atom))175void TwoVersionsSameAttr(void);176// LINUX: define weak_odr ptr @TwoVersionsSameAttr.resolver() #[[ATTR_RESOLVER]]177// LINUX: ret ptr @TwoVersionsSameAttr.Z178// LINUX: ret ptr @TwoVersionsSameAttr.S179// LINUX: ret ptr @TwoVersionsSameAttr.O180// LINUX: call void @llvm.trap181// LINUX: unreachable182 183// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() #[[ATTR_RESOLVER]] comdat184// WINDOWS: call void @TwoVersionsSameAttr.Z185// WINDOWS-NEXT: ret void186// WINDOWS: call void @TwoVersionsSameAttr.S187// WINDOWS-NEXT: ret void188// WINDOWS: call void @TwoVersionsSameAttr.O189// WINDOWS-NEXT: ret void190// WINDOWS: call void @llvm.trap191// WINDOWS: unreachable192 193ATTR(cpu_dispatch(atom, ivybridge, knl))194void ThreeVersionsSameAttr(void){}195// LINUX: define weak_odr ptr @ThreeVersionsSameAttr.resolver() #[[ATTR_RESOLVER]]196// LINUX: call void @__cpu_indicator_init197// LINUX: ret ptr @ThreeVersionsSameAttr.Z198// LINUX: ret ptr @ThreeVersionsSameAttr.S199// LINUX: ret ptr @ThreeVersionsSameAttr.O200// LINUX: call void @llvm.trap201// LINUX: unreachable202 203// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() #[[ATTR_RESOLVER]] comdat204// WINDOWS: call void @__cpu_indicator_init205// WINDOWS: call void @ThreeVersionsSameAttr.Z206// WINDOWS-NEXT: ret void207// WINDOWS: call void @ThreeVersionsSameAttr.S208// WINDOWS-NEXT: ret void209// WINDOWS: call void @ThreeVersionsSameAttr.O210// WINDOWS-NEXT: ret void211// WINDOWS: call void @llvm.trap212// WINDOWS: unreachable213 214ATTR(cpu_dispatch(knl))215void OrderSpecificUsageDispatch(void);216// LINUX: define weak_odr ptr @OrderSpecificUsageDispatch.resolver() #[[ATTR_RESOLVER]]217// LINUX: ret ptr @OrderSpecificUsageDispatch.Z218 219// WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() #[[ATTR_RESOLVER]] comdat220// WINDOWS: call void @__cpu_indicator_init221// WINDOWS: call void @OrderSpecificUsageDispatch.Z222// WINDOWS-NEXT: ret void223 224// No Cpu Specific options.225ATTR(cpu_dispatch(atom, ivybridge, knl))226void NoSpecifics(void);227// LINUX: define weak_odr ptr @NoSpecifics.resolver() #[[ATTR_RESOLVER]]228// LINUX: call void @__cpu_indicator_init229// LINUX: ret ptr @NoSpecifics.Z230// LINUX: ret ptr @NoSpecifics.S231// LINUX: ret ptr @NoSpecifics.O232// LINUX: call void @llvm.trap233// LINUX: unreachable234 235// WINDOWS: define weak_odr dso_local void @NoSpecifics() #[[ATTR_RESOLVER]] comdat236// WINDOWS: call void @__cpu_indicator_init237// WINDOWS: call void @NoSpecifics.Z238// WINDOWS-NEXT: ret void239// WINDOWS: call void @NoSpecifics.S240// WINDOWS-NEXT: ret void241// WINDOWS: call void @NoSpecifics.O242// WINDOWS-NEXT: ret void243// WINDOWS: call void @llvm.trap244// WINDOWS: unreachable245 246ATTR(cpu_dispatch(atom, generic, ivybridge, knl))247void HasGeneric(void);248// LINUX: define weak_odr ptr @HasGeneric.resolver() #[[ATTR_RESOLVER]]249// LINUX: call void @__cpu_indicator_init250// LINUX: ret ptr @HasGeneric.Z251// LINUX: ret ptr @HasGeneric.S252// LINUX: ret ptr @HasGeneric.O253// LINUX: ret ptr @HasGeneric.A254// LINUX-NOT: call void @llvm.trap255 256// WINDOWS: define weak_odr dso_local void @HasGeneric() #[[ATTR_RESOLVER]] comdat257// WINDOWS: call void @__cpu_indicator_init258// WINDOWS: call void @HasGeneric.Z259// WINDOWS-NEXT: ret void260// WINDOWS: call void @HasGeneric.S261// WINDOWS-NEXT: ret void262// WINDOWS: call void @HasGeneric.O263// WINDOWS-NEXT: ret void264// WINDOWS: call void @HasGeneric.A265// WINDOWS-NEXT: ret void266// WINDOWS-NOT: call void @llvm.trap267 268ATTR(cpu_dispatch(atom, generic, ivybridge, knl))269void HasParams(int i, double d);270// LINUX: define weak_odr ptr @HasParams.resolver() #[[ATTR_RESOLVER]]271// LINUX: call void @__cpu_indicator_init272// LINUX: ret ptr @HasParams.Z273// LINUX: ret ptr @HasParams.S274// LINUX: ret ptr @HasParams.O275// LINUX: ret ptr @HasParams.A276// LINUX-NOT: call void @llvm.trap277 278// WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) #[[ATTR_RESOLVER]] comdat279// WINDOWS: call void @__cpu_indicator_init280// WINDOWS: call void @HasParams.Z(i32 %0, double %1)281// WINDOWS-NEXT: ret void282// WINDOWS: call void @HasParams.S(i32 %0, double %1)283// WINDOWS-NEXT: ret void284// WINDOWS: call void @HasParams.O(i32 %0, double %1)285// WINDOWS-NEXT: ret void286// WINDOWS: call void @HasParams.A(i32 %0, double %1)287// WINDOWS-NEXT: ret void288// WINDOWS-NOT: call void @llvm.trap289 290ATTR(cpu_dispatch(atom, generic, ivybridge, knl))291int HasParamsAndReturn(int i, double d);292// LINUX: define weak_odr ptr @HasParamsAndReturn.resolver() #[[ATTR_RESOLVER]]293// LINUX: call void @__cpu_indicator_init294// LINUX: ret ptr @HasParamsAndReturn.Z295// LINUX: ret ptr @HasParamsAndReturn.S296// LINUX: ret ptr @HasParamsAndReturn.O297// LINUX: ret ptr @HasParamsAndReturn.A298// LINUX-NOT: call void @llvm.trap299 300// WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) #[[ATTR_RESOLVER]] comdat301// WINDOWS: call void @__cpu_indicator_init302// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)303// WINDOWS-NEXT: ret i32 %[[RET]]304// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.S(i32 %0, double %1)305// WINDOWS-NEXT: ret i32 %[[RET]]306// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.O(i32 %0, double %1)307// WINDOWS-NEXT: ret i32 %[[RET]]308// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.A(i32 %0, double %1)309// WINDOWS-NEXT: ret i32 %[[RET]]310// WINDOWS-NOT: call void @llvm.trap311 312ATTR(cpu_dispatch(atom, generic, pentium))313int GenericAndPentium(int i, double d);314// LINUX: define weak_odr ptr @GenericAndPentium.resolver() #[[ATTR_RESOLVER]]315// LINUX: call void @__cpu_indicator_init316// LINUX: ret ptr @GenericAndPentium.O317// LINUX: ret ptr @GenericAndPentium.B318// LINUX-NOT: ret ptr @GenericAndPentium.A319// LINUX-NOT: call void @llvm.trap320 321// WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) #[[ATTR_RESOLVER]] comdat322// WINDOWS: call void @__cpu_indicator_init323// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)324// WINDOWS-NEXT: ret i32 %[[RET]]325// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.B(i32 %0, double %1)326// WINDOWS-NEXT: ret i32 %[[RET]]327// WINDOWS-NOT: call i32 @GenericAndPentium.A328// WINDOWS-NOT: call void @llvm.trap329 330ATTR(cpu_dispatch(atom, pentium))331int DispatchFirst(void);332// LINUX: define weak_odr ptr @DispatchFirst.resolver() #[[ATTR_RESOLVER]]333// LINUX: ret ptr @DispatchFirst.O334// LINUX: ret ptr @DispatchFirst.B335 336// WINDOWS: define weak_odr dso_local i32 @DispatchFirst() #[[ATTR_RESOLVER]] comdat337// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()338// WINDOWS-NEXT: ret i32 %[[RET]]339// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()340// WINDOWS-NEXT: ret i32 %[[RET]]341 342ATTR(cpu_specific(atom))343int DispatchFirst(void) {return 0;}344// LINUX: define{{.*}} i32 @DispatchFirst.O345// LINUX: ret i32 0346 347// WINDOWS: define dso_local i32 @DispatchFirst.O()348// WINDOWS: ret i32 0349 350ATTR(cpu_specific(pentium))351int DispatchFirst(void) {return 1;}352// LINUX: define{{.*}} i32 @DispatchFirst.B353// LINUX: ret i32 1354 355// WINDOWS: define dso_local i32 @DispatchFirst.B356// WINDOWS: ret i32 1357 358ATTR(cpu_specific(knl))359void OrderDispatchUsageSpecific(void) {}360 361// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+crc32,+cx16,+cx8,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"362// CHECK-SAME: "tune-cpu"="ivybridge"363// CHECK: attributes #[[ATTR_RESOLVER]] = { disable_sanitizer_instrumentation }364// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+aes,+avx,+avx2,+avx512cd,+avx512f,+bmi,+bmi2,+cmov,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+pclmul,+popcnt,+prfchw,+rdrnd,+rdseed,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"365// CHECK-SAME: "tune-cpu"="knl"366// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+cx16,+cx8,+fxsr,+mmx,+movbe,+sahf,+sse,+sse2,+sse3,+ssse3,+x87"367// CHECK-SAME: "tune-cpu"="atom"368