GBuella created this revision. GBuella added reviewers: craig.topper, echristo, dblaikie. Herald added a subscriber: cfe-commits.
When requirement imposed by __target__ attributes on functions are not satisfied, prefer printing those requirements, which are explicitly mentioned in the attributes. This makes such messages more useful, e.g. printing avx512f instead of avx2 in the following scenario: $ cat foo.c static inline void __attribute__((__always_inline__, __target__("avx512f"))) x(void) { } int main(void) { x(); } $ clang foo.c foo.c:7:2: error: always_inline function 'x' requires target feature 'avx2', but would be inlined into function 'main' that is compiled without support for 'avx2' x(); ^ 1 error generated. bugzilla: https://bugs.llvm.org/show_bug.cgi?id=37338 Repository: rC Clang https://reviews.llvm.org/D46541 Files: lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/target-features-error-2.c test/CodeGen/target-features-error.c
Index: test/CodeGen/target-features-error.c =================================================================== --- test/CodeGen/target-features-error.c +++ test/CodeGen/target-features-error.c @@ -3,6 +3,5 @@ return a + 4; } int bar() { - return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'sse4.2', but would be inlined into function 'bar' that is compiled without support for 'sse4.2'}} + return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'avx', but would be inlined into function 'bar' that is compiled without support for 'avx'}} } - Index: test/CodeGen/target-features-error-2.c =================================================================== --- test/CodeGen/target-features-error-2.c +++ test/CodeGen/target-features-error-2.c @@ -3,13 +3,14 @@ // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_2 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_3 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_4 +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX512f #define __MM_MALLOC_H #include <x86intrin.h> #if NEED_SSE42 int baz(__m256i a) { - return _mm256_extract_epi32(a, 3); // expected-error {{always_inline function '_mm256_extract_epi32' requires target feature 'sse4.2', but would be inlined into function 'baz' that is compiled without support for 'sse4.2'}} + return _mm256_extract_epi32(a, 3); // expected-error {{always_inline function '_mm256_extract_epi32' requires target feature 'avx', but would be inlined into function 'baz' that is compiled without support for 'avx'}} } #endif @@ -36,3 +37,9 @@ return _mm_cmp_sd(a, b, 0); // expected-error {{'__builtin_ia32_cmpsd' needs target feature avx}} } #endif + +#if NEED_AVX512f +unsigned short need_avx512f(unsigned short a, unsigned short b) { + return __builtin_ia32_korhi(a, b); // expected-error {{'__builtin_ia32_korhi' needs target feature avx512f}} +} +#endif Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1082,6 +1082,8 @@ /// It's up to you to ensure that this is safe. void AddDefaultFnAttrs(llvm::Function &F); + TargetAttr::ParsedTargetAttr getFunctionTargetAttrs(const FunctionDecl *FD); + // Fills in the supplied string map with the set of target features for the // passed in function. void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -4995,11 +4995,8 @@ } } -// Fills in the supplied string map with the set of target features for the -// passed in function. -void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, - const FunctionDecl *FD) { - StringRef TargetCPU = Target.getTargetOpts().CPU; +TargetAttr::ParsedTargetAttr CodeGenModule::getFunctionTargetAttrs(const FunctionDecl *FD) +{ if (const auto *TD = FD->getAttr<TargetAttr>()) { // If we have a TargetAttr build up the feature map based on that. TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); @@ -5011,7 +5008,20 @@ StringRef{Feat}.substr(1)); }), ParsedAttr.Features.end()); + return ParsedAttr; + } else { + return TargetAttr::ParsedTargetAttr(); + } +} + +// Fills in the supplied string map with the set of target features for the +// passed in function. +void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, + const FunctionDecl *FD) { + StringRef TargetCPU = Target.getTargetOpts().CPU; + TargetAttr::ParsedTargetAttr ParsedAttr = getFunctionTargetAttrs(FD); + if (ParsedAttr.Features.size() != 0) { // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. ParsedAttr.Features.insert(ParsedAttr.Features.begin(), Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -2267,8 +2267,24 @@ CGF->InsertHelper(I, Name, BB, InsertPt); } +static bool hasRequiredFeature(StringRef Feature, + llvm::StringMap<bool>& CallerFeatureMap, + std::string &Missing) { + SmallVector<StringRef, 1> OrFeatures; + Feature.split(OrFeatures, '|'); + return std::any_of(OrFeatures.begin(), OrFeatures.end(), + [&](StringRef Feature) { + if (!CallerFeatureMap.lookup(Feature)) { + Missing = Feature.str(); + return false; + } + return true; + }); +} + static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures, CodeGenModule &CGM, const FunctionDecl *FD, + const FunctionDecl *TargetDecl, std::string &FirstMissing) { // If there aren't any required features listed then go ahead and return. if (ReqFeatures.empty()) @@ -2279,20 +2295,23 @@ llvm::StringMap<bool> CallerFeatureMap; CGM.getFunctionFeatureMap(CallerFeatureMap, FD); + TargetAttr::ParsedTargetAttr ParsedAttr = CGM.getFunctionTargetAttrs(TargetDecl); + for (auto& Feature : ReqFeatures) { + if (std::any_of(ParsedAttr.Features.begin(), ParsedAttr.Features.end(), + [&](StringRef ExplicitFeature) { + if (ExplicitFeature[0] != '+') + return false; + return Feature == ExplicitFeature.substr(1); + })) + if (!hasRequiredFeature(Feature, CallerFeatureMap, FirstMissing)) + return false; + } + // If we have at least one of the features in the feature list return // true, otherwise return false. return std::all_of( ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) { - SmallVector<StringRef, 1> OrFeatures; - Feature.split(OrFeatures, '|'); - return std::any_of(OrFeatures.begin(), OrFeatures.end(), - [&](StringRef Feature) { - if (!CallerFeatureMap.lookup(Feature)) { - FirstMissing = Feature.str(); - return false; - } - return true; - }); + return hasRequiredFeature(Feature, CallerFeatureMap, FirstMissing); }); } @@ -2323,7 +2342,7 @@ if (!FeatureList || StringRef(FeatureList) == "") return; StringRef(FeatureList).split(ReqFeatures, ','); - if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) + if (!hasRequiredFeatures(ReqFeatures, CGM, FD, TargetDecl, MissingFeature)) CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature) << TargetDecl->getDeclName() << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); @@ -2338,7 +2357,7 @@ if (F.getValue()) ReqFeatures.push_back(F.getKey()); } - if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) + if (!hasRequiredFeatures(ReqFeatures, CGM, FD, TargetDecl, MissingFeature)) CGM.getDiags().Report(E->getLocStart(), diag::err_function_needs_feature) << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits