From 6e11fd34d0f135140d6d7d175d4ca6954f2f266c Mon Sep 17 00:00:00 2001 From: 7mile Date: Thu, 11 Jul 2024 03:35:43 +0800 Subject: [PATCH] [CIR][Dialect] Emit OpenCL kernel metadata (#705) This PR introduces a new attribute `OpenCLKernelMetadataAttr` to model the OpenCL kernel metadata structurally in CIR, with its corresponding implementations of CodeGen, Lowering and Translation. The `"TypeAttr":$vec_type_hint` part is tricky because of the absence of the signless feature of LLVM IR, while SPIR-V requires it. According to the spec, the final LLVM IR should encode signedness with an extra `i32` boolean value. In this PR, the droping logic from CIR's `TypeConverter` is still used to avoid code duplication when lowering to LLVM dialect. However, the signedness is then restored (still capsuled by a CIR attribute) and dropped again in the translation into LLVM IR. --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 2 + .../clang/CIR/Dialect/IR/CIROpenCLAttrs.td | 95 +++++++++++++++++++ clang/include/clang/CIR/MissingFeatures.h | 1 + clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 67 ++++++++++++- clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 + clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 55 +++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 41 +++++++- .../Lowering/DirectToLLVM/LowerToLLVMIR.cpp | 59 ++++++++++++ .../CIR/CodeGen/OpenCL/kernel-attributes.cl | 35 +++++++ .../CIR/IR/invalid-opencl-vec-type-hint.cir | 7 ++ clang/test/CIR/IR/invalid.cir | 45 +++++++++ 11 files changed, 406 insertions(+), 5 deletions(-) create mode 100644 clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td create mode 100644 clang/test/CIR/CodeGen/OpenCL/kernel-attributes.cl create mode 100644 clang/test/CIR/IR/invalid-opencl-vec-type-hint.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index b5cff38517e2..ca9e991e6565 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -979,4 +979,6 @@ def BitfieldInfoAttr : CIR_Attr<"BitfieldInfo", "bitfield_info"> { ]; } +include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td" + #endif // MLIR_CIR_DIALECT_CIR_ATTRS diff --git a/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td new file mode 100644 index 000000000000..1f32701909b7 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td @@ -0,0 +1,95 @@ +//===- CIROpenCLAttrs.td - CIR dialect attrs for OpenCL ----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the CIR dialect attributes for OpenCL. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CIR_DIALECT_CIR_OPENCL_ATTRS +#define MLIR_CIR_DIALECT_CIR_OPENCL_ATTRS + +//===----------------------------------------------------------------------===// +// OpenCLKernelMetadataAttr +//===----------------------------------------------------------------------===// + +def OpenCLKernelMetadataAttr + : CIR_Attr<"OpenCLKernelMetadata", "cl.kernel_metadata"> { + + let summary = "OpenCL kernel metadata"; + let description = [{ + Provide the required information of an OpenCL kernel for the SPIR-V backend. + + The `work_group_size_hint` and `reqd_work_group_size` parameter are integer + arrays with 3 elements that provide hints for the work-group size and the + required work-group size, respectively. + + The `vec_type_hint` parameter is a type attribute that provides a hint for + the vectorization. It can be a CIR or LLVM type, depending on the lowering + stage. + + The `vec_type_hint_signedness` parameter is a boolean that indicates the + signedness of the vector type hint. It's useful when LLVM type is set in + `vec_type_hint`, which is signless by design. It should be set if and only + if the `vec_type_hint` is present. + + The `intel_reqd_sub_group_size` parameter is an integer that restricts the + sub-group size to the specified value. + + Example: + ``` + #fn_attr = #cir})> + + cir.func @kernel(%arg0: !s32i) extra(#fn_attr) { + cir.return + } + ``` + }]; + + let parameters = (ins + OptionalParameter<"ArrayAttr">:$work_group_size_hint, + OptionalParameter<"ArrayAttr">:$reqd_work_group_size, + OptionalParameter<"TypeAttr">:$vec_type_hint, + OptionalParameter<"std::optional">:$vec_type_hint_signedness, + OptionalParameter<"IntegerAttr">:$intel_reqd_sub_group_size + ); + + let assemblyFormat = "`<` struct(params) `>`"; + + let genVerifyDecl = 1; + + let extraClassDeclaration = [{ + /// Extract the signedness from int or int vector types. + static std::optional isSignedHint(mlir::Type vecTypeHint); + }]; + + let extraClassDefinition = [{ + std::optional $cppClass::isSignedHint(mlir::Type hintQTy) { + // Only types in CIR carry signedness + if (!mlir::isa(hintQTy.getDialect())) + return std::nullopt; + + // See also clang::CodeGen::CodeGenFunction::EmitKernelMetadata + auto hintEltQTy = mlir::dyn_cast(hintQTy); + auto isCIRSignedIntType = [](mlir::Type t) { + return mlir::isa(t) && + mlir::cast(t).isSigned(); + }; + return isCIRSignedIntType(hintQTy) || + (hintEltQTy && isCIRSignedIntType(hintEltQTy.getEltType())); + } + }]; + +} + +#endif // MLIR_CIR_DIALECT_CIR_OPENCL_ATTRS diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 3c096884a04b..5e2c4f7143a9 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -142,6 +142,7 @@ struct MissingFeatures { static bool getFPFeaturesInEffect() { return false; } static bool cxxABI() { return false; } static bool openCL() { return false; } + static bool openCLGenKernelMetadata() { return false; } static bool CUDA() { return false; } static bool openMP() { return false; } static bool openMPRuntime() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index f5efa14796ab..27049934a556 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -993,8 +993,7 @@ void CIRGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm_unreachable("NYI"); if (FD && getLangOpts().OpenCL) { - // TODO(cir): Emit OpenCL kernel metadata - assert(!MissingFeatures::openCL()); + buildKernelMetadata(FD, Fn); } // If we are checking function types, emit a function type signature as @@ -1720,3 +1719,67 @@ CIRGenFunction::buildArrayLength(const clang::ArrayType *origArrayType, return numElements; } + +void CIRGenFunction::buildKernelMetadata(const FunctionDecl *FD, + mlir::cir::FuncOp Fn) { + if (!FD->hasAttr() && !FD->hasAttr()) + return; + + // TODO(cir): CGM.genKernelArgMetadata(Fn, FD, this); + assert(!MissingFeatures::openCLGenKernelMetadata()); + + if (!getLangOpts().OpenCL) + return; + + using mlir::cir::OpenCLKernelMetadataAttr; + + mlir::ArrayAttr workGroupSizeHintAttr, reqdWorkGroupSizeAttr; + mlir::TypeAttr vecTypeHintAttr; + std::optional vecTypeHintSignedness; + mlir::IntegerAttr intelReqdSubGroupSizeAttr; + + if (const VecTypeHintAttr *A = FD->getAttr()) { + mlir::Type typeHintValue = getTypes().ConvertType(A->getTypeHint()); + vecTypeHintAttr = mlir::TypeAttr::get(typeHintValue); + vecTypeHintSignedness = + OpenCLKernelMetadataAttr::isSignedHint(typeHintValue); + } + + if (const WorkGroupSizeHintAttr *A = FD->getAttr()) { + workGroupSizeHintAttr = builder.getI32ArrayAttr({ + static_cast(A->getXDim()), + static_cast(A->getYDim()), + static_cast(A->getZDim()), + }); + } + + if (const ReqdWorkGroupSizeAttr *A = FD->getAttr()) { + reqdWorkGroupSizeAttr = builder.getI32ArrayAttr({ + static_cast(A->getXDim()), + static_cast(A->getYDim()), + static_cast(A->getZDim()), + }); + } + + if (const OpenCLIntelReqdSubGroupSizeAttr *A = + FD->getAttr()) { + intelReqdSubGroupSizeAttr = builder.getI32IntegerAttr(A->getSubGroupSize()); + } + + // Skip the metadata attr if no hints are present. + if (!vecTypeHintAttr && !workGroupSizeHintAttr && !reqdWorkGroupSizeAttr && + !intelReqdSubGroupSizeAttr) + return; + + // Append the kernel metadata to the extra attributes dictionary. + mlir::NamedAttrList attrs; + attrs.append(Fn.getExtraAttrs().getElements()); + + auto kernelMetadataAttr = OpenCLKernelMetadataAttr::get( + builder.getContext(), workGroupSizeHintAttr, reqdWorkGroupSizeAttr, + vecTypeHintAttr, vecTypeHintSignedness, intelReqdSubGroupSizeAttr); + attrs.append(kernelMetadataAttr.getMnemonic(), kernelMetadataAttr); + + Fn.setExtraAttrsAttr(mlir::cir::ExtraFuncAttributesAttr::get( + builder.getContext(), attrs.getDictionary(builder.getContext()))); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 8d40f29439ce..77da0e2185a1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -100,6 +100,10 @@ class CIRGenFunction : public CIRGenTypeCache { // enter/leave scopes. llvm::DenseMap VLASizeMap; + /// Add OpenCL kernel arg metadata and the kernel attribute metadata to + /// the function metadata. + void buildKernelMetadata(const FunctionDecl *FD, mlir::cir::FuncOp Fn); + public: /// A non-RAII class containing all the information about a bound /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 6a8596f6ebcd..08769cdd5066 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -15,6 +15,7 @@ #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinAttributeInterfaces.h" @@ -499,6 +500,60 @@ LogicalResult DynamicCastInfoAttr::verify( return success(); } +//===----------------------------------------------------------------------===// +// OpenCLKernelMetadataAttr definitions +//===----------------------------------------------------------------------===// + +LogicalResult OpenCLKernelMetadataAttr::verify( + ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, + ArrayAttr workGroupSizeHint, ArrayAttr reqdWorkGroupSize, + TypeAttr vecTypeHint, std::optional vecTypeHintSignedness, + IntegerAttr intelReqdSubGroupSize) { + // If no field is present, the attribute is considered invalid. + if (!workGroupSizeHint && !reqdWorkGroupSize && !vecTypeHint && + !vecTypeHintSignedness && !intelReqdSubGroupSize) { + return emitError() + << "metadata attribute without any field present is invalid"; + } + + // Check for 3-dim integer tuples + auto is3dimIntTuple = [](ArrayAttr arr) { + auto isInt = [](Attribute dim) { return mlir::isa(dim); }; + return arr.size() == 3 && llvm::all_of(arr, isInt); + }; + if (workGroupSizeHint && !is3dimIntTuple(workGroupSizeHint)) { + return emitError() + << "work_group_size_hint must have exactly 3 integer elements"; + } + if (reqdWorkGroupSize && !is3dimIntTuple(reqdWorkGroupSize)) { + return emitError() + << "reqd_work_group_size must have exactly 3 integer elements"; + } + + // Check for co-presence of vecTypeHintSignedness + if (!!vecTypeHint != vecTypeHintSignedness.has_value()) { + return emitError() << "vec_type_hint_signedness should be present if and " + "only if vec_type_hint is set"; + } + + if (vecTypeHint) { + Type vecTypeHintValue = vecTypeHint.getValue(); + if (mlir::isa(vecTypeHintValue.getDialect())) { + // Check for signedness alignment in CIR + if (isSignedHint(vecTypeHintValue) != vecTypeHintSignedness) { + return emitError() << "vec_type_hint_signedness must match the " + "signedness of the vec_type_hint type"; + } + // Check for the dialect of type hint + } else if (!LLVM::isCompatibleType(vecTypeHintValue)) { + return emitError() << "vec_type_hint must be a type from the CIR or LLVM " + "dialect"; + } + } + + return success(); +} + //===----------------------------------------------------------------------===// // CIR Dialect //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index d9b4724e4c71..ec933b27a826 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1523,12 +1523,13 @@ class CIRFuncLowering : public mlir::OpConversionPattern { /// to the name of the attribute in ODS. static StringRef getLinkageAttrNameString() { return "linkage"; } + /// Convert the `cir.func` attributes to `llvm.func` attributes. /// Only retain those attributes that are not constructed by /// `LLVMFuncOp::build`. If `filterArgAttrs` is set, also filter out /// argument attributes. void - filterFuncAttributes(mlir::cir::FuncOp func, bool filterArgAndResAttrs, - SmallVectorImpl &result) const { + lowerFuncAttributes(mlir::cir::FuncOp func, bool filterArgAndResAttrs, + SmallVectorImpl &result) const { for (auto attr : func->getAttrs()) { if (attr.getName() == mlir::SymbolTable::getSymbolAttrName() || attr.getName() == func.getFunctionTypeAttrName() || @@ -1543,11 +1544,45 @@ class CIRFuncLowering : public mlir::OpConversionPattern { if (attr.getName() == func.getExtraAttrsAttrName()) { std::string cirName = "cir." + func.getExtraAttrsAttrName().str(); attr.setName(mlir::StringAttr::get(getContext(), cirName)); + + lowerFuncOpenCLKernelMetadata(attr); } result.push_back(attr); } } + /// When do module translation, we can only translate LLVM-compatible types. + /// Here we lower possible OpenCLKernelMetadataAttr to use the converted type. + void + lowerFuncOpenCLKernelMetadata(mlir::NamedAttribute &extraAttrsEntry) const { + const auto attrKey = mlir::cir::OpenCLKernelMetadataAttr::getMnemonic(); + auto oldExtraAttrs = + cast(extraAttrsEntry.getValue()); + if (!oldExtraAttrs.getElements().contains(attrKey)) + return; + + mlir::NamedAttrList newExtraAttrs; + for (auto entry : oldExtraAttrs.getElements()) { + if (entry.getName() == attrKey) { + auto clKernelMetadata = + cast(entry.getValue()); + if (auto vecTypeHint = clKernelMetadata.getVecTypeHint()) { + auto newType = typeConverter->convertType(vecTypeHint.getValue()); + auto newTypeHint = mlir::TypeAttr::get(newType); + auto newCLKMAttr = mlir::cir::OpenCLKernelMetadataAttr::get( + getContext(), clKernelMetadata.getWorkGroupSizeHint(), + clKernelMetadata.getReqdWorkGroupSize(), newTypeHint, + clKernelMetadata.getVecTypeHintSignedness(), + clKernelMetadata.getIntelReqdSubGroupSize()); + entry.setValue(newCLKMAttr); + } + } + newExtraAttrs.push_back(entry); + } + extraAttrsEntry.setValue(mlir::cir::ExtraFuncAttributesAttr::get( + getContext(), newExtraAttrs.getDictionary(getContext()))); + } + mlir::LogicalResult matchAndRewrite(mlir::cir::FuncOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { @@ -1585,7 +1620,7 @@ class CIRFuncLowering : public mlir::OpConversionPattern { auto linkage = convertLinkage(op.getLinkage()); SmallVector attributes; - filterFuncAttributes(op, /*filterArgAndResAttrs=*/false, attributes); + lowerFuncAttributes(op, /*filterArgAndResAttrs=*/false, attributes); auto fn = rewriter.create( Loc, op.getName(), llvmFnTy, linkage, isDsoLocal, mlir::LLVM::CConv::C, diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp index ea1c04d76fc9..62a988b37533 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp @@ -61,6 +61,11 @@ class CIRDialectLLVMIRTranslationInterface llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone); } else if (mlir::dyn_cast(attr.getValue())) { llvmFunc->addFnAttr(llvm::Attribute::NoUnwind); + } else if (auto clKernelMetadata = + mlir::dyn_cast( + attr.getValue())) { + emitOpenCLKernelMetadata(clKernelMetadata, llvmFunc, + moduleTranslation); } } } @@ -83,6 +88,60 @@ class CIRDialectLLVMIRTranslationInterface return mlir::success(); } + +private: + void emitOpenCLKernelMetadata( + mlir::cir::OpenCLKernelMetadataAttr clKernelMetadata, + llvm::Function *llvmFunc, + mlir::LLVM::ModuleTranslation &moduleTranslation) const { + auto &vmCtx = moduleTranslation.getLLVMContext(); + + auto lowerArrayAttr = [&](mlir::ArrayAttr arrayAttr) { + llvm::SmallVector attrMDArgs; + for (mlir::Attribute attr : arrayAttr) { + int64_t value = mlir::cast(attr).getInt(); + attrMDArgs.push_back( + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::IntegerType::get(vmCtx, 32), llvm::APInt(32, value)))); + } + return llvm::MDNode::get(vmCtx, attrMDArgs); + }; + + if (auto workGroupSizeHint = clKernelMetadata.getWorkGroupSizeHint()) { + llvmFunc->setMetadata("work_group_size_hint", + lowerArrayAttr(workGroupSizeHint)); + } + + if (auto reqdWorkGroupSize = clKernelMetadata.getReqdWorkGroupSize()) { + llvmFunc->setMetadata("reqd_work_group_size", + lowerArrayAttr(reqdWorkGroupSize)); + } + + if (auto vecTypeHint = clKernelMetadata.getVecTypeHint()) { + auto hintQTy = vecTypeHint.getValue(); + bool isSignedInteger = *clKernelMetadata.getVecTypeHintSignedness(); + llvm::Metadata *attrMDArgs[] = { + llvm::ConstantAsMetadata::get( + llvm::UndefValue::get(moduleTranslation.convertType(hintQTy))), + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::IntegerType::get(vmCtx, 32), + llvm::APInt(32, (uint64_t)(isSignedInteger ? 1 : 0))))}; + llvmFunc->setMetadata("vec_type_hint", + llvm::MDNode::get(vmCtx, attrMDArgs)); + } + + if (auto intelReqdSubgroupSize = + clKernelMetadata.getIntelReqdSubGroupSize()) { + int64_t reqdSubgroupSize = intelReqdSubgroupSize.getInt(); + llvm::Metadata *attrMDArgs[] = { + llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(llvm::IntegerType::get(vmCtx, 32), + llvm::APInt(32, reqdSubgroupSize))), + }; + llvmFunc->setMetadata("intel_reqd_sub_group_size", + llvm::MDNode::get(vmCtx, attrMDArgs)); + } + } }; void registerCIRDialectTranslation(mlir::DialectRegistry ®istry) { diff --git a/clang/test/CIR/CodeGen/OpenCL/kernel-attributes.cl b/clang/test/CIR/CodeGen/OpenCL/kernel-attributes.cl new file mode 100644 index 000000000000..6badc7ce47ba --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenCL/kernel-attributes.cl @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fclangir -emit-cir -triple x86_64-unknown-linux-gnu %s -o %t.cir +// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR +// RUN: %clang_cc1 -fclangir -emit-llvm -triple x86_64-unknown-linux-gnu %s -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll --check-prefix=LLVM + +typedef unsigned int uint4 __attribute__((ext_vector_type(4))); + + +kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {} + +// CIR-DAG: #fn_attr[[KERNEL1:[0-9]*]] = {{.+}}cl.kernel_metadata = #cir.cl.kernel_metadata{{.+}} +// CIR-DAG: cir.func @kernel1{{.+}} extra(#fn_attr[[KERNEL1]]) + +// LLVM-DAG: define{{.*}}@kernel1(i32 {{[^%]*}}%0) {{[^{]+}} !reqd_work_group_size ![[MD1_REQD_WG:[0-9]+]] !vec_type_hint ![[MD1_VEC_TYPE:[0-9]+]] +// LLVM-DAG: [[MD1_VEC_TYPE]] = !{i32 undef, i32 1} +// LLVM-DAG: [[MD1_REQD_WG]] = !{i32 1, i32 2, i32 4} + + +kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {} + +// CIR-DAG: #fn_attr[[KERNEL2:[0-9]*]] = {{.+}}cl.kernel_metadata = #cir.cl.kernel_metadata, vec_type_hint_signedness = 0>{{.+}} +// CIR-DAG: cir.func @kernel2{{.+}} extra(#fn_attr[[KERNEL2]]) + +// LLVM-DAG: define{{.*}}@kernel2(i32 {{[^%]*}}%0) {{[^{]+}} !vec_type_hint ![[MD2_VEC_TYPE:[0-9]+]] !work_group_size_hint ![[MD2_WG_SIZE:[0-9]+]] +// LLVM-DAG: [[MD2_VEC_TYPE]] = !{<4 x i32> undef, i32 0} +// LLVM-DAG: [[MD2_WG_SIZE]] = !{i32 8, i32 16, i32 32} + + +kernel __attribute__((intel_reqd_sub_group_size(8))) void kernel3(int a) {} + +// CIR-DAG: #fn_attr[[KERNEL3:[0-9]*]] = {{.+}}cl.kernel_metadata = #cir.cl.kernel_metadata{{.+}} +// CIR-DAG: cir.func @kernel3{{.+}} extra(#fn_attr[[KERNEL3]]) + +// LLVM-DAG: define{{.*}}@kernel3(i32 {{[^%]*}}%0) {{[^{]+}} !intel_reqd_sub_group_size ![[MD3_INTEL:[0-9]+]] +// LLVM-DAG: [[MD3_INTEL]] = !{i32 8} diff --git a/clang/test/CIR/IR/invalid-opencl-vec-type-hint.cir b/clang/test/CIR/IR/invalid-opencl-vec-type-hint.cir new file mode 100644 index 000000000000..9e57ad793bf8 --- /dev/null +++ b/clang/test/CIR/IR/invalid-opencl-vec-type-hint.cir @@ -0,0 +1,7 @@ +// RUN: cir-opt %s -verify-diagnostics -allow-unregistered-dialect + +// expected-error@+1 {{vec_type_hint must be a type from the CIR or LLVM dialect}} +#fn_attr = #cir.cl.kernel_metadata< + vec_type_hint = !tensor<7xi8>, + vec_type_hint_signedness = 0 +> diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 4872fc862607..8f3db36232a1 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1172,3 +1172,48 @@ cir.func @address_space3(%p : !cir.ptr) { // expected- cir.func @address_space4(%p : !cir.ptr) { // expected-error {{invalid addrspace kind keyword: foobar}} cir.return } + +// ----- + +// expected-error@+1 {{metadata attribute without any field present is invalid}} +#fn_attr = #cir.cl.kernel_metadata<> + +// ----- + +// expected-error@+1 {{work_group_size_hint must have exactly 3 integer elements}} +#fn_attr = #cir.cl.kernel_metadata< + work_group_size_hint = [2 : i32] +> + +// ----- + +// expected-error@+1 {{reqd_work_group_size must have exactly 3 integer elements}} +#fn_attr = #cir.cl.kernel_metadata< + reqd_work_group_size = [3.0 : f32, 1.7 : f32] +> + +// ----- + +// expected-error@+1 {{vec_type_hint_signedness should be present if and only if vec_type_hint is set}} +#fn_attr = #cir.cl.kernel_metadata< + vec_type_hint_signedness = 1 +> + +// ----- + +!s32i = !cir.int + +// expected-error@+1 {{vec_type_hint_signedness should be present if and only if vec_type_hint is set}} +#fn_attr = #cir.cl.kernel_metadata< + vec_type_hint = !s32i +> + +// ----- + +!s32i = !cir.int + +// expected-error@+1 {{vec_type_hint_signedness must match the signedness of the vec_type_hint type}} +#fn_attr = #cir.cl.kernel_metadata< + vec_type_hint = !s32i, + vec_type_hint_signedness = 0 +>