Patch by Anton Lokhmotov to add OpenCL work group size attributes.
llvm-svn: 159965
This commit is contained in:
parent
17709ae8d9
commit
bcffcdfd18
@ -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">];
|
||||
|
||||
@ -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<
|
||||
|
||||
@ -252,6 +252,51 @@ void CodeGenFunction::EmitMCountInstrumentation() {
|
||||
Builder.CreateCall(MCountFn);
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
|
||||
llvm::Function *Fn)
|
||||
{
|
||||
if (!FD->hasAttr<OpenCLKernelAttr>())
|
||||
return;
|
||||
|
||||
llvm::LLVMContext &Context = getLLVMContext();
|
||||
|
||||
llvm::SmallVector <llvm::Value*, 5> kernelMDArgs;
|
||||
kernelMDArgs.push_back(Fn);
|
||||
|
||||
if (FD->hasAttr<WorkGroupSizeHintAttr>()) {
|
||||
llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
|
||||
attrMDArgs.push_back(llvm::MDString::get(Context, "work_group_size_hint"));
|
||||
WorkGroupSizeHintAttr *attr = FD->getAttr<WorkGroupSizeHintAttr>();
|
||||
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<ReqdWorkGroupSizeAttr>()) {
|
||||
llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
|
||||
attrMDArgs.push_back(llvm::MDString::get(Context, "reqd_work_group_size"));
|
||||
ReqdWorkGroupSizeAttr *attr = FD->getAttr<ReqdWorkGroupSizeAttr>();
|
||||
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<FunctionDecl>(D))
|
||||
if (FD->hasAttr<OpenCLKernelAttr>()) {
|
||||
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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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>()) {
|
||||
ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>();
|
||||
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>()) {
|
||||
WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>();
|
||||
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;
|
||||
|
||||
14
clang/test/CodeGenOpenCL/kernel-attributes.cl
Normal file
14
clang/test/CodeGenOpenCL/kernel-attributes.cl
Normal file
@ -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}
|
||||
Loading…
x
Reference in New Issue
Block a user