Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp @@ -9088,17 +9088,17 @@ return EmitX86CpuSupports(FeatureStr); } -uint32_t +uint64_t CodeGenFunction::GetX86CpuSupportsMask(ArrayRef 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(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 @@ 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"); +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); + } - // 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); + return Result; } Value *CodeGenFunction::EmitX86CpuInit() { Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -4308,7 +4308,7 @@ void EmitCPUDispatchMultiVersionResolver( llvm::Function *Resolver, ArrayRef Options); - static uint32_t GetX86CpuSupportsMask(ArrayRef FeatureStrs); + static uint64_t GetX86CpuSupportsMask(ArrayRef FeatureStrs); private: QualType getVarArgType(const Expr *Arg); @@ -4325,7 +4325,7 @@ llvm::Value *EmitX86CpuIs(StringRef CPUStr); llvm::Value *EmitX86CpuSupports(const CallExpr *E); llvm::Value *EmitX86CpuSupports(ArrayRef FeatureStrs); - llvm::Value *EmitX86CpuSupports(uint32_t Mask); + llvm::Value *EmitX86CpuSupports(uint64_t Mask); llvm::Value *EmitX86CpuInit(); llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO); }; Index: cfe/trunk/test/CodeGen/builtin-cpu-supports.c =================================================================== --- cfe/trunk/test/CodeGen/builtin-cpu-supports.c +++ cfe/trunk/test/CodeGen/builtin-cpu-supports.c @@ -16,5 +16,12 @@ // 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; } Index: cfe/trunk/test/CodeGen/target-builtin-noerror.c =================================================================== --- cfe/trunk/test/CodeGen/target-builtin-noerror.c +++ cfe/trunk/test/CodeGen/target-builtin-noerror.c @@ -75,6 +75,11 @@ (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)__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)__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"); }