clover: add CL_KERNEL_ATTRIBUTES for clGetKernelInfo
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4974>
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 @@
buf.as_scalar<cl_program>() = 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 @@
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 @@
};
struct symbol {
- symbol(const std::string &name, resource_id section,
- size_t offset, const std::vector<argument> &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<argument> &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<argument> 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 @@
cl_address_qualifier, cl_access_qualifier);
}
+ std::string
+ kernel_attributes(const Module &mod, const std::string &kernel_name) {
+ std::vector<std::string> 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<module::argument>
make_kernel_args(const Module &mod, const std::string &kernel_name,
const clang::CompilerInstance &c) {
@@ -251,7 +284,8 @@
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 @@
}
///
+ /// 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<size_t>
+ 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 @@
reinterpret_cast<const char *>(&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 @@
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 @@
r.erase(i, e);
}
+
+ ///
+ /// Build a \a sep separated string from a vector of T
+ ///
+ template<typename T>
+ std::string
+ detokenize(const std::vector<T> &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<std::string> &ss, const std::string &sep) {
+ std::string r;
+
+ for (const auto &s : ss)
+ r += (r.empty() || s.empty() ? "" : sep) + s;
+
+ return r;
+ }
}
#endif