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"); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits