From: Tanya Lattner Date: Mon, 9 Jul 2012 22:06:01 +0000 (+0000) Subject: Patch by Anton Lokhmotov to add OpenCL work group size attributes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0df579ec000ffe52e0cddf1e7ee5e50a55256835;p=clang Patch by Anton Lokhmotov to add OpenCL work group size attributes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159965 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 468d623eb7..99180e450e 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -578,6 +578,13 @@ def ReqdWorkGroupSize : InheritableAttr { UnsignedArgument<"ZDim">]; } +def WorkGroupSizeHint : InheritableAttr { + let Spellings = [GNU<"work_group_size_hint">]; + let Args = [UnsignedArgument<"XDim">, + UnsignedArgument<"YDim">, + UnsignedArgument<"ZDim">]; +} + def InitPriority : InheritableAttr { let Spellings = [GNU<"init_priority">]; let Args = [UnsignedArgument<"Priority">]; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 92bedbae3f..52641b86d6 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5523,6 +5523,9 @@ def warn_collection_expr_type : Warning< def err_invalid_conversion_between_ext_vectors : Error< "invalid conversion between ext-vector type %0 and %1">; +def warn_duplicate_attribute : Warning< + "attribute %0 is already applied with different parameters">; + // Type def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">; def warn_receiver_forward_class : Warning< diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 68593946f6..c40b42193f 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -252,6 +252,51 @@ void CodeGenFunction::EmitMCountInstrumentation() { Builder.CreateCall(MCountFn); } +void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, + llvm::Function *Fn) +{ + if (!FD->hasAttr()) + return; + + llvm::LLVMContext &Context = getLLVMContext(); + + llvm::SmallVector kernelMDArgs; + kernelMDArgs.push_back(Fn); + + if (FD->hasAttr()) { + llvm::SmallVector attrMDArgs; + attrMDArgs.push_back(llvm::MDString::get(Context, "work_group_size_hint")); + WorkGroupSizeHintAttr *attr = FD->getAttr(); + llvm::Type *iTy = llvm::IntegerType::get(Context, 32); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getXDim()))); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getYDim()))); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getZDim()))); + kernelMDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs)); + } + + if (FD->hasAttr()) { + llvm::SmallVector attrMDArgs; + attrMDArgs.push_back(llvm::MDString::get(Context, "reqd_work_group_size")); + ReqdWorkGroupSizeAttr *attr = FD->getAttr(); + llvm::Type *iTy = llvm::IntegerType::get(Context, 32); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getXDim()))); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getYDim()))); + attrMDArgs.push_back(llvm::ConstantInt::get(iTy, + llvm::APInt(32, (uint64_t)attr->getZDim()))); + kernelMDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs)); + } + + llvm::MDNode *kernelMDNode = llvm::MDNode::get(Context, kernelMDArgs); + llvm::NamedMDNode *OpenCLKernelMetadata = + CGM.getModule().getOrInsertNamedMetadata("opencl.kernels"); + OpenCLKernelMetadata->addOperand(kernelMDNode); +} + void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, @@ -280,14 +325,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, if (getContext().getLangOpts().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null(D)) - if (FD->hasAttr()) { - llvm::LLVMContext &Context = getLLVMContext(); - llvm::NamedMDNode *OpenCLMetadata = - CGM.getModule().getOrInsertNamedMetadata("opencl.kernels"); - - llvm::Value *Op = Fn; - OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Op)); - } + EmitOpenCLKernelMetadata(FD, Fn); } llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index a3d1acf591..b737a9ed7a 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1197,6 +1197,16 @@ private: llvm::BasicBlock *TerminateHandler; llvm::BasicBlock *TrapBB; + /// Add a kernel metadata node to the named metadata node 'opencl.kernels'. + /// In the kernel metadata node, reference the kernel function and metadata + /// nodes for its optional attribute qualifiers (OpenCL 1.1 6.7.2): + /// - A node for the work_group_size_hint(X,Y,Z) qualifier contains string + /// "work_group_size_hint", and three 32-bit integers X, Y and Z. + /// - A node for the reqd_work_group_size(X,Y,Z) qualifier contains string + /// "reqd_work_group_size", and three 32-bit integers X, Y and Z. + void EmitOpenCLKernelMetadata(const FunctionDecl *FD, + llvm::Function *Fn); + public: CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext=false); ~CodeGenFunction(); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 744d18bfd9..65fceaa93a 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2355,11 +2355,14 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context)); } -static void handleReqdWorkGroupSize(Sema &S, Decl *D, - const AttributeList &Attr) { +// Handles reqd_work_group_size and work_group_size_hint. +static void handleWorkGroupSize(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize + || Attr.getKind() == AttributeList::AT_WorkGroupSizeHint); + // Attribute has 3 arguments. - if (!checkAttributeNumArgs(S, Attr, 3)) - return; + if (!checkAttributeNumArgs(S, Attr, 3)) return; unsigned WGSize[3]; for (unsigned i = 0; i < 3; ++i) { @@ -2368,14 +2371,42 @@ static void handleReqdWorkGroupSize(Sema &S, Decl *D, if (E->isTypeDependent() || E->isValueDependent() || !E->isIntegerConstantExpr(ArgNum, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "reqd_work_group_size" << E->getSourceRange(); + << Attr.getName()->getName() << E->getSourceRange(); return; } WGSize[i] = (unsigned) ArgNum.getZExtValue(); } - D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, - WGSize[0], WGSize[1], - WGSize[2])); + + if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize + && D->hasAttr()) { + ReqdWorkGroupSizeAttr *A = D->getAttr(); + if (!(A->getXDim() == WGSize[0] && + A->getYDim() == WGSize[1] && + A->getZDim() == WGSize[2])) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << + Attr.getName(); + } + } + + if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint + && D->hasAttr()) { + WorkGroupSizeHintAttr *A = D->getAttr(); + if (!(A->getXDim() == WGSize[0] && + A->getYDim() == WGSize[1] && + A->getZDim() == WGSize[2])) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << + Attr.getName(); + } + } + + if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) + D->addAttr(::new (S.Context) + ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, + WGSize[0], WGSize[1], WGSize[2])); + else + D->addAttr(::new (S.Context) + WorkGroupSizeHintAttr(Attr.getRange(), S.Context, + WGSize[0], WGSize[1], WGSize[2])); } SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, @@ -4043,8 +4074,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_CFReturnsRetained: handleNSReturnsRetainedAttr(S, D, Attr); break; + case AttributeList::AT_WorkGroupSizeHint: case AttributeList::AT_ReqdWorkGroupSize: - handleReqdWorkGroupSize(S, D, Attr); break; + handleWorkGroupSize(S, D, Attr); break; case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; diff --git a/test/CodeGenOpenCL/kernel-attributes.cl b/test/CodeGenOpenCL/kernel-attributes.cl new file mode 100644 index 0000000000..014285ff2b --- /dev/null +++ b/test/CodeGenOpenCL/kernel-attributes.cl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm -O0 -o - %s | FileCheck %s + +typedef float float4 __attribute__((ext_vector_type(4))); + +kernel __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {} + +kernel __attribute__((work_group_size_hint(8,16,32))) void kernel2(float4 a) {} + +// CHECK: opencl.kernels = !{[[MDNODE0:![0-9]+]], [[MDNODE3:![0-9]+]]} + +// CHECK: [[MDNODE0]] = metadata !{void (i32)* @kernel1, metadata [[MDNODE2:![0-9]+]]} +// CHECK: [[MDNODE2]] = metadata !{metadata !"reqd_work_group_size", i32 1, i32 2, i32 4} +// CHECK: [[MDNODE3]] = metadata !{void (<4 x float>)* @kernel2, metadata [[MDNODE5:![0-9]+]]} +// CHECK: [[MDNODE5]] = metadata !{metadata !"work_group_size_hint", i32 8, i32 16, i32 32}