nir: Add pass to combine adjacent scoped memory barriers

SPIR-V generates very granular barriers, however HW and backends might
not necessarily take advantage of those.  This pass provides a general
mechanism to combine such barriers.

Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3224>
This commit is contained in:
Caio Marcelo de Oliveira Filho
2020-02-21 10:53:05 -08:00
committed by Marge Bot
parent d31a8ed8fd
commit bf432cd831
4 changed files with 95 additions and 0 deletions
+1
View File
@@ -296,6 +296,7 @@ NIR_FILES = \
nir/nir_move_vec_src_uses_to_dest.c \
nir/nir_normalize_cubemap_coords.c \
nir/nir_opt_access.c \
nir/nir_opt_barriers.c \
nir/nir_opt_combine_stores.c \
nir/nir_opt_comparison_pre.c \
nir/nir_opt_conditional_discard.c \
+1
View File
@@ -177,6 +177,7 @@ files_libnir = files(
'nir_move_vec_src_uses_to_dest.c',
'nir_normalize_cubemap_coords.c',
'nir_opt_access.c',
'nir_opt_barriers.c',
'nir_opt_combine_stores.c',
'nir_opt_comparison_pre.c',
'nir_opt_conditional_discard.c',
+11
View File
@@ -4240,6 +4240,17 @@ bool nir_opt_algebraic_before_ffma(nir_shader *shader);
bool nir_opt_algebraic_late(nir_shader *shader);
bool nir_opt_constant_folding(nir_shader *shader);
/* Try to combine a and b into a. Return true if combination was possible,
* which will result in b being removed by the pass. Return false if
* combination wasn't possible.
*/
typedef bool (*nir_combine_memory_barrier_cb)(
nir_intrinsic_instr *a, nir_intrinsic_instr *b, void *data);
bool nir_opt_combine_memory_barriers(nir_shader *shader,
nir_combine_memory_barrier_cb combine_cb,
void *data);
bool nir_opt_combine_stores(nir_shader *shader, nir_variable_mode modes);
bool nir_copy_prop(nir_shader *shader);
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright © 2020 Intel Corporation
*
* 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.
*/
#include "nir.h"
static bool
nir_opt_combine_memory_barriers_impl(
nir_function_impl *impl, nir_combine_memory_barrier_cb combine_cb, void *data)
{
bool progress = false;
nir_foreach_block(block, impl) {
nir_intrinsic_instr *prev = NULL;
nir_foreach_instr_safe(instr, block) {
if (instr->type != nir_instr_type_intrinsic) {
prev = NULL;
continue;
}
nir_intrinsic_instr *current = nir_instr_as_intrinsic(instr);
if (current->intrinsic != nir_intrinsic_scoped_memory_barrier) {
prev = NULL;
continue;
}
if (prev && combine_cb(prev, current, data)) {
nir_instr_remove(&current->instr);
progress = true;
} else {
prev = current;
}
}
}
if (progress) {
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_live_ssa_defs);
}
return progress;
}
/* Combine adjacent scoped memory barriers. */
bool
nir_opt_combine_memory_barriers(
nir_shader *shader, nir_combine_memory_barrier_cb combine_cb, void *data)
{
assert(combine_cb);
bool progress = false;
nir_foreach_function(function, shader) {
if (function->impl &&
nir_opt_combine_memory_barriers_impl(function->impl, combine_cb, data)) {
progress = true;
}
}
return progress;
}