From aadd13408147c06b69af61c5871aab3dd6d3fa21 Mon Sep 17 00:00:00 2001 From: Serge Martin Date: Sun, 23 Aug 2020 08:50:54 +0200 Subject: [PATCH] clover: add CL_KERNEL_ATTRIBUTES for clGetKernelInfo Reviewed-by: Francisco Jerez Part-of: --- src/gallium/frontends/clover/api/kernel.cpp | 4 + src/gallium/frontends/clover/core/module.cpp | 1 + src/gallium/frontends/clover/core/module.hpp | 12 ++- .../frontends/clover/llvm/codegen/common.cpp | 36 ++++++++- src/gallium/frontends/clover/llvm/metadata.hpp | 88 ++++++++++++++++++++++ src/gallium/frontends/clover/nir/invocation.cpp | 2 +- src/gallium/frontends/clover/spirv/invocation.cpp | 2 +- src/gallium/frontends/clover/util/algorithm.hpp | 28 +++++++ 8 files changed, 166 insertions(+), 7 deletions(-) diff --git a/src/gallium/frontends/clover/api/kernel.cpp b/src/gallium/frontends/clover/api/kernel.cpp index 501e267..773d8e1 100644 --- a/src/gallium/frontends/clover/api/kernel.cpp +++ b/src/gallium/frontends/clover/api/kernel.cpp @@ -134,6 +134,10 @@ clGetKernelInfo(cl_kernel d_kern, cl_kernel_info param, buf.as_scalar() = desc(kern.program()); break; + case CL_KERNEL_ATTRIBUTES: + buf.as_string() = find(name_equals(kern.name()), kern.program().symbols()).attributes; + break; + default: throw error(CL_INVALID_VALUE); } diff --git a/src/gallium/frontends/clover/core/module.cpp b/src/gallium/frontends/clover/core/module.cpp index a6c5b98..aa7d3d0 100644 --- a/src/gallium/frontends/clover/core/module.cpp +++ b/src/gallium/frontends/clover/core/module.cpp @@ -190,6 +190,7 @@ namespace { static void proc(S &s, QT &x) { _proc(s, x.name); + _proc(s, x.attributes); _proc(s, x.section); _proc(s, x.offset); _proc(s, x.args); diff --git a/src/gallium/frontends/clover/core/module.hpp b/src/gallium/frontends/clover/core/module.hpp index 1d938df..6117f7f 100644 --- a/src/gallium/frontends/clover/core/module.hpp +++ b/src/gallium/frontends/clover/core/module.hpp @@ -128,12 +128,16 @@ namespace clover { }; struct symbol { - symbol(const std::string &name, resource_id section, - size_t offset, const std::vector &args) : - name(name), section(section), offset(offset), args(args) { } - symbol() : name(), section(0), offset(0), args() { } + symbol(const std::string &name, const std::string &attributes, + resource_id section, size_t offset, + const std::vector &args) : + name(name), attributes(attributes), + section(section), + offset(offset), args(args) { } + symbol() : name(), attributes(), section(0), offset(0), args() { } std::string name; + std::string attributes; resource_id section; size_t offset; std::vector args; diff --git a/src/gallium/frontends/clover/llvm/codegen/common.cpp b/src/gallium/frontends/clover/llvm/codegen/common.cpp index 698f77c..0cb7148 100644 --- a/src/gallium/frontends/clover/llvm/codegen/common.cpp +++ b/src/gallium/frontends/clover/llvm/codegen/common.cpp @@ -103,6 +103,39 @@ namespace { cl_address_qualifier, cl_access_qualifier); } + std::string + kernel_attributes(const Module &mod, const std::string &kernel_name) { + std::vector attributes; + + const Function &f = *mod.getFunction(kernel_name); + + auto vec_type_hint = get_type_kernel_metadata(f, "vec_type_hint"); + if (!vec_type_hint.empty()) + attributes.emplace_back("vec_type_hint(" + vec_type_hint + ")"); + + auto work_group_size_hint = get_uint_vector_kernel_metadata(f, "work_group_size_hint"); + if (!work_group_size_hint.empty()) { + std::string s = "work_group_size_hint("; + s += detokenize(work_group_size_hint, ","); + s += ")"; + attributes.emplace_back(s); + } + + auto reqd_work_group_size = get_uint_vector_kernel_metadata(f, "reqd_work_group_size"); + if (!reqd_work_group_size.empty()) { + std::string s = "reqd_work_group_size("; + s += detokenize(reqd_work_group_size, ","); + s += ")"; + attributes.emplace_back(s); + } + + auto nosvm = get_str_kernel_metadata(f, "nosvm"); + if (!nosvm.empty()) + attributes.emplace_back("nosvm"); + + return detokenize(attributes, " "); + } + std::vector make_kernel_args(const Module &mod, const std::string &kernel_name, const clang::CompilerInstance &c) { @@ -251,7 +284,8 @@ clover::llvm::build_module_common(const Module &mod, get_kernels(mod))) { const ::std::string name(llvm_name); if (offsets.count(name)) - m.syms.emplace_back(name, 0, offsets.at(name), + m.syms.emplace_back(name, kernel_attributes(mod, name), + 0, offsets.at(name), make_kernel_args(mod, name, c)); } diff --git a/src/gallium/frontends/clover/llvm/metadata.hpp b/src/gallium/frontends/clover/llvm/metadata.hpp index 8519d98..be97a00 100644 --- a/src/gallium/frontends/clover/llvm/metadata.hpp +++ b/src/gallium/frontends/clover/llvm/metadata.hpp @@ -56,6 +56,94 @@ namespace clover { } /// + /// Extract the string metadata node \p name. + /// + inline std::string + get_str_kernel_metadata(const ::llvm::Function &f, + const std::string &name) { + auto operands = detail::get_kernel_metadata_operands(f, name); + if (operands.size()) { + return ::llvm::cast< ::llvm::MDString>( + detail::get_kernel_metadata_operands(f, name)[0]) + ->getString().str(); + } else { + return ""; + } + } + + /// + /// Extract the string metadata node \p name. + /// + inline std::vector + get_uint_vector_kernel_metadata(const ::llvm::Function &f, + const std::string &name) { + auto operands = detail::get_kernel_metadata_operands(f, name); + if (operands.size()) { + return map([=](const ::llvm::MDOperand& o) { + auto value = ::llvm::cast< ::llvm::ConstantAsMetadata>(o) + ->getValue(); + return ::llvm::cast< ::llvm::ConstantInt>(value) + ->getLimitedValue(UINT_MAX); + }, operands); + } else { + return {}; + } + } + + /// + /// Extract the string metadata node \p name. + /// + inline std::string + get_type_kernel_metadata(const ::llvm::Function &f, + const std::string &name) { + auto operands = detail::get_kernel_metadata_operands(f, name); + if (operands.size()) { + auto value = ::llvm::cast< ::llvm::ConstantAsMetadata>(operands[0]) + ->getValue(); + auto type = ::llvm::cast< ::llvm::UndefValue>(value) + ->getType(); + + value = ::llvm::cast< ::llvm::ConstantAsMetadata>(operands[1]) + ->getValue(); + bool is_signed = ::llvm::cast< ::llvm::ConstantInt>(value) + ->getLimitedValue(UINT_MAX); + + std::string data; + if (type->isIntOrIntVectorTy()) { + if (!is_signed) + data = "unsigned "; + + const auto size = type->getScalarSizeInBits(); + switch(size) { + case 8: + data += "char"; + break; + case 16: + data += "short"; + break; + case 32: + data += "int"; + break; + case 64: + data += "long"; + break; + } + if (type->isVectorTy()) + data += std::to_string(((::llvm::VectorType*)type)->getNumElements()); + + } else { + ::llvm::raw_string_ostream os { data }; + type->print(os); + os.flush(); + } + + return data; + } else { + return ""; + } + } + + /// /// Extract the string metadata node \p name corresponding to the kernel /// argument given by \p arg. /// diff --git a/src/gallium/frontends/clover/nir/invocation.cpp b/src/gallium/frontends/clover/nir/invocation.cpp index c0bf646..991ebd6 100644 --- a/src/gallium/frontends/clover/nir/invocation.cpp +++ b/src/gallium/frontends/clover/nir/invocation.cpp @@ -390,7 +390,7 @@ module clover::nir::spirv_to_nir(const module &mod, const device &dev, reinterpret_cast(&header) + sizeof(header)); text.data.insert(text.data.end(), blob.data, blob.data + blob.size); - m.syms.emplace_back(sym.name, section_id, 0, args); + m.syms.emplace_back(sym.name, std::string(), section_id, 0, args); m.secs.push_back(text); section_id++; } diff --git a/src/gallium/frontends/clover/spirv/invocation.cpp b/src/gallium/frontends/clover/spirv/invocation.cpp index 9b33e66..eaf99fa 100644 --- a/src/gallium/frontends/clover/spirv/invocation.cpp +++ b/src/gallium/frontends/clover/spirv/invocation.cpp @@ -346,7 +346,7 @@ namespace { case SpvOpFunctionEnd: if (kernel_name.empty()) break; - m.syms.emplace_back(kernel_name, 0, kernel_nb, args); + m.syms.emplace_back(kernel_name, std::string(), 0, kernel_nb, args); ++kernel_nb; kernel_name.clear(); args.clear(); diff --git a/src/gallium/frontends/clover/util/algorithm.hpp b/src/gallium/frontends/clover/util/algorithm.hpp index 1658458..0841dd1 100644 --- a/src/gallium/frontends/clover/util/algorithm.hpp +++ b/src/gallium/frontends/clover/util/algorithm.hpp @@ -213,6 +213,34 @@ namespace clover { r.erase(i, e); } + + /// + /// Build a \a sep separated string from a vector of T + /// + template + std::string + detokenize(const std::vector &ss, const std::string &sep) { + std::string r; + + for (const auto &s : ss) + r += (r.empty() ? "" : sep) + std::to_string(s); + + return r; + } + + /// + /// Build a \a sep separated string from a vector of string + /// + template <> + inline std::string + detokenize(const std::vector &ss, const std::string &sep) { + std::string r; + + for (const auto &s : ss) + r += (r.empty() || s.empty() ? "" : sep) + s; + + return r; + } } #endif -- 2.7.4