]> granicus.if.org Git - clang/commitdiff
CPU-Dispatch-- Fix conflict between 'generic' and 'pentium'
authorErich Keane <erich.keane@intel.com>
Thu, 1 Nov 2018 12:50:37 +0000 (12:50 +0000)
committerErich Keane <erich.keane@intel.com>
Thu, 1 Nov 2018 12:50:37 +0000 (12:50 +0000)
When a dispatch function was being emitted that had both a generic and a
pentium configuration listed, we would assert.  This is because neither
configuration has any 'features' associated with it so they were both
considered the 'default' version.  'pentium' lacks any features because
we implement it in terms of __builtin_cpu_supports (instead of Intel
proprietary checks), which is unable to decern between the two.

The fix for this is to omit the 'generic' version from the dispatcher if
both are present. This permits existing code to compile, and still will
choose the 'best' version available (since 'pentium' is technically
better than 'generic').

Change-Id: I4b69f3e0344e74cbdbb04497845d5895dd05fda0

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345826 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/attr-cpuspecific.c

index 9c4b097c5d62e0917e1c335a6e2ca78b7791deb3..227b88333425fa0ac0394ba5d16a9f58cbe131ee 100644 (file)
@@ -2583,6 +2583,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);
 }
index a0a7b9770f06671870cb073f67fa2e1ca26b6f85..e1562e52e002c86c8cae9a828dcf12c2fbf8c283 100644 (file)
@@ -205,6 +205,24 @@ int HasParamsAndReturn(int i, double d);
 // WINDOWS-NEXT: ret i32 %[[RET]]
 // WINDOWS-NOT: call void @llvm.trap
 
+ATTR(cpu_dispatch(atom, generic, pentium))
+int GenericAndPentium(int i, double d);
+// LINUX: define i32 (i32, double)* @GenericAndPentium.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret i32 (i32, double)* @GenericAndPentium.O
+// LINUX: ret i32 (i32, double)* @GenericAndPentium.B
+// LINUX-NOT: ret i32 (i32, double)* @GenericAndPentium.A
+// LINUX-NOT: call void @llvm.trap
+
+// WINDOWS: define dso_local i32 @GenericAndPentium(i32, double)
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.B(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS-NOT: call i32 @GenericAndPentium.A
+// WINDOWS-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"