Mesa (main): nir/opt_memcpy: Add another case for function_temp
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Jun 24 19:53:13 UTC 2022
Module: Mesa
Branch: main
Commit: 7c127ca0188a837b810f7269e7bb648523715c46
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=7c127ca0188a837b810f7269e7bb648523715c46
Author: Jason Ekstrand <jason.ekstrand at intel.com>
Date: Mon Mar 1 21:25:11 2021 -0600
nir/opt_memcpy: Add another case for function_temp
Reviewed-by: Kristian H. Kristensen <hoegsberg at gmail.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand at collabora.com> (1.5 years later)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13166>
---
src/compiler/nir/nir_opt_memcpy.c | 45 +++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/src/compiler/nir/nir_opt_memcpy.c b/src/compiler/nir/nir_opt_memcpy.c
index d022e5811ab..d984c131e28 100644
--- a/src/compiler/nir/nir_opt_memcpy.c
+++ b/src/compiler/nir/nir_opt_memcpy.c
@@ -123,7 +123,8 @@ type_is_tightly_packed(const struct glsl_type *type, unsigned *size_out)
}
static bool
-try_lower_memcpy(nir_builder *b, nir_intrinsic_instr *cpy)
+try_lower_memcpy(nir_builder *b, nir_intrinsic_instr *cpy,
+ struct set *complex_vars)
{
nir_deref_instr *dst = nir_src_as_deref(cpy->src[0]);
nir_deref_instr *src = nir_src_as_deref(cpy->src[1]);
@@ -192,6 +193,26 @@ try_lower_memcpy(nir_builder *b, nir_intrinsic_instr *cpy)
return true;
}
+ /* If we can get at the variable AND the only complex use of that variable
+ * is as a memcpy destination, then we don't have to care about any empty
+ * space in the variable. In particular, we know that the variable is never
+ * cast to any other type and it's never used as a memcpy source so nothing
+ * can see any padding bytes. This holds even if some other memcpy only
+ * writes to part of the variable.
+ */
+ if (dst->deref_type == nir_deref_type_var &&
+ dst->modes == nir_var_function_temp &&
+ _mesa_set_search(complex_vars, dst->var) == NULL &&
+ glsl_get_explicit_size(dst->type, false) <= size) {
+ b->cursor = nir_instr_remove(&cpy->instr);
+ src = nir_build_deref_cast(b, &src->dest.ssa,
+ src->modes, dst->type, 0);
+ nir_copy_deref_with_access(b, dst, src,
+ nir_intrinsic_dst_access(cpy),
+ nir_intrinsic_src_access(cpy));
+ return true;
+ }
+
if (src->modes == nir_var_function_temp &&
type_is_tightly_packed(src->type, &type_size) &&
type_size == size) {
@@ -215,6 +236,24 @@ opt_memcpy_impl(nir_function_impl *impl)
nir_builder b;
nir_builder_init(&b, impl);
+ struct set *complex_vars = _mesa_pointer_set_create(NULL);
+
+ nir_foreach_block(block, impl) {
+ nir_foreach_instr(instr, block) {
+ if (instr->type != nir_instr_type_deref)
+ continue;
+
+ nir_deref_instr *deref = nir_instr_as_deref(instr);
+ if (deref->deref_type != nir_deref_type_var)
+ continue;
+
+ nir_deref_instr_has_complex_use_options opts =
+ nir_deref_instr_has_complex_use_allow_memcpy_dst;
+ if (nir_deref_instr_has_complex_use(deref, opts))
+ _mesa_set_add(complex_vars, deref->var);
+ }
+ }
+
nir_foreach_block(block, impl) {
nir_foreach_instr_safe(instr, block) {
if (instr->type != nir_instr_type_intrinsic)
@@ -229,13 +268,15 @@ opt_memcpy_impl(nir_function_impl *impl)
while (opt_memcpy_deref_cast(cpy, &cpy->src[1]))
progress = true;
- if (try_lower_memcpy(&b, cpy)) {
+ if (try_lower_memcpy(&b, cpy, complex_vars)) {
progress = true;
continue;
}
}
}
+ _mesa_set_destroy(complex_vars, NULL);
+
if (progress) {
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance);
More information about the mesa-commit
mailing list