summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp16
-rw-r--r--clang/test/CodeGen/attr-cpuspecific.c9
2 files changed, 25 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 2654247b959..448a8b298e8 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2505,6 +2505,22 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
});
+
+ // If the list contains multiple 'default' versions, such as when it contains
+ // 'pentium' and 'generic', don't emit the call to the generic one (since we
+ // always run on at least a 'pentium'). We do this by deleting the 'least
+ // advanced' (read, lowest mangling letter).
+ while (Options.size() > 1 &&
+ CodeGenFunction::GetX86CpuSupportsMask(
+ (Options.end() - 2)->Conditions.Features) == 0) {
+ StringRef LHSName = (Options.end() - 2)->Function->getName();
+ StringRef RHSName = (Options.end() - 1)->Function->getName();
+ if (LHSName.compare(RHSName) < 0)
+ Options.erase(Options.end() - 2);
+ else
+ Options.erase(Options.end() - 1);
+ }
+
CodeGenFunction CGF(*this);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
diff --git a/clang/test/CodeGen/attr-cpuspecific.c b/clang/test/CodeGen/attr-cpuspecific.c
index 1b98b5dc967..6005456f0b2 100644
--- a/clang/test/CodeGen/attr-cpuspecific.c
+++ b/clang/test/CodeGen/attr-cpuspecific.c
@@ -96,6 +96,15 @@ void HasGeneric(void);
// CHECK: ret void ()* @HasGeneric.A
// CHECK-NOT: call void @llvm.trap
+__attribute__((cpu_dispatch(atom, generic, pentium)))
+int GenericAndPentium(int i, double d);
+// CHECK: define i32 (i32, double)* @GenericAndPentium.resolver()
+// CHECK: call void @__cpu_indicator_init
+// CHECK: ret i32 (i32, double)* @GenericAndPentium.O
+// CHECK: ret i32 (i32, double)* @GenericAndPentium.B
+// CHECK-NOT: ret i32 (i32, double)* @GenericAndPentium.A
+// CHECK-NOT: call void @llvm.trap
+
// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"
OpenPOWER on IntegriCloud