r344832 - [X86] Add support for more than 32 features for __builtin_cpu_is

Craig Topper via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 19 20:51:52 PDT 2018


Author: ctopper
Date: Fri Oct 19 20:51:52 2018
New Revision: 344832

URL: http://llvm.org/viewvc/llvm-project?rev=344832&view=rev
Log:
[X86] Add support for more than 32 features for __builtin_cpu_is

libgcc supports more than 32 features by adding a new 32-bit variable __cpu_features2.

This adds the clang support for checking these feature bits.

Patches for compiler-rt and llvm to support this are coming as well.

Probably still need an additional patch for target multiversioning in clang.

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

Modified:
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGen/builtin-cpu-supports.c
    cfe/trunk/test/CodeGen/target-builtin-noerror.c

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=344832&r1=344831&r2=344832&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Oct 19 20:51:52 2018
@@ -9088,17 +9088,17 @@ Value *CodeGenFunction::EmitX86CpuSuppor
   return EmitX86CpuSupports(FeatureStr);
 }
 
-uint32_t
+uint64_t
 CodeGenFunction::GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
   // Processor features and mapping to processor feature value.
-  uint32_t FeaturesMask = 0;
+  uint64_t FeaturesMask = 0;
   for (const StringRef &FeatureStr : FeatureStrs) {
     unsigned Feature =
         StringSwitch<unsigned>(FeatureStr)
 #define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, VAL)
 #include "llvm/Support/X86TargetParser.def"
         ;
-    FeaturesMask |= (1U << Feature);
+    FeaturesMask |= (1ULL << Feature);
   }
   return FeaturesMask;
 }
@@ -9107,31 +9107,54 @@ Value *CodeGenFunction::EmitX86CpuSuppor
   return EmitX86CpuSupports(GetX86CpuSupportsMask(FeatureStrs));
 }
 
-llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint32_t FeaturesMask) {
-  // Matching the struct layout from the compiler-rt/libgcc structure that is
-  // filled in:
-  // unsigned int __cpu_vendor;
-  // unsigned int __cpu_type;
-  // unsigned int __cpu_subtype;
-  // unsigned int __cpu_features[1];
-  llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
-                                          llvm::ArrayType::get(Int32Ty, 1));
-
-  // Grab the global __cpu_model.
-  llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
-
-  // Grab the first (0th) element from the field __cpu_features off of the
-  // global in the struct STy.
-  Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 3),
-                   ConstantInt::get(Int32Ty, 0)};
-  Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
-  Value *Features =
-      Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
-
-  // Check the value of the bit corresponding to the feature requested.
-  Value *Mask = Builder.getInt32(FeaturesMask);
-  Value *Bitset = Builder.CreateAnd(Features, Mask);
-  return Builder.CreateICmpEQ(Bitset, Mask);
+llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint64_t FeaturesMask) {
+  uint32_t Features1 = Lo_32(FeaturesMask);
+  uint32_t Features2 = Hi_32(FeaturesMask);
+
+  Value *Result = Builder.getTrue();
+
+  if (Features1 != 0) {
+    // Matching the struct layout from the compiler-rt/libgcc structure that is
+    // filled in:
+    // unsigned int __cpu_vendor;
+    // unsigned int __cpu_type;
+    // unsigned int __cpu_subtype;
+    // unsigned int __cpu_features[1];
+    llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
+                                            llvm::ArrayType::get(Int32Ty, 1));
+
+    // Grab the global __cpu_model.
+    llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+
+    // Grab the first (0th) element from the field __cpu_features off of the
+    // global in the struct STy.
+    Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3),
+                     Builder.getInt32(0)};
+    Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
+    Value *Features =
+        Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
+
+    // Check the value of the bit corresponding to the feature requested.
+    Value *Mask = Builder.getInt32(Features1);
+    Value *Bitset = Builder.CreateAnd(Features, Mask);
+    Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
+    Result = Builder.CreateAnd(Result, Cmp);
+  }
+
+  if (Features2 != 0) {
+    llvm::Constant *CpuFeatures2 = CGM.CreateRuntimeVariable(Int32Ty,
+                                                             "__cpu_features2");
+    Value *Features =
+        Builder.CreateAlignedLoad(CpuFeatures2, CharUnits::fromQuantity(4));
+
+    // Check the value of the bit corresponding to the feature requested.
+    Value *Mask = Builder.getInt32(Features2);
+    Value *Bitset = Builder.CreateAnd(Features, Mask);
+    Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
+    Result = Builder.CreateAnd(Result, Cmp);
+  }
+
+  return Result;
 }
 
 Value *CodeGenFunction::EmitX86CpuInit() {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=344832&r1=344831&r2=344832&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Oct 19 20:51:52 2018
@@ -4308,7 +4308,7 @@ public:
   void EmitCPUDispatchMultiVersionResolver(
       llvm::Function *Resolver,
       ArrayRef<CPUDispatchMultiVersionResolverOption> Options);
-  static uint32_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
+  static uint64_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
 
 private:
   QualType getVarArgType(const Expr *Arg);
@@ -4325,7 +4325,7 @@ private:
   llvm::Value *EmitX86CpuIs(StringRef CPUStr);
   llvm::Value *EmitX86CpuSupports(const CallExpr *E);
   llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
-  llvm::Value *EmitX86CpuSupports(uint32_t Mask);
+  llvm::Value *EmitX86CpuSupports(uint64_t Mask);
   llvm::Value *EmitX86CpuInit();
   llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
 };

Modified: cfe/trunk/test/CodeGen/builtin-cpu-supports.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin-cpu-supports.c?rev=344832&r1=344831&r2=344832&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtin-cpu-supports.c (original)
+++ cfe/trunk/test/CodeGen/builtin-cpu-supports.c Fri Oct 19 20:51:52 2018
@@ -16,5 +16,12 @@ int main() {
   // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256
   // CHECK: = icmp eq i32 [[AND]], 256
 
+  if (__builtin_cpu_supports("gfni"))
+    a("gfni");
+
+  // CHECK: [[LOAD:%[^ ]+]] = load i32, i32* @__cpu_features2
+  // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 1
+  // CHECK: = icmp eq i32 [[AND]], 1
+
   return 0;
 }

Modified: cfe/trunk/test/CodeGen/target-builtin-noerror.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/target-builtin-noerror.c?rev=344832&r1=344831&r2=344832&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/target-builtin-noerror.c (original)
+++ cfe/trunk/test/CodeGen/target-builtin-noerror.c Fri Oct 19 20:51:52 2018
@@ -75,6 +75,11 @@ void verifyfeaturestrings() {
   (void)__builtin_cpu_supports("avx5124vnniw");
   (void)__builtin_cpu_supports("avx5124fmaps");
   (void)__builtin_cpu_supports("avx512vpopcntdq");
+  (void)__builtin_cpu_supports("avx512vbmi2");
+  (void)__builtin_cpu_supports("gfni");
+  (void)__builtin_cpu_supports("vpclmulqdq");
+  (void)__builtin_cpu_supports("avx512vnni");
+  (void)__builtin_cpu_supports("avx512bitalg");
 }
 
 void verifycpustrings() {
@@ -95,7 +100,11 @@ void verifycpustrings() {
   (void)__builtin_cpu_is("cannonlake");
   (void)__builtin_cpu_is("core2");
   (void)__builtin_cpu_is("corei7");
+  (void)__builtin_cpu_is("goldmont");
+  (void)__builtin_cpu_is("goldmont-plus");
   (void)__builtin_cpu_is("haswell");
+  (void)__builtin_cpu_is("icelake-client");
+  (void)__builtin_cpu_is("icelake-server");
   (void)__builtin_cpu_is("intel");
   (void)__builtin_cpu_is("istanbul");
   (void)__builtin_cpu_is("ivybridge");
@@ -108,6 +117,7 @@ void verifycpustrings() {
   (void)__builtin_cpu_is("skylake");
   (void)__builtin_cpu_is("skylake-avx512");
   (void)__builtin_cpu_is("slm");
+  (void)__builtin_cpu_is("tremont");
   (void)__builtin_cpu_is("westmere");
   (void)__builtin_cpu_is("znver1");
 }




More information about the cfe-commits mailing list