]> granicus.if.org Git - clang/commitdiff
[X86] When checking the bits in cpu_features for function multiversioning dispatcher...
authorCraig Topper <craig.topper@intel.com>
Sat, 20 Oct 2018 01:30:00 +0000 (01:30 +0000)
committerCraig Topper <craig.topper@intel.com>
Sat, 20 Oct 2018 01:30:00 +0000 (01:30 +0000)
Summary:
The multiversioning code repurposed the code from __builtin_cpu_supports for checking if a single feature is enabled. That code essentially performed (_cpu_features & (1 << C)) != 0. But with the multiversioning path, the mask is no longer guaranteed to be a power of 2. So we return true anytime any one of the bits in the mask is set not just all of the bits.

The correct check is (_cpu_features & mask) == mask

Reviewers: erichkeane, echristo

Reviewed By: echristo

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D53460

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

lib/CodeGen/CGBuiltin.cpp
test/CodeGen/attr-target-mv.c
test/CodeGen/builtin-cpu-supports.c

index 7d0ec81ea223d158cb47e2b9f580feff3cc75e68..25c39c331095eba6056321d868b1916180225603 100644 (file)
@@ -9129,9 +9129,9 @@ llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint32_t FeaturesMask) {
       Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
 
   // Check the value of the bit corresponding to the feature requested.
-  Value *Bitset = Builder.CreateAnd(
-      Features, llvm::ConstantInt::get(Int32Ty, FeaturesMask));
-  return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
+  Value *Mask = Builder.getInt32(FeaturesMask);
+  Value *Bitset = Builder.CreateAnd(Features, Mask);
+  return Builder.CreateICmpEQ(Bitset, Mask);
 }
 
 Value *CodeGenFunction::EmitX86CpuInit() {
index 0085a154ced176de59f52c51e1677ac29c233537..48e1558356977a1c65d8533442cd5b62ce5af63a 100644 (file)
@@ -70,6 +70,22 @@ void bar4() {
 // CHECK: ret void ()* @foo_decls.sse4.2
 // CHECK: ret void ()* @foo_decls
 
+// CHECK: define void @bar4()
+// CHECK: call void @foo_multi.ifunc()
+
+// CHECK: define void ()* @foo_multi.resolver() comdat
+// CHECK: and i32 %{{.*}}, 4352
+// CHECK: icmp eq i32 %{{.*}}, 4352
+// CHECK: ret void ()* @foo_multi.fma4_sse4.2
+// CHECK: icmp eq i32 %{{.*}}, 12
+// CHECK: and i32 %{{.*}}, 4352
+// CHECK: icmp eq i32 %{{.*}}, 4352
+// CHECK: ret void ()* @foo_multi.arch_ivybridge_fma4_sse4.2
+// CHECK: and i32 %{{.*}}, 768
+// CHECK: icmp eq i32 %{{.*}}, 768
+// CHECK: ret void ()* @foo_multi.avx_sse4.2
+// CHECK: ret void ()* @foo_multi
+
 // CHECK: declare i32 @foo.arch_sandybridge()
 
 // CHECK: define available_externally i32 @foo_inline.sse4.2()
@@ -88,4 +104,3 @@ void bar4() {
 // CHECK: define available_externally void @foo_multi.avx_sse4.2()
 // CHECK: define available_externally void @foo_multi.fma4_sse4.2()
 // CHECK: define available_externally void @foo_multi.arch_ivybridge_fma4_sse4.2()
-
index b70f4aca9d4326a5d6b6b8769dbcbb523b7a64bd..4964b98e6f52bce88182713d41040c10917abc11 100644 (file)
@@ -14,7 +14,7 @@ int main() {
 
   // CHECK: [[LOAD:%[^ ]+]] = load i32, i32* getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, { i32, i32, i32, [1 x i32] }* @__cpu_model, i32 0, i32 3, i32 0)
   // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256
-  // CHECK: = icmp ne i32 [[AND]], 0
+  // CHECK: = icmp eq i32 [[AND]], 256
 
   return 0;
 }