clover/nir: add libclc lowering pass
This pass goes through all the functions in the shader, checks
if the matching function is in the clc spir-v library and inlines
the replacement from there it is.
v2 (daniels): Also copy variables from the libclc shader
v3 (jekstrand): Fix progress return, only run variable inlining once
v4 (jekstrand): Have function inlining also copy vars for us
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6035>
diff --git a/src/gallium/frontends/clover/meson.build b/src/gallium/frontends/clover/meson.build
index cbd31a6..64c77f5 100644
--- a/src/gallium/frontends/clover/meson.build
+++ b/src/gallium/frontends/clover/meson.build
@@ -85,7 +85,7 @@
libclnir = static_library(
'clnir',
- files('nir/invocation.cpp', 'nir/invocation.hpp'),
+ files('nir/invocation.cpp', 'nir/invocation.hpp', 'nir/nir_lower_libclc.c', 'nir/nir_lower_libclc.h'),
include_directories : [clover_incs, inc_mesa],
dependencies : idep_nir,
cpp_args : [clover_opencl_cpp_args, clover_spirv_cpp_args],
diff --git a/src/gallium/frontends/clover/nir/nir_lower_libclc.c b/src/gallium/frontends/clover/nir/nir_lower_libclc.c
new file mode 100644
index 0000000..9d17756
--- /dev/null
+++ b/src/gallium/frontends/clover/nir/nir_lower_libclc.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2019 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+/* Pass to find libclc functions from a clc library shader and inline
+ * them into a user shader.
+ * This pass should only be called once, but it also has to iterate
+ * itself to make sure all instances are lowered, before validation.
+ */
+#include "nir.h"
+#include "nir_builder.h"
+#include "nir_lower_libclc.h"
+
+static bool
+lower_clc_call_instr(nir_instr *instr, nir_builder *b,
+ const nir_shader *clc_shader,
+ struct hash_table *copy_vars)
+{
+ nir_call_instr *call = nir_instr_as_call(instr);
+ nir_function *func = NULL;
+ nir_foreach_function(function, clc_shader) {
+ if (strcmp(function->name, call->callee->name) == 0) {
+ func = function;
+ break;
+ }
+ }
+ if (!func || !func->impl) {
+ return false;
+ }
+
+ nir_ssa_def **params = rzalloc_array(b->shader, nir_ssa_def*, call->num_params);
+
+ for (unsigned i = 0; i < call->num_params; i++) {
+ params[i] = nir_ssa_for_src(b, call->params[i],
+ call->callee->params[i].num_components);
+ }
+
+ b->cursor = nir_instr_remove(&call->instr);
+ nir_inline_function_impl(b, func->impl, params, copy_vars);
+
+ ralloc_free(params);
+
+ return true;
+}
+
+static bool
+nir_lower_libclc_impl(nir_function_impl *impl,
+ const nir_shader *clc_shader,
+ struct hash_table *copy_vars)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+
+ bool progress = false;
+ nir_foreach_block_safe(block, impl) {
+ nir_foreach_instr_safe(instr, block) {
+ if (instr->type == nir_instr_type_call)
+ progress |= lower_clc_call_instr(instr, &b, clc_shader, copy_vars);
+ }
+ }
+
+ if (progress) {
+ nir_index_ssa_defs(impl);
+ nir_index_local_regs(impl);
+ nir_metadata_preserve(impl, nir_metadata_none);
+ } else {
+ nir_metadata_preserve(impl, nir_metadata_all);
+ }
+
+ return progress;
+}
+
+bool
+nir_lower_libclc(nir_shader *shader,
+ const nir_shader *clc_shader)
+{
+ void *ra_ctx = ralloc_context(NULL);
+ struct hash_table *copy_vars = _mesa_pointer_hash_table_create(ra_ctx);
+ bool progress = false, overall_progress = false;
+
+ /* do progress passes inside the pass */
+ do {
+ progress = false;
+ nir_foreach_function(function, shader) {
+ if (function->impl)
+ progress |= nir_lower_libclc_impl(function->impl, clc_shader, copy_vars);
+ }
+ overall_progress |= progress;
+ } while (progress);
+
+ ralloc_free(ra_ctx);
+
+ return overall_progress;
+}
diff --git a/src/gallium/frontends/clover/nir/nir_lower_libclc.h b/src/gallium/frontends/clover/nir/nir_lower_libclc.h
new file mode 100644
index 0000000..8db8d0a
--- /dev/null
+++ b/src/gallium/frontends/clover/nir/nir_lower_libclc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2019 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+#ifndef NIR_LOWER_LIBCLC_H
+#define NIR_LOWER_LIBCLC_H
+
+bool
+nir_lower_libclc(nir_shader *shader,
+ const nir_shader *clc_shader);
+
+#endif