[clang] [CIR][CodeGen] Implement target-features checking(CodeGenUtils!) (PR #223056)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 13:52:18 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
This DOES move checking functions out of CodeGen and into CodeGenUtils so both can use it.
This is a diagnostic for builtins/etc that is built in to classic codegen. We have to implement it, because otherwise autoconfig thinks that we support AVX without a flag, and thus causes us to fail builds later on that now expect __AVX__/etc to be defined without enabling them.
---
Patch is 44.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223056.diff
22 Files Affected:
- (modified) clang/include/clang/CodeGenUtils/CodeGenUtils.h (+23)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+22)
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+17)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+7)
- (modified) clang/lib/CIR/FrontendAction/CIRGenAction.cpp (+4)
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+6-108)
- (modified) clang/lib/CodeGenUtils/CodeGenUtils.cpp (+118)
- (added) clang/test/CIR/CodeGen/avx512-error.c (+23)
- (added) clang/test/CIR/CodeGen/target-builtin-error-2.c (+13)
- (added) clang/test/CIR/CodeGen/target-builtin-error-3.c (+62)
- (added) clang/test/CIR/CodeGen/target-builtin-error.c (+8)
- (added) clang/test/CIR/CodeGen/target-builtin-noerror.c (+215)
- (added) clang/test/CIR/CodeGen/target-features-error-2.c (+50)
- (added) clang/test/CIR/CodeGen/target-features-error-3.c (+12)
- (added) clang/test/CIR/CodeGen/target-features-error-4.c (+12)
- (added) clang/test/CIR/CodeGen/target-features-error-5.c (+12)
- (added) clang/test/CIR/CodeGen/target-features-error.c (+7)
- (added) clang/test/CIR/CodeGen/target-features-no-error-2.c (+12)
- (added) clang/test/CIR/CodeGen/target-features-no-error.c (+9)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512vlvbmi2-builtins.c (+4-4)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/sqrt-builtins.c (+3-3)
- (modified) clang/test/CIR/CodeGenBuiltins/builtin-undef-rvalue.cpp (-6)
``````````diff
diff --git a/clang/include/clang/CodeGenUtils/CodeGenUtils.h b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
index 2ecae74d1f606..b24f457f9537c 100644
--- a/clang/include/clang/CodeGenUtils/CodeGenUtils.h
+++ b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
@@ -10,6 +10,14 @@
#define LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class CallExpr;
+class DiagnosticsEngine;
+class FunctionDecl;
+class LangOptions;
+} // namespace clang
namespace clang::CodeGenUtils {
/// Check whether we need to initialize any vtable pointers before calling this
@@ -37,6 +45,21 @@ bool hasUnwindExceptions(const LangOptions &LangOpts);
bool isAAPCS(const TargetInfo &TargetInfo);
bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit);
+
+/// Check that a call to a target-specific builtin has the required target
+/// features enabled in the caller, emitting an error diagnostic if not.
+/// \p caller is the FunctionDecl of the enclosing function (may be null).
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const CallExpr *E,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl);
+
+/// Overload taking a raw source location instead of a CallExpr.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, SourceLocation Loc,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl);
+
} // namespace clang::CodeGenUtils
#endif // LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index c7ce147b68d61..e039f85851337 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -26,6 +26,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/ErrorHandling.h"
@@ -1236,6 +1237,20 @@ static cir::FuncType getIntrinsicType(CIRGenFunction &cgf,
return cir::FuncType::get(context, argTypes, resultTy, isVarArg);
}
+void CIRGenFunction::checkTargetFeatures(const CallExpr *e,
+ const FunctionDecl *targetDecl) {
+ const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
+ CodeGenUtils::checkTargetFeatures(getContext(), cgm.getDiags(), getLangOpts(),
+ e, fd, targetDecl);
+}
+
+void CIRGenFunction::checkTargetFeatures(SourceLocation loc,
+ const FunctionDecl *targetDecl) {
+ const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
+ CodeGenUtils::checkTargetFeatures(getContext(), cgm.getDiags(), getLangOpts(),
+ loc, fd, targetDecl);
+}
+
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
const CallExpr *e,
ReturnValueSlot returnValue) {
@@ -2998,6 +3013,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return emitLibraryCall(*this, fd, e,
emitScalarExpr(e->getCallee()).getDefiningOp());
+ // Check that a call to a target specific builtin has the correct target
+ // features.
+ // This is down here to avoid non-target specific builtins, however, if
+ // generic builtins start to require generic target features then we
+ // can move this up to the beginning of the function.
+ checkTargetFeatures(e, fd);
+
// See if we have a target specific intrinsic.
std::string name = getContext().BuiltinInfo.getName(builtinID);
Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 2caf22d3beb88..b9c3472190553 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1218,6 +1218,23 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
SmallVector<mlir::Value, 16> cirCallArgs(args.size());
const Decl *targetDecl = callee.getAbstractInfo().getCalleeDecl().getDecl();
+
+ if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(targetDecl)) {
+ // We can only guarantee that a function is called from the correct
+ // context/function based on the appropriate target attributes,
+ // so only check in the case where we have both always_inline and target
+ // since otherwise we could be making a conditional call after a check for
+ // the proper cpu features (and it won't cause code generation issues due to
+ // function based code generation).
+ if ((targetDecl->hasAttr<AlwaysInlineAttr>() &&
+ (targetDecl->hasAttr<TargetAttr>() ||
+ (curFuncDecl && curFuncDecl->hasAttr<TargetAttr>()))) ||
+ (curFuncDecl && curFuncDecl->hasAttr<FlattenAttr>() &&
+ (curFuncDecl->hasAttr<TargetAttr>() ||
+ targetDecl->hasAttr<TargetAttr>())))
+ checkTargetFeatures(clangLoc.getBegin(), fd);
+ }
+
const FunctionDecl *callerDecl = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
const FunctionDecl *calleeDecl = dyn_cast_or_null<FunctionDecl>(targetDecl);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 86a8736980773..dc57fd826337b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -2346,6 +2346,13 @@ class CIRGenFunction : public CIRGenTypeCache {
emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e,
ReturnValueSlot &returnValue);
+ /// Emit a diagnostic if the target features required by \p targetDecl are
+ /// not available in the calling function. Mirrors CodeGenFunction behavior.
+ void checkTargetFeatures(const clang::CallExpr *e,
+ const clang::FunctionDecl *targetDecl);
+ void checkTargetFeatures(clang::SourceLocation loc,
+ const clang::FunctionDecl *targetDecl);
+
/// Given a value and its clang type, returns the value casted to its memory
/// representation.
/// Note: CIR defers most of the special casting to the final lowering passes
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 66c2f9b7a8937..57c40121fb39b 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -195,6 +195,10 @@ class CIRGenConsumer : public clang::ASTConsumer {
MlirModule->print(out);
}
+ // If errors occurred during codegen, stop before running the backend.
+ if (CI.getDiagnostics().hasErrorOccurred())
+ return;
+
std::unique_ptr<llvm::Module> LLVMModule = lowerFromCIRToLLVMIR(
MlirModule, LLVMCtx, C.getLangOpts().OpenMP, mlirSaveTempsOutFile,
&CI.getVirtualFileSystem());
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 7e7f9a072f765..fe39235fcd4f6 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -36,6 +36,7 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
@@ -2884,121 +2885,18 @@ void CGBuilderInserter::InsertHelper(
// called function.
void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
const FunctionDecl *TargetDecl) {
- // SemaChecking cannot handle below x86 builtins because they have different
- // parameter ranges with different TargetAttribute of caller.
- if (CGM.getContext().getTargetInfo().getTriple().isX86()) {
- unsigned BuiltinID = TargetDecl->getBuiltinID();
- if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
- BuiltinID == X86::BI__builtin_ia32_cmpss ||
- BuiltinID == X86::BI__builtin_ia32_cmppd ||
- BuiltinID == X86::BI__builtin_ia32_cmpsd) {
- const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
- llvm::StringMap<bool> TargetFetureMap;
- CGM.getContext().getFunctionFeatureMap(TargetFetureMap, FD);
- llvm::APSInt Result =
- *(E->getArg(2)->getIntegerConstantExpr(CGM.getContext()));
- if (Result.getSExtValue() > 7 && !TargetFetureMap.lookup("avx"))
- CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
- << TargetDecl->getDeclName() << "avx";
- }
- }
- return checkTargetFeatures(E->getBeginLoc(), TargetDecl);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
+ CodeGenUtils::checkTargetFeatures(CGM.getContext(), CGM.getDiags(),
+ getLangOpts(), E, FD, TargetDecl);
}
// Emits an error if we don't have a valid set of target features for the
// called function.
void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
const FunctionDecl *TargetDecl) {
- // Early exit if this is an indirect call.
- if (!TargetDecl)
- return;
-
- // Get the current enclosing function if it exists. If it doesn't
- // we can't check the target features anyhow.
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
- if (!FD)
- return;
-
- bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
- bool IsFlatten = FD && FD->hasAttr<FlattenAttr>();
-
- // Grab the required features for the call. For a builtin this is listed in
- // the td file with the default cpu, for an always_inline function this is any
- // listed cpu and any listed features.
- unsigned BuiltinID = TargetDecl->getBuiltinID();
- std::string MissingFeature;
- llvm::StringMap<bool> CallerFeatureMap;
- CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
- // When compiling in HipStdPar mode we have to be conservative in rejecting
- // target specific features in the FE, and defer the possible error to the
- // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
- // referenced by an accelerator executable function, we emit an error.
- bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
- if (BuiltinID) {
- StringRef FeatureList(CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
- if (!Builtin::evaluateRequiredTargetFeatures(
- FeatureList, CallerFeatureMap) && !IsHipStdPar) {
- CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
- << TargetDecl->getDeclName()
- << FeatureList;
- }
- } else if (!TargetDecl->isMultiVersion() &&
- TargetDecl->hasAttr<TargetAttr>()) {
- // Get the required features for the callee.
-
- const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
- ParsedTargetAttr ParsedAttr =
- CGM.getContext().filterFunctionTargetAttrs(TD);
-
- SmallVector<StringRef, 1> ReqFeatures;
- llvm::StringMap<bool> CalleeFeatureMap;
- CGM.getContext().getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
- for (const auto &F : ParsedAttr.Features) {
- if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
- ReqFeatures.push_back(StringRef(F).substr(1));
- }
-
- for (const auto &F : CalleeFeatureMap) {
- // Only positive features are "required".
- if (F.getValue())
- ReqFeatures.push_back(F.getKey());
- }
- if (!llvm::all_of(ReqFeatures,
- [&](StringRef Feature) {
- if (!CallerFeatureMap.lookup(Feature)) {
- MissingFeature = Feature.str();
- return false;
- }
- return true;
- }) &&
- !IsHipStdPar) {
- if (IsAlwaysInline)
- CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
- << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
- else if (IsFlatten)
- CGM.getDiags().Report(Loc, diag::err_flatten_function_needs_feature)
- << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
- }
-
- } else if (!FD->isMultiVersion() && FD->hasAttr<TargetAttr>()) {
- llvm::StringMap<bool> CalleeFeatureMap;
- CGM.getContext().getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
- for (const auto &F : CalleeFeatureMap) {
- if (F.getValue() &&
- (!CallerFeatureMap.lookup(F.getKey()) ||
- !CallerFeatureMap.find(F.getKey())->getValue()) &&
- !IsHipStdPar) {
- if (IsAlwaysInline)
- CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
- << FD->getDeclName() << TargetDecl->getDeclName() << F.getKey();
- else if (IsFlatten)
- CGM.getDiags().Report(Loc, diag::err_flatten_function_needs_feature)
- << FD->getDeclName() << TargetDecl->getDeclName() << F.getKey();
- }
- }
- }
+ CodeGenUtils::checkTargetFeatures(CGM.getContext(), CGM.getDiags(),
+ getLangOpts(), Loc, FD, TargetDecl);
}
void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
diff --git a/clang/lib/CodeGenUtils/CodeGenUtils.cpp b/clang/lib/CodeGenUtils/CodeGenUtils.cpp
index 42544c74af4aa..4fd78d6997e95 100644
--- a/clang/lib/CodeGenUtils/CodeGenUtils.cpp
+++ b/clang/lib/CodeGenUtils/CodeGenUtils.cpp
@@ -7,7 +7,13 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringMap.h"
namespace clang::CodeGenUtils {
static bool
@@ -112,4 +118,116 @@ bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
return BaseType->castAsCXXRecordDecl()->isDynamicClass();
}
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const CallExpr *E,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl) {
+ // SemaChecking cannot handle these x86 builtins because they have different
+ // parameter ranges depending on the caller's TargetAttribute.
+ if (Ctx.getTargetInfo().getTriple().isX86()) {
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
+ BuiltinID == X86::BI__builtin_ia32_cmpss ||
+ BuiltinID == X86::BI__builtin_ia32_cmppd ||
+ BuiltinID == X86::BI__builtin_ia32_cmpsd) {
+ llvm::StringMap<bool> TargetFeatureMap;
+ Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
+ llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
+ if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
+ Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
+ << TargetDecl->getDeclName() << "avx";
+ }
+ }
+ checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
+ TargetDecl);
+}
+
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, SourceLocation Loc,
+ const FunctionDecl *Caller,
+ const FunctionDecl *TargetDecl) {
+ if (!TargetDecl || !Caller)
+ return;
+
+ bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
+ bool IsFlatten = Caller->hasAttr<FlattenAttr>();
+
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ std::string MissingFeature;
+ llvm::StringMap<bool> CallerFeatureMap;
+ Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
+ // When compiling in HipStdPar mode we have to be conservative in rejecting
+ // target specific features in the FE, and defer the possible error to the
+ // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
+ // referenced by an accelerator executable function, we emit an error.
+ bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
+ if (BuiltinID) {
+ StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
+ if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
+ CallerFeatureMap) &&
+ !IsHipStdPar)
+ Diags.Report(Loc, diag::err_builtin_needs_feature)
+ << TargetDecl->getDeclName() << FeatureList;
+ } else if (!TargetDecl->isMultiVersion() &&
+ TargetDecl->hasAttr<TargetAttr>()) {
+ // Get the required features for the callee.
+ const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
+ ParsedTargetAttr ParsedAttr = Ctx.filterFunctionTargetAttrs(TD);
+
+ SmallVector<StringRef, 1> ReqFeatures;
+ llvm::StringMap<bool> CalleeFeatureMap;
+ Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+ for (const auto &F : ParsedAttr.Features) {
+ if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
+ ReqFeatures.push_back(StringRef(F).substr(1));
+ }
+ for (const auto &F : CalleeFeatureMap) {
+ if (F.getValue())
+ ReqFeatures.push_back(F.getKey());
+ }
+ if (!llvm::all_of(ReqFeatures,
+ [&](StringRef Feature) {
+ if (!CallerFeatureMap.lookup(Feature)) {
+ MissingFeature = Feature.str();
+ return false;
+ }
+ return true;
+ }) &&
+ !IsHipStdPar) {
+ if (IsAlwaysInline)
+ Diags.Report(Loc, diag::err_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << MissingFeature;
+ else if (IsFlatten)
+ Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << MissingFeature;
+ }
+ } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
+ llvm::StringMap<bool> CalleeFeatureMap;
+ Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+ for (const auto &F : CalleeFeatureMap) {
+ if (F.getValue() &&
+ (!CallerFeatureMap.lookup(F.getKey()) ||
+ !CallerFeatureMap.find(F.getKey())->getValue()) &&
+ !IsHipStdPar) {
+ if (IsAlwaysInline)
+ Diags.Report(Loc, diag::err_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << F.getKey();
+ else if (IsFlatten)
+ Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+ << Caller->getDeclName() << TargetDecl->getDeclName()
+ << F.getKey();
+ }
+ }
+ }
+}
+
} // namespace clang::CodeGenUtils
diff --git a/clang/test/CIR/CodeGen/avx512-error.c b/clang/test/CIR/CodeGen/avx512-error.c
new file mode 100644
index 0000000000000..1402c01ce5e55
--- /dev/null
+++ b/clang/test/CIR/CodeGen/avx512-error.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-linux-gnu -fclangir -target-feature +avx512bw -emit-llvm -o /dev/null -verify
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-linux-gnu -fclangir -target-feature +avx10.1 -emit-llvm -o /dev/null -verify
+
+#include <immintrin.h>
+
+__attribute__((target("avx512bw")))
+__mmask64 k64_verify_1(__mmask64 a) {
+ return _knot_mask64(a); // expected-no-diagnostics
+}
+
+__mmask64 k64_verify_2(__mmask64 a) {
+ return _knot_mask64(a); // expected-no-diagnostic
+}
+
+__attribute__((target("avx512bw")))
+__m512d zmm_verify_ok(__m512d a) {
+ return __builtin_ia32_...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/223056
More information about the cfe-commits
mailing list