Patch by Anton Lokhmotov to add OpenCL work group size attributes.

llvm-svn: 159965
This commit is contained in:
Tanya Lattner 2012-07-09 22:06:01 +00:00
parent 17709ae8d9
commit bcffcdfd18
6 changed files with 121 additions and 17 deletions

View File

@ -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">];

View File

@ -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<

View File

@ -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);

View File

@ -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();

View File

@ -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;

View 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}