[cfe-dev] cfe-dev Digest, Vol 55, Issue 4
Bill Wendling
wendling at apple.com
Wed Jan 18 14:33:41 PST 2012
Hi Anton,
I just sent out a proposal for "module flags metadata". It's similar to what you're proposing here, but more general. If you think it's a benefit to what you would like to do or needs improvements, please send feedback. :-)
-bw
On Jan 3, 2012, at 9:54 AM, Anton Lokhmotov wrote:
> Hi Guy,
>
> Great to see new OpenCL patches coming in! I hope we'll work together on
> providing full support for OpenCL C in Clang/LLVM.
>
> We'd like to propose a different way of representing kernel function
> qualifiers using metadata.
>
> Example code:
>
> __kernel __attribute__(( work_group_size_hint(1,15,92) )) void hint_1_15_92(
> ) { }
>
> __kernel __attribute__(( reqd_work_group_size(12,72,256) )) void
> reqd_12_72_256( ) { }
>
> __kernel void no_attr( ) { }
>
> __kernel __attribute__(( reqd_work_group_size(12,72,256), vec_type_hint
> (float8))) void mix_attr( ) { }
>
> Example metadata:
>
> !opencl.kernels = !{!0, !2, !4, !5}
>
> !0 = metadata !{void ()* @hint_1_15_92, metadata !1}
> !1 = metadata !{metadata !"work_group_size_hint", i32 1, i32 15, i32 92}
> !2 = metadata !{void ()* @reqd_12_72_256, metadata !3}
> !3 = metadata !{metadata !"reqd_work_group_size", i32 12, i32 72, i32 256}
> !4 = metadata !{void ()* @no_attr}
> !5 = metadata !{void ()* @mix_attr, metadata !6, metadata !3}
> !6 = metadata !{metadata !"vec_type_hint", <8 x float> undef}
>
> The only named metadata node "opencl.kernels" references metadata objects
> for kernel functions. The first object provides the kernel signature (in
> fact, LLVM::Function*), and the following refer to optional kernel
> attributes. Note that the number and order of the optional attributes are
> unspecified, which allows future extensions. Note also that the metadata
> node !3 is shared between the 'mix_attr' and 'reqd_12_72_256' kernels.
>
> The most unusual feature here is representing the 'vec_type_hint' attribute
> not as string metadata (e.g. "float8"), but as an undefined value of the
> corresponding LLVM type. This avoids the need to parse the metadata string
> in the backend to get the type of this attribute.
>
> The following function implements emitting this representation:
>
> void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
> llvm::Function *Fn)
> {
> if (FD->hasAttr<OpenCLKernelAttr>()) {
> llvm::SmallVector <llvm::Value*, 5> MDArgs;
> llvm::LLVMContext &Context = getLLVMContext();
> MDArgs.push_back(Fn);
>
> if (FD->hasAttr<VecTypeHintAttr>()) {
> llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
> attrMDArgs.
> push_back(llvm::MDString::get(Context, "vec_type_hint"));
>
> llvm::Type *type_hint =
> CGM.getTypes().
> ConvertType(FD->getAttr<VecTypeHintAttr>()->getTypeHint());
> attrMDArgs.push_back(llvm::UndefValue::get(type_hint));
> MDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs));
> }
>
> if (FD->hasAttr<WorkGroupSizeHintAttr>()) {
> llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
> attrMDArgs.
> push_back(llvm::MDString::get(Context, "work_group_size_hint"));
> llvm::Type *iTy = llvm::IntegerType::get(Context, 32);
> WorkGroupSizeHintAttr *attr = FD->getAttr<WorkGroupSizeHintAttr>();
> 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())));
> MDArgs.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"));
> llvm::Type *iTy = llvm::IntegerType::get(Context, 32);
> ReqdWorkGroupSizeAttr *attr = FD->getAttr<ReqdWorkGroupSizeAttr>();
> 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())));
> MDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs));
> }
>
> llvm::MDNode *kernelMDNode = llvm::MDNode::get(Context, MDArgs);
> llvm::NamedMDNode *OpenCLMetadata =
> CGM.getModule().getOrInsertNamedMetadata("opencl.kernels");
>
> OpenCLMetadata->addOperand(kernelMDNode);
> }
> }
>
> What do you think?
>
> Best wishes,
> Anton.
>
>
> P.S. Please also find some niggles below.
>
> +/// DummyTypeExpr - Not a real expression, but a simple container for a
> type
> +/// Should be used to pass type arguments to attributes, like OpenCL's
> +/// vec_type_hint
>
> Please terminate sentences with dots.
>
> + /// vec_type_hint(...)
> + ExprResult ActOnDummyTypeExpr(ParsedType ParsedTy);
> +
> Either expand or remove the comment?
>
> - } else {
> + } if (S.getLangOptions().OpenCL) {
>
> Do you mean "} else if (S.getLangOptions().OpenCL) {" ???
>
> + if(S.getLangOptions().OpenCL && ASIdx == LangAS::opencl_constant) {
> + Type = S.Context.getConstType(Type);
> + }
> Remove curly braces?
>
>
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
More information about the cfe-dev
mailing list