[clang] [CIR][CodeGen] Implement target-features checking(CodeGenUtils!) (PR #223056)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 13:51:44 PDT 2026
https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/223056
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.
>From 4ddc1ad3d3ebaa86cbbe35dbcab49dc7e5ce48e0 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Thu, 10 Sep 2026 15:16:14 -0700
Subject: [PATCH] [CIR][CodeGen] Implement target-features
checking(CodeGenUtils!)
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.
---
.../include/clang/CodeGenUtils/CodeGenUtils.h | 23 ++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 22 ++
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 17 ++
clang/lib/CIR/CodeGen/CIRGenFunction.h | 7 +
clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 4 +
clang/lib/CodeGen/CodeGenFunction.cpp | 114 +---------
clang/lib/CodeGenUtils/CodeGenUtils.cpp | 118 ++++++++++
clang/test/CIR/CodeGen/avx512-error.c | 23 ++
.../test/CIR/CodeGen/target-builtin-error-2.c | 13 ++
.../test/CIR/CodeGen/target-builtin-error-3.c | 62 +++++
clang/test/CIR/CodeGen/target-builtin-error.c | 8 +
.../test/CIR/CodeGen/target-builtin-noerror.c | 215 ++++++++++++++++++
.../CIR/CodeGen/target-features-error-2.c | 50 ++++
.../CIR/CodeGen/target-features-error-3.c | 12 +
.../CIR/CodeGen/target-features-error-4.c | 12 +
.../CIR/CodeGen/target-features-error-5.c | 12 +
.../test/CIR/CodeGen/target-features-error.c | 7 +
.../CIR/CodeGen/target-features-no-error-2.c | 12 +
.../CIR/CodeGen/target-features-no-error.c | 9 +
.../X86/avx512vlvbmi2-builtins.c | 8 +-
.../CIR/CodeGenBuiltins/X86/sqrt-builtins.c | 6 +-
.../CodeGenBuiltins/builtin-undef-rvalue.cpp | 6 -
22 files changed, 639 insertions(+), 121 deletions(-)
create mode 100644 clang/test/CIR/CodeGen/avx512-error.c
create mode 100644 clang/test/CIR/CodeGen/target-builtin-error-2.c
create mode 100644 clang/test/CIR/CodeGen/target-builtin-error-3.c
create mode 100644 clang/test/CIR/CodeGen/target-builtin-error.c
create mode 100644 clang/test/CIR/CodeGen/target-builtin-noerror.c
create mode 100644 clang/test/CIR/CodeGen/target-features-error-2.c
create mode 100644 clang/test/CIR/CodeGen/target-features-error-3.c
create mode 100644 clang/test/CIR/CodeGen/target-features-error-4.c
create mode 100644 clang/test/CIR/CodeGen/target-features-error-5.c
create mode 100644 clang/test/CIR/CodeGen/target-features-error.c
create mode 100644 clang/test/CIR/CodeGen/target-features-no-error-2.c
create mode 100644 clang/test/CIR/CodeGen/target-features-no-error.c
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_sqrtpd512(a, _MM_FROUND_CUR_DIRECTION); // expected-no-diagnostic
+}
+
+__m512d zmm_error(__m512d a) {
+ // CHECK-LABEL: @test_mm512_sqrt_pd
+ return __builtin_ia32_sqrtpd512(a, _MM_FROUND_CUR_DIRECTION); // noevex-error {{'__builtin_ia32_sqrtpd512' needs target feature avx512f}}
+}
diff --git a/clang/test/CIR/CodeGen/target-builtin-error-2.c b/clang/test/CIR/CodeGen/target-builtin-error-2.c
new file mode 100644
index 0000000000000..bc18a9fba0940
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-builtin-error-2.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o -
+#define __MM_MALLOC_H
+
+#include <x86intrin.h>
+
+// Since we do code generation on a function level this needs to error out since
+// the subtarget feature won't be available.
+__m128 wombat(__m128i a) {
+ if (__builtin_cpu_supports("avx"))
+ return __builtin_ia32_vpermilvarps((__v4sf) {0.0f, 1.0f, 2.0f, 3.0f}, (__v4si)a); // expected-error {{'__builtin_ia32_vpermilvarps' needs target feature avx}}
+ else
+ return (__m128){0, 0};
+}
diff --git a/clang/test/CIR/CodeGen/target-builtin-error-3.c b/clang/test/CIR/CodeGen/target-builtin-error-3.c
new file mode 100644
index 0000000000000..0f75fff278abb
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-builtin-error-3.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -fclangir -S -verify -o - -target-feature +avx
+
+// RUN: not %clang_cc1 %s -triple=x86_64-apple-darwin -fclangir -emit-obj -target-feature +avx 2> %t.err
+// RUN: FileCheck < %t.err %s
+//
+// CHECK: 1 error generated
+
+typedef unsigned short uint16_t;
+typedef long long __m128i __attribute__((__vector_size__(16)));
+typedef float __v8sf __attribute__ ((__vector_size__ (32)));
+typedef float __m256 __attribute__ ((__vector_size__ (32)));
+typedef uint16_t half;
+typedef __attribute__ ((ext_vector_type( 8),__aligned__( 16))) half half8;
+typedef __attribute__ ((ext_vector_type(16),__aligned__( 32))) half half16;
+typedef __attribute__ ((ext_vector_type(16),__aligned__( 2))) half half16U;
+typedef __attribute__ ((ext_vector_type( 8),__aligned__( 32))) float float8;
+typedef __attribute__ ((ext_vector_type(16),__aligned__( 64))) float float16;
+static inline half8 __attribute__((__overloadable__)) convert_half( float8 a ) {
+ return __extension__ ({ __m256 __a = (a); (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)__a, (0x00)); }); // expected-error {{'__builtin_ia32_vcvtps2ph256' needs target feature f16c}}
+}
+// Internal definitions do not warn.
+static inline half16 __attribute__((__overloadable__)) convert_half( float16 a ) {
+ half16 r;
+ r.lo = convert_half(a.lo);
+ return r;
+}
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+void avx_test( uint16_t *destData, float16 argbF)
+{
+ ((half16U *)destData)[0] = convert_half(argbF);
+}
+
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+half16 test( float16 a ) {
+ half16 r;
+ r.lo = convert_half(a.lo);
+ return r;
+}
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+void avx_test2( uint16_t *destData, float16 argbF)
+{
+ // FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+ // <expected>-warning at +1{{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+ ((half16U *)destData)[0] = test(argbF);
+}
+
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+__attribute__((always_inline)) half16 test2( float16 a ) {
+ half16 r;
+ r.lo = convert_half(a.lo);
+ return r;
+}
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+void avx_test3( uint16_t *destData, float16 argbF)
+{
+ ((half16U *)destData)[0] = test2(argbF);
+}
diff --git a/clang/test/CIR/CodeGen/target-builtin-error.c b/clang/test/CIR/CodeGen/target-builtin-error.c
new file mode 100644
index 0000000000000..d8bd68ac11ce6
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-builtin-error.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o -
+#define __MM_MALLOC_H
+
+#include <x86intrin.h>
+
+__m128 foo(__m128 a, __m128 b) {
+ return __builtin_ia32_addsubps(b, a); // expected-error {{'__builtin_ia32_addsubps' needs target feature sse3}}
+}
diff --git a/clang/test/CIR/CodeGen/target-builtin-noerror.c b/clang/test/CIR/CodeGen/target-builtin-noerror.c
new file mode 100644
index 0000000000000..30161947a99ee
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-builtin-noerror.c
@@ -0,0 +1,215 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -o - -Werror
+#define __MM_MALLOC_H
+
+#include <x86intrin.h>
+
+// No warnings.
+extern __m256i a;
+int __attribute__((target("avx"))) bar(void) {
+ return _mm256_extract_epi32(a, 3);
+}
+
+int baz(void) {
+ return bar();
+}
+
+int __attribute__((target("avx"))) qq_avx(void) {
+ return _mm256_extract_epi32(a, 3);
+}
+
+int qq_noavx(void) {
+ return 0;
+}
+
+extern __m256i a;
+int qq(void) {
+ if (__builtin_cpu_supports("avx"))
+ return qq_avx();
+ else
+ return qq_noavx();
+}
+
+// Test that fma and fma4 are both separately and combined valid for an fma intrinsic.
+__m128 __attribute__((target("fma"))) fma_1(__m128 a, __m128 b, __m128 c) {
+ return __builtin_ia32_vfmaddsubps(a, b, c);
+}
+
+__m128 __attribute__((target("fma4"))) fma_2(__m128 a, __m128 b, __m128 c) {
+ return __builtin_ia32_vfmaddsubps(a, b, c);
+}
+
+__m128 __attribute__((target("fma,fma4"))) fma_3(__m128 a, __m128 b, __m128 c) {
+ return __builtin_ia32_vfmaddsubps(a, b, c);
+}
+
+void verifyfeaturestrings(void) {
+ (void)__builtin_cpu_supports("cmov");
+ (void)__builtin_cpu_supports("mmx");
+ (void)__builtin_cpu_supports("popcnt");
+ (void)__builtin_cpu_supports("sse");
+ (void)__builtin_cpu_supports("sse2");
+ (void)__builtin_cpu_supports("sse3");
+ (void)__builtin_cpu_supports("ssse3");
+ (void)__builtin_cpu_supports("sse4.1");
+ (void)__builtin_cpu_supports("sse4.2");
+ (void)__builtin_cpu_supports("avx");
+ (void)__builtin_cpu_supports("avx2");
+ (void)__builtin_cpu_supports("sse4a");
+ (void)__builtin_cpu_supports("fma4");
+ (void)__builtin_cpu_supports("xop");
+ (void)__builtin_cpu_supports("fma");
+ (void)__builtin_cpu_supports("avx512f");
+ (void)__builtin_cpu_supports("bmi");
+ (void)__builtin_cpu_supports("bmi2");
+ (void)__builtin_cpu_supports("aes");
+ (void)__builtin_cpu_supports("pclmul");
+ (void)__builtin_cpu_supports("avx512vl");
+ (void)__builtin_cpu_supports("avx512bw");
+ (void)__builtin_cpu_supports("avx512dq");
+ (void)__builtin_cpu_supports("avx512cd");
+ (void)__builtin_cpu_supports("avx512vbmi");
+ (void)__builtin_cpu_supports("avx512ifma");
+ (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)__builtin_cpu_supports("avx512bmm");
+ (void)__builtin_cpu_supports("avx512bf16");
+ (void)__builtin_cpu_supports("avx512vp2intersect");
+ (void)__builtin_cpu_supports("f16c");
+ (void)__builtin_cpu_supports("avx512fp16");
+ (void)__builtin_cpu_supports("adx");
+ (void)__builtin_cpu_supports("cldemote");
+ (void)__builtin_cpu_supports("clflushopt");
+ (void)__builtin_cpu_supports("clwb");
+ (void)__builtin_cpu_supports("clzero");
+ (void)__builtin_cpu_supports("cx16");
+ (void)__builtin_cpu_supports("enqcmd");
+ (void)__builtin_cpu_supports("fsgsbase");
+ (void)__builtin_cpu_supports("lwp");
+ (void)__builtin_cpu_supports("lzcnt");
+ (void)__builtin_cpu_supports("movbe");
+ (void)__builtin_cpu_supports("movdir64b");
+ (void)__builtin_cpu_supports("movdiri");
+ (void)__builtin_cpu_supports("mwaitx");
+ (void)__builtin_cpu_supports("pconfig");
+ (void)__builtin_cpu_supports("pku");
+ (void)__builtin_cpu_supports("prfchw");
+ (void)__builtin_cpu_supports("ptwrite");
+ (void)__builtin_cpu_supports("rdpid");
+ (void)__builtin_cpu_supports("rdrnd");
+ (void)__builtin_cpu_supports("rdseed");
+ (void)__builtin_cpu_supports("rtm");
+ (void)__builtin_cpu_supports("serialize");
+ (void)__builtin_cpu_supports("sgx");
+ (void)__builtin_cpu_supports("sha");
+ (void)__builtin_cpu_supports("shstk");
+ (void)__builtin_cpu_supports("tbm");
+ (void)__builtin_cpu_supports("tsxldtrk");
+ (void)__builtin_cpu_supports("vaes");
+ (void)__builtin_cpu_supports("waitpkg");
+ (void)__builtin_cpu_supports("wbnoinvd");
+ (void)__builtin_cpu_supports("xsave");
+ (void)__builtin_cpu_supports("xsavec");
+ (void)__builtin_cpu_supports("xsaveopt");
+ (void)__builtin_cpu_supports("xsaves");
+ (void)__builtin_cpu_supports("amx-tile");
+ (void)__builtin_cpu_supports("amx-int8");
+ (void)__builtin_cpu_supports("amx-bf16");
+ (void)__builtin_cpu_supports("uintr");
+ (void)__builtin_cpu_supports("hreset");
+ (void)__builtin_cpu_supports("kl");
+ (void)__builtin_cpu_supports("widekl");
+ (void)__builtin_cpu_supports("avxvnni");
+ (void)__builtin_cpu_supports("avxifma");
+ (void)__builtin_cpu_supports("avxvnniint8");
+ (void)__builtin_cpu_supports("avxneconvert");
+ (void)__builtin_cpu_supports("cmpccxadd");
+ (void)__builtin_cpu_supports("amx-fp16");
+ (void)__builtin_cpu_supports("prefetchi");
+ (void)__builtin_cpu_supports("raoint");
+ (void)__builtin_cpu_supports("amx-complex");
+ (void)__builtin_cpu_supports("avxvnniint16");
+ (void)__builtin_cpu_supports("sm3");
+ (void)__builtin_cpu_supports("sha512");
+ (void)__builtin_cpu_supports("sm4");
+ (void)__builtin_cpu_supports("apxf");
+ (void)__builtin_cpu_supports("usermsr");
+ (void)__builtin_cpu_supports("avx10.1");
+ (void)__builtin_cpu_supports("avx10.2");
+ (void)__builtin_cpu_supports("movrs");
+}
+
+void verifycpustrings(void) {
+ (void)__builtin_cpu_is("alderlake");
+ (void)__builtin_cpu_is("amd");
+ (void)__builtin_cpu_is("amdfam10h");
+ (void)__builtin_cpu_is("amdfam15h");
+ (void)__builtin_cpu_is("amdfam17h");
+ (void)__builtin_cpu_is("atom");
+ (void)__builtin_cpu_is("barcelona");
+ (void)__builtin_cpu_is("bdver1");
+ (void)__builtin_cpu_is("bdver2");
+ (void)__builtin_cpu_is("bdver3");
+ (void)__builtin_cpu_is("bdver4");
+ (void)__builtin_cpu_is("bonnell");
+ (void)__builtin_cpu_is("broadwell");
+ (void)__builtin_cpu_is("btver1");
+ (void)__builtin_cpu_is("btver2");
+ (void)__builtin_cpu_is("cannonlake");
+ (void)__builtin_cpu_is("cascadelake");
+ (void)__builtin_cpu_is("cooperlake");
+ (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("grandridge");
+ (void)__builtin_cpu_is("graniterapids");
+ (void)__builtin_cpu_is("emeraldrapids");
+ (void)__builtin_cpu_is("graniterapids-d");
+ (void)__builtin_cpu_is("arrowlake");
+ (void)__builtin_cpu_is("arrowlake-s");
+ (void)__builtin_cpu_is("lunarlake");
+ (void)__builtin_cpu_is("clearwaterforest");
+ (void)__builtin_cpu_is("pantherlake");
+ (void)__builtin_cpu_is("wildcatlake");
+ (void)__builtin_cpu_is("novalake");
+ (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");
+ (void)__builtin_cpu_is("knl");
+ (void)__builtin_cpu_is("knm");
+ (void)__builtin_cpu_is("meteorlake");
+ (void)__builtin_cpu_is("nehalem");
+ (void)__builtin_cpu_is("raptorlake");
+ (void)__builtin_cpu_is("rocketlake");
+ (void)__builtin_cpu_is("sandybridge");
+ (void)__builtin_cpu_is("shanghai");
+ (void)__builtin_cpu_is("sierraforest");
+ (void)__builtin_cpu_is("silvermont");
+ (void)__builtin_cpu_is("skylake");
+ (void)__builtin_cpu_is("skylake-avx512");
+ (void)__builtin_cpu_is("slm");
+ (void)__builtin_cpu_is("tigerlake");
+ (void)__builtin_cpu_is("sapphirerapids");
+ (void)__builtin_cpu_is("tremont");
+ (void)__builtin_cpu_is("gracemont");
+ (void)__builtin_cpu_is("westmere");
+ (void)__builtin_cpu_is("znver1");
+ (void)__builtin_cpu_is("znver2");
+ (void)__builtin_cpu_is("znver3");
+ (void)__builtin_cpu_is("znver4");
+ (void)__builtin_cpu_is("znver5");
+ (void)__builtin_cpu_is("znver6");
+ (void)__builtin_cpu_is("diamondrapids");
+ (void)__builtin_cpu_is("c86-4g-m4");
+ (void)__builtin_cpu_is("c86-4g-m6");
+ (void)__builtin_cpu_is("c86-4g-m7");
+ (void)__builtin_cpu_is("c86-4g-m8");
+}
diff --git a/clang/test/CIR/CodeGen/target-features-error-2.c b/clang/test/CIR/CodeGen/target-features-error-2.c
new file mode 100644
index 0000000000000..6891e6c73a4e2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-error-2.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o - -D NEED_AVX_1
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o - -D NEED_AVX_2
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o - -D NEED_AVX512f
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -target-feature +movdir64b -S -verify -o - -D NEED_MOVDIRI
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -target-feature +avx512vnni -target-feature +movdiri -S -verify -o - -D NEED_CLWB
+
+#define __MM_MALLOC_H
+#include <x86intrin.h>
+
+#if NEED_AVX_1
+// FIXME(cir): The below warning should be emitted, which requires avx builtin checking..
+// <expected>-warning at +1 {{AVX vector argument of type '__m256i' (vector of 4 'long long' values) without 'avx' enabled changes the ABI}}
+int baz(__m256i a) {
+ return _mm256_extract_epi32(a, 3); // expected-error {{'__builtin_ia32_vec_ext_v8si' needs target feature avx}}
+}
+#endif
+
+#if NEED_AVX_2
+__m128 need_avx(__m128 a, __m128 b) {
+ // expected-error at +2{{unimplemented X86 builtin call:}}
+ // expected-error at +1{{unimplemented builtin call:}}
+ return _mm_cmp_ps(a, b, 8); // expected-error {{'__builtin_ia32_cmpps' 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
+
+#if NEED_MOVDIRI
+void need_movdiri(unsigned int *a, unsigned int b) {
+ __builtin_ia32_directstore_u32(a, b); // expected-error {{'__builtin_ia32_directstore_u32' needs target feature movdiri}}
+}
+#endif
+
+#if NEED_CLWB
+static __inline__ void
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni,clwb,movdiri,movdir64b")))
+ func(unsigned int *a, unsigned int b)
+{
+ __builtin_ia32_directstore_u32(a, b);
+}
+
+void need_clwb(unsigned int *a, unsigned int b) {
+ func(a, b); // expected-error {{always_inline function 'func' requires target feature 'clwb', but would be inlined into function 'need_clwb' that is compiled without support for 'clwb'}}
+
+}
+#endif
diff --git a/clang/test/CIR/CodeGen/target-features-error-3.c b/clang/test/CIR/CodeGen/target-features-error-3.c
new file mode 100644
index 0000000000000..4690b5a258c77
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-error-3.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -emit-llvm -verify -o /dev/null
+
+typedef double __v2df __attribute__((__vector_size__(16)));
+
+__v2df __attribute__((target("sse4.1"))) foo() {
+ __v2df v = {0.0, 0.0};
+ return v;
+}
+
+__v2df __attribute__((flatten)) bar() {
+ return foo(); // expected-error {{flatten function 'bar' calls 'foo' which requires target feature 'sse4.1', but the caller is compiled without support for 'sse4.1'}}
+}
diff --git a/clang/test/CIR/CodeGen/target-features-error-4.c b/clang/test/CIR/CodeGen/target-features-error-4.c
new file mode 100644
index 0000000000000..107f79cb669f1
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-error-4.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -emit-llvm -verify -o /dev/null
+
+typedef double __v2df __attribute__((__vector_size__(16)));
+
+__v2df __attribute__((target("sse4.1"))) foo() {
+ __v2df v = {0.0, 0.0};
+ return v;
+}
+
+__v2df __attribute__((target("no-sse4.1"), flatten)) bar() {
+ return foo(); // expected-error {{flatten function 'bar' calls 'foo' which requires target feature 'sse4.1', but the caller is compiled without support for 'sse4.1'}}
+}
diff --git a/clang/test/CIR/CodeGen/target-features-error-5.c b/clang/test/CIR/CodeGen/target-features-error-5.c
new file mode 100644
index 0000000000000..2d01f381a427f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-error-5.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -target-feature +sse4.1 -emit-llvm -verify -o /dev/null
+
+typedef double __v2df __attribute__((__vector_size__(16)));
+
+__v2df foo() {
+ __v2df v = {0.0, 0.0};
+ return v;
+}
+
+__v2df __attribute__((target("no-sse4.1"), flatten)) bar() {
+ return foo(); // expected-error {{flatten function 'bar' calls 'foo' which requires target feature 'sse4.1', but the caller is compiled without support for 'sse4.1'}}
+}
diff --git a/clang/test/CIR/CodeGen/target-features-error.c b/clang/test/CIR/CodeGen/target-features-error.c
new file mode 100644
index 0000000000000..8ac0ecad4dd30
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-error.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -fclangir -S -verify -o -
+int __attribute__((target("avx"), always_inline)) foo(int a) {
+ return a + 4;
+}
+int bar(void) {
+ 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'}}
+}
diff --git a/clang/test/CIR/CodeGen/target-features-no-error-2.c b/clang/test/CIR/CodeGen/target-features-no-error-2.c
new file mode 100644
index 0000000000000..5d2cc59835d79
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-no-error-2.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fclangir -verify -o /dev/null
+
+typedef double __v2df __attribute__((__vector_size__(16)));
+
+__v2df __attribute__((target("sse4.1"))) foo() {
+ __v2df v = {0.0, 0.0};
+ return v;
+}
+
+__v2df __attribute__((target("sse4.1"), flatten)) bar() {
+ return foo(); // expected-no-diagnostics
+}
diff --git a/clang/test/CIR/CodeGen/target-features-no-error.c b/clang/test/CIR/CodeGen/target-features-no-error.c
new file mode 100644
index 0000000000000..4f535495a78ed
--- /dev/null
+++ b/clang/test/CIR/CodeGen/target-features-no-error.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -fclangir -o - -target-feature -sse2
+
+// Verify that negative features don't cause additional requirements on the inline function.
+int __attribute__((target("sse"), always_inline)) foo(int a) {
+ return a + 4;
+}
+int bar(void) {
+ return foo(4); // expected-no-diagnostics
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512vlvbmi2-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512vlvbmi2-builtins.c
index 9e0cdaa9eea75..c1e60b2f0a5a5 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512vlvbmi2-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512vlvbmi2-builtins.c
@@ -1,12 +1,12 @@
-// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vlvbmi2 -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion
+// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vl -target-feature +avx512vbmi2 -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
-// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vlvbmi2 -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion
+// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vl -target-feature +avx512vbmi2 -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
-// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vlvbmi2 -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion
+// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vl -target-feature +avx512vbmi2 -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
-// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vlvbmi2 -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion
+// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512vl -target-feature +avx512vbmi2 -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
#include <immintrin.h>
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/sqrt-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/sqrt-builtins.c
index d540e9c227e67..2ba0e2ca63ff1 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/sqrt-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/sqrt-builtins.c
@@ -1,8 +1,8 @@
// Test X86-specific sqrt builtins
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -target-feature +avx512fp16 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -target-feature +avx512fp16 -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -target-feature +avx512fp16 -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
@@ -42,4 +42,4 @@ __m512d test_sqrtpd512(__m512d a) {
// LLVM-LABEL: define {{.*}} @test_sqrtpd512
// LLVM: call <8 x double> @llvm.sqrt.v8f64
// OGCG-LABEL: define {{.*}} @test_sqrtpd512
-// OGCG: call <8 x double> @llvm.sqrt.v8f64
\ No newline at end of file
+// OGCG: call <8 x double> @llvm.sqrt.v8f64
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-undef-rvalue.cpp b/clang/test/CIR/CodeGenBuiltins/builtin-undef-rvalue.cpp
index dac0ddf366334..c15375621f08a 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-undef-rvalue.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-undef-rvalue.cpp
@@ -1,7 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -verify %s -o - > %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -verify %s -o - > %t.ll
-// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
typedef int v4si __attribute__((vector_size(16)));
@@ -13,7 +11,3 @@ int test_builtin_reduce_add_undef_rvalue(v4si x) {
// CIR-LABEL: @_Z36test_builtin_reduce_add_undef_rvalueDv4_i
// CIR: cir.const #cir.undef : !s32i
// CIR: cir.return
-
-// LLVM-LABEL: @_Z36test_builtin_reduce_add_undef_rvalueDv4_i
-// LLVM: store i32 undef, ptr %{{.+}}, align 4
-// LLVM: ret i32 %{{.+}}
More information about the cfe-commits
mailing list